Release coccinelle-0.2.0rc1
[bpt/coccinelle.git] / parsing_cocci / parser_cocci_menhir.mly
1 %{
2
3 (* Not clear how to allow function declarations to specify a return type
4 and how to allow both to be specified as static, because they are in
5 different rules. The rules seem to have to be combined, which would allow
6 functions to be declared as local variables *)
7
8 (* Not clear how to let a function have a parameter of type void. At the
9 moment, void is allowed to be the type of a variable, which is wrong, and a
10 parameter needs both a type and an identifier *)
11 module Ast0 = Ast0_cocci
12 module Ast = Ast_cocci
13 module P = Parse_aux
14 %}
15
16 %token EOF
17
18 %token TIdentifier TExpression TStatement TFunction TLocal TType TParameter
19 %token TIdExpression TInitialiser
20 %token Tlist TFresh TConstant TError TWords TWhy0 TPlus0 TBang0
21 %token TPure TContext TGenerated
22 %token TTypedef TDeclarer TIterator TName TPosition TPosAny
23 %token TUsing TDisable TExtends TDepends TOn TEver TNever TExists TForall
24 %token TScript TInitialize TFinalize TNothing TVirtual
25 %token<string> TRuleName
26
27 %token<Data.clt> Tchar Tshort Tint Tdouble Tfloat Tlong
28 %token<Data.clt> Tvoid Tstruct Tunion Tenum
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
37 %token <string * Data.clt> TIdent TTypeId TDeclarerId TIteratorId TPragma
38
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
47
48 %token TArob TArobArob TPArob
49 %token <string> TScriptData
50
51 %token <Data.clt> TEllipsis TOEllipsis TCEllipsis TPOEllipsis TPCEllipsis
52 %token <Data.clt> TWhen TWhenTrue TWhenFalse TAny TStrict TLineEnd
53
54 %token <Data.clt> TWhy TDotDot TBang TOPar TOPar0
55 %token <Data.clt> TMid0 TCPar TCPar0
56
57 %token <string> TPathIsoFile
58 %token <string * Data.clt> TIncludeL TIncludeNL
59 %token <Data.clt * token> TDefine
60 %token <Data.clt * token * int * int> TDefineParam
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
71 %token <Data.clt> TAnd
72 %token <Data.clt> TEqEq TNotEq TTildeEq TTildeExclEq
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
79 %token <Data.clt> TOBrace TCBrace TOInit
80 %token <Data.clt> TOCro TCCro
81
82 %token <Data.clt> TPtrOp
83
84 %token TMPtVirg TCppConcatOp
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
101 %left TAnd
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
124 %type <Data.incl_iso list> include_main
125
126 %start iso_rule_name
127 %type <Ast_cocci.rulename>
128 iso_rule_name
129
130 %start rule_name
131 %type <Ast_cocci.rulename>
132 rule_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
150 reinit: { }
151 minus_main: minus_body EOF { $1 } | m=minus_body TArobArob { m }
152 | m=minus_body TArob { m }
153 plus_main: plus_body EOF { $1 } | p=plus_body TArobArob { p }
154 | p=plus_body TArob { p }
155 minus_exp_main: minus_exp_body EOF { $1 } | m=minus_exp_body TArobArob { m }
156 | m=minus_exp_body TArob { m }
157 plus_exp_main: plus_exp_body EOF { $1 } | p=plus_exp_body TArobArob { p }
158 | p=plus_exp_body TArob { p }
159 meta_main: m=metadec { m (!Ast0.rule_name) }
160 iso_meta_main: m=metadec { m "" }
161
162 /*****************************************************************************
163 *
164 *
165 *****************************************************************************/
166
167 pure:
168 TPure { Ast0.Pure }
169 | TContext { Ast0.Context }
170 | TPure TContext { Ast0.PureContext }
171 | TContext TPure { Ast0.PureContext }
172 | /* empty */ { Ast0.Impure }
173
174 iso_rule_name:
175 nm=pure_ident TArob { P.make_iso_rule_name_result (P.id2name nm) }
176
177 rule_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 }
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 }
186 | TScript TDotDot lang=pure_ident d=depends TArob
187 { P.make_script_rule_name_result lang d }
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 }
192
193 extends:
194 /* empty */ { () }
195 | TExtends parent=TRuleName
196 { !Data.install_bindings (parent) }
197
198 depends:
199 /* empty */ { Ast.NoDep }
200 | TDepends TOn parents=dep { parents }
201
202 dep:
203 pnrule { $1 }
204 | dep TAndLog dep { Ast.AndDep($1, $3) }
205 | dep TOrLog dep { Ast.OrDep ($1, $3) }
206
207 pnrule:
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
214 choose_iso:
215 TUsing separated_nonempty_list(TComma,TString) { List.map P.id2name $2 }
216
217 disable:
218 TDisable separated_nonempty_list(TComma,pure_ident) { List.map P.id2name $2 }
219
220 exists:
221 TExists { Ast.Exists }
222 | TForall { Ast.Forall }
223 | { Ast.Undetermined }
224
225 is_expression: // for more flexible parsing of top level expressions
226 { false }
227 | TExpression { true }
228
229 include_main:
230 list(incl) TArob { $1 }
231 | list(incl) TArobArob { $1 }
232
233 incl:
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) }
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) }
244
245 metadec:
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 }
249 | kindfn=metakind_fresh ids=comma_list(pure_ident_or_meta_ident_with_seed)
250 TMPtVirg
251 { P.create_fresh_metadec kindfn ids }
252 | ar=arity ispure=pure
253 kindfn=metakind_atomic
254 ids=comma_list(pure_ident_or_meta_ident_with_idconstraint(re_or_not_eqid))
255 TMPtVirg
256 { P.create_metadec_with_constraints ar ispure kindfn ids }
257 | ar=arity ispure=pure
258 kindfn=metakind_atomic_expi
259 ids=comma_list(pure_ident_or_meta_ident_with_econstraint(re_or_not_eqe))
260 TMPtVirg
261 { P.create_metadec_with_constraints ar ispure kindfn ids }
262 | ar=arity ispure=pure
263 kindfn=metakind_atomic_expe
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 }
266 | ar=arity TPosition a=option(TPosAny)
267 ids=comma_list(pure_ident_or_meta_ident_with_x_eq(not_pos)) TMPtVirg
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 =
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
277 P.create_metadec_with_constraints ar false kindfn ids }
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
297 %inline metakind_fresh:
298 TFresh TIdentifier
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
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
319 !Data.add_type_meta name pure; tok) }
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) }
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
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
414 !Data.add_exp_meta None name (Ast0.NotExpCstrt constraints) pure; tok) }
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
425 Type_cocci.BaseType(Type_cocci.IntType) -> true
426 | Type_cocci.BaseType(Type_cocci.ShortType) -> true
427 | Type_cocci.BaseType(Type_cocci.LongType) -> true
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
434 !Data.add_exp_meta ty name (Ast0.NotExpCstrt constraints) pure; tok)
435 }
436
437
438 meta_exp_type:
439 t=typedef_ctype
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
446 arity: TBang0 { Ast.UNIQUE }
447 | TWhy0 { Ast.OPT }
448 | TPlus0 { Ast.MULTI }
449 | /* empty */ { Ast.NONE }
450
451 /* ---------------------------------------------------------------------- */
452
453 %inline
454 signable_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
480 non_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
506 all_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
514 ctype:
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 */
527 typedef_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 /* ---------------------------------------------------------------------- */
536
537 struct_or_union:
538 s=Tstruct { P.clt2mcode Ast.Struct s }
539 | u=Tunion { P.clt2mcode Ast.Union u }
540
541 struct_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))] }
546 | t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
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
560 struct_decl_list:
561 struct_decl_list_start { Ast0.wrap(Ast0.DOTS($1)) }
562
563 struct_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
569 continue_struct_decl_list:
570 /* empty */ { [] }
571 | struct_decl struct_decl_list_start { $1@$2 }
572 | struct_decl { $1 }
573
574
575 /*****************************************************************************/
576
577 /* have to inline everything to avoid conflicts? switch to proper
578 declarations, statements, and expressions for the subterms */
579
580 minus_body:
581 f=loption(filespec)
582 b=loption(minus_start)
583 /*ew=loption(error_words)*/
584 { match f@b(*@ew*) with
585 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
586 | code -> Top_level.top_level code }
587
588 plus_body:
589 f=loption(filespec)
590 b=loption(plus_start)
591 /*ew=loption(error_words)*/
592 { Top_level.top_level (f@b(*@ew*)) }
593
594 minus_exp_body:
595 f=loption(filespec)
596 b=top_eexpr
597 /*ew=loption(error_words)*/
598 { match f@[b](*@ew*) with
599 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
600 | code -> Top_level.top_level code }
601
602 plus_exp_body:
603 f=loption(filespec)
604 b=top_eexpr
605 /*ew=loption(error_words)*/
606 { Top_level.top_level (f@[b](*@ew*)) }
607
608 filespec:
609 TMinusFile TPlusFile
610 { [Ast0.wrap
611 (Ast0.FILEINFO(P.id2mcode $1,
612 P.id2mcode $2))] }
613
614 includes:
615 TIncludeL
616 { Ast0.wrap
617 (Ast0.Include(P.clt2mcode "#include"
618 (P.drop_pos (P.drop_aft (P.id2clt $1))),
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
628 (Ast0.Include(P.clt2mcode "#include"
629 (P.drop_pos (P.drop_aft (P.id2clt $1))),
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
651 defineop:
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
670 { let (clt,ident,parenoff,parencol) = $1 in
671 (* clt is the start of the #define itself *)
672 let (arity,line,lline,offset,col,strbef,straft,pos) = clt in
673 let lp =
674 P.clt2mcode "("
675 (arity,line,lline,parenoff,parencol,[],[],Ast0.NoMetaPos) in
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
693 define_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
700 define_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
709 dp_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
718 define_param_list_option: define_param_list { $1 }
719 | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
720
721 /*****************************************************************************/
722
723 funproto:
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)) }
733
734 fundecl:
735 f=fninfo
736 TFunDecl i=func_ident lp=TOPar d=decl_list(decl) rp=TCPar
737 lb=TOBrace b=fun_start rb=TCBrace
738 { P.verify_parameter_declarations (Ast0.undots d);
739 Ast0.wrap(Ast0.FunDecl((Ast0.default_info(),Ast0.context_befaft()),
740 f, i,
741 P.clt2mcode "(" lp, d,
742 P.clt2mcode ")" rp,
743 P.clt2mcode "{" lb, b,
744 P.clt2mcode "}" rb)) }
745
746 fninfo:
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 }
754 | t=ctype r=fninfo_nt { (Ast0.FType(t))::r }
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
766 fninfo_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
785 storage:
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
791 decl: t=ctype i=ident
792 { Ast0.wrap(Ast0.Param(t, Some i)) }
793 | t=ctype { (*verify in FunDecl*) Ast0.wrap(Ast0.Param(t, None)) }
794 | t=ctype lp=TOPar s=TMul i=ident rp=TCPar
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)) }
802 | TMetaParam
803 { let (nm,pure,clt) = $1 in
804 Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) }
805
806 name_opt_decl:
807 decl { $1 }
808 | t=ctype lp=TOPar s=TMul rp=TCPar
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
817 const_vol:
818 Tconst { P.clt2mcode Ast.Const $1 }
819 | Tvolatile { P.clt2mcode Ast.Volatile $1 }
820
821 /*****************************************************************************/
822
823 statement:
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 }
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 }
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
853 stm_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
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
875 whenppdecs: w=whens(when_start,rule_elem_statement,any_strict)
876 { w }
877
878 /* a statement that fits into a single rule_elem. should nests be included?
879 what about statement metavariables? */
880 rule_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 */
896 single_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
907 case_line:
908 TDefault TDotDot fun_start
909 { Ast0.wrap
910 (Ast0.Default(P.clt2mcode "default" $1,P.clt2mcode ":" $2,$3)) }
911 | TCase eexpr TDotDot fun_start
912 { Ast0.wrap(Ast0.Case(P.clt2mcode "case" $1,$2,P.clt2mcode ":" $3,$4)) }
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)) } */
917
918 /* In the following, an identifier as a type is not fully supported. Indeed,
919 the language is ambiguous: what is foo * bar; */
920 /* The AST DisjDecl cannot be generated because it would be ambiguous with
921 a disjunction on a statement with a declaration in each branch */
922 decl_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)
952 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
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,
964 P.clt2mcode ")" $4,P.clt2mcode ";" $5))] }
965 | s=ioption(storage)
966 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
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))]}
976 | s=Ttypedef t=typedef_ctype id=comma_list(typedef_ident) pv=TPtVirg
977 { let s = P.clt2mcode "typedef" s in
978 List.map
979 (function id ->
980 Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv)))
981 id }
982
983 one_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)
1008 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
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,
1020 P.clt2mcode ")" $4,P.clt2mcode ";" $5)) }
1021 | s=ioption(storage)
1022 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
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
1034 d_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
1045 array_dec: l=TOCro i=option(eexpr) r=TCCro { (l,i,r) }
1046
1047 initialize:
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)) }
1056 | TMetaInit
1057 {let (nm,pure,clt) = $1 in
1058 Ast0.wrap(Ast0.MetaInit(P.clt2mcode nm clt,pure)) }
1059
1060 initialize2:
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 */
1071 | list(designator) TEq initialize2
1072 { Ast0.wrap(Ast0.InitGccExt($1,P.clt2mcode "=" $2,$3)) }
1073 | ident TDotDot initialize2
1074 { Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */
1075
1076 designator:
1077 | TDot ident
1078 { Ast0.DesignatorField (P.clt2mcode "." $1,$2) }
1079 | TOCro eexpr TCCro
1080 { Ast0.DesignatorIndex (P.clt2mcode "[" $1,$2,P.clt2mcode "]" $3) }
1081 | TOCro eexpr TEllipsis eexpr TCCro
1082 { Ast0.DesignatorRange (P.clt2mcode "[" $1,$2,P.clt2mcode "..." $3,
1083 $4,P.clt2mcode "]" $5) }
1084
1085 initialize_list:
1086 initialize_list_start { Ast0.wrap(Ast0.DOTS($1)) }
1087
1088 initialize_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
1097 comma_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
1105 comma_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 */
1112 decl_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 */
1142 decl_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
1173 be allowed as an expression when the expression is delimited on both sides
1174 by expression-specific markers. In that case, the rule eexpr is used, which
1175 allows <... ...> anywhere. Hopefully, this will not be too much of a problem
1176 in practice. */
1177 expr: basic_expr(expr,invalid) { $1 }
1178 /* allows ... and nests */
1179 eexpr: basic_expr(eexpr,dot_expressions) { $1 }
1180 /* allows nests but not .... */
1181 dexpr: basic_expr(eexpr,nest_expressions) { $1 }
1182
1183 top_eexpr:
1184 eexpr { Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))) }
1185
1186 invalid:
1187 TInvalid { raise (Semantic_cocci.Semantic "not matchable") }
1188
1189 dot_expressions:
1190 TEllipsis { Ast0.wrap(Ast0.Edots(P.clt2mcode "..." $1,None)) }
1191 | nest_expressions { $1 }
1192
1193 /* not clear what whencode would mean, so just drop it */
1194 nest_expressions:
1195 TOEllipsis e=expr_dots(TEllipsis) c=TCEllipsis
1196 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<..." $1,
1197 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1198 P.clt2mcode "...>" c, None, false)) }
1199 | TPOEllipsis e=expr_dots(TEllipsis) c=TPCEllipsis
1200 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<+..." $1,
1201 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1202 P.clt2mcode "...+>" c, None, true)) }
1203
1204 //whenexp: TWhen TNotEq w=eexpr TLineEnd { w }
1205
1206 basic_expr(recurser,primary_extra):
1207 assign_expr(recurser,primary_extra) { $1 }
1208
1209 assign_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
1220 assign_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
1231 cond_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
1237 arith_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
1266 cast_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
1272 unary_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)) }
1278 | unary_op cast_expr(r,pe)
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
1290 unary_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
1296 postfix_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
1315 primary_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
1358 expr_dots(dotter):
1359 r=no_dot_start_end(dexpr,edots_when(dotter,eexpr)) { r }
1360
1361 // used in NEST
1362 no_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
1369 pure_ident:
1370 TIdent { $1 }
1371
1372 meta_ident:
1373 TRuleName TDot pure_ident { (Some $1,P.id2name $3) }
1374
1375 pure_ident_or_meta_ident:
1376 pure_ident { (None,P.id2name $1) }
1377 | meta_ident { $1 }
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") }
1400
1401 pure_ident_or_meta_ident_with_seed:
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
1409 seed_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 }
1416
1417 pure_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
1423 pure_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
1431 pure_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
1439 re_or_not_eqid:
1440 re=regexp_eqid {re}
1441 | ne=not_eqid {ne}
1442
1443 regexp_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 }
1458
1459 not_eqid:
1460 TNotEq i=pure_ident
1461 { (if !Data.in_iso
1462 then failwith "constraints not allowed in iso file");
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");
1467 Ast.IdNegIdSet([fst i]) }
1468 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1469 { (if !Data.in_iso
1470 then failwith "constraints not allowed in iso file");
1471 (if !Data.in_generating
1472 then failwith "constraints not allowed in a generated rule file");
1473 Ast.IdNegIdSet(List.map fst l)
1474 }
1475
1476 re_or_not_eqe:
1477 re=regexp_eqid {Ast0.NotIdCstrt (re)}
1478 | ne=not_eqe {Ast0.NotExpCstrt (ne)}
1479
1480 not_eqe:
1481 TNotEq i=pure_ident
1482 { (if !Data.in_iso
1483 then failwith "constraints not allowed in iso file");
1484 (if !Data.in_generating
1485 then failwith "constraints not allowed in a generated rule file");
1486 [Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))]
1487 }
1488 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1489 { (if !Data.in_iso
1490 then failwith "constraints not allowed in iso file");
1491 (if !Data.in_generating
1492 then failwith "constraints not allowed in a generated rule file");
1493 List.map
1494 (function i ->
1495 Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))))
1496 l
1497 }
1498
1499 not_ceq:
1500 TNotEq i=ident_or_const
1501 { (if !Data.in_iso
1502 then failwith "constraints not allowed in iso file");
1503 (if !Data.in_generating
1504 then failwith "constraints not allowed in a generated rule file");
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");
1509 (if !Data.in_generating
1510 then failwith "constraints not allowed in a generated rule file");
1511 l }
1512
1513 ident_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
1519 not_pos:
1520 TNotEq i=meta_ident
1521 { (if !Data.in_iso
1522 then failwith "constraints not allowed in iso file");
1523 (if !Data.in_generating
1524 then failwith "constraints not allowed in a generated rule file");
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");
1534 (if !Data.in_generating
1535 then failwith "constraints not allowed in a generated rule file");
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
1546 func_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
1559 ident: 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
1565 decl_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
1572 iter_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
1579 typedef_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
1588 decl_list(decl):
1589 /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
1590 | decl_list_start(decl)
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
1597 decl_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
1605 one_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)) }
1615
1616 comma_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
1627 /* error words make it complicated to be able to use error as a metavariable
1628 name or a type in a metavariable list; for that we would like to allow TError
1629 as an ident, but that makes conflicts with this rule. To add back error words,
1630 need to find some appropriate delimiter for it, but it has not been used much
1631 so just drop it */
1632 /*error_words:
1633 TError TWords TEq TOCro cl=comma_list(dexpr) TCCro
1634 { [Ast0.wrap(Ast0.ERRORWORDS(cl))] }
1635 */
1636
1637 /* ---------------------------------------------------------------------- */
1638 /* sequences of statements and expressions */
1639
1640 /* There are number of cases that must be considered:
1641
1642 1. 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
1646 2. 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
1650 3. 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
1654 4. 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
1659 These are implemented by the rules minus_toplevel_sequence,
1660 plus_toplevel_sequence, function_body_sequence, nest_body_sequence, and
1661 when_body_sequence.
1662 */
1663 /* ------------------------------------------------------------------------ */
1664 /* Minus top level */
1665
1666 /* doesn't allow only ... */
1667 minus_start:
1668 fundecl { [Ast0.wrap(Ast0.DECL($1))] }
1669 | ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1670 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1671 | toplevel_seq_startne(toplevel_after_dots_init)
1672 { List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1 }
1673
1674 toplevel_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
1681 toplevel_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
1686 toplevel_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
1691 toplevel_after_exp:
1692 /* empty */ {[]}
1693 | stm_dots toplevel_after_dots {$1::$2}
1694
1695 toplevel_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
1701 toplevel_after_stm:
1702 /* empty */ {[]}
1703 | stm_dots toplevel_after_dots {$1::$2}
1704 | decl_statement toplevel_after_stm {$1@$2}
1705
1706 top_init:
1707 TOInit initialize_list TCBrace
1708 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1709
1710 /* ------------------------------------------------------------------------ */
1711 /* Plus top level */
1712
1713 /* does allow only ... also allows multiple top-level functions */
1714 plus_start:
1715 ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1716 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
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
1725 plus_after_exp:
1726 /* empty */ {[]}
1727 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1728
1729 plus_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
1738 plus_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
1748 fun_start:
1749 fun_after_stm { Ast0.wrap(Ast0.DOTS($1)) }
1750
1751 fun_after_stm:
1752 /* empty */ {[]}
1753 | stm_dots fun_after_dots {$1::$2}
1754 | decl_statement fun_after_stm {$1@$2}
1755
1756 fun_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
1762 fun_after_exp:
1763 stm_dots fun_after_dots {$1::$2}
1764
1765 /* hack to allow mixing statements and expressions in an or */
1766 fun_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
1772 fun_after_exp_or:
1773 /* empty */ {[]}
1774 | stm_dots fun_after_dots {$1::$2}
1775
1776 /* ------------------------------------------------------------------------ */
1777 /* Nest body */
1778
1779 nest_start:
1780 nest_after_dots { Ast0.wrap(Ast0.DOTS($1)) }
1781
1782 nest_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
1787 nest_after_stm:
1788 /* empty */ {[]}
1789 | stm_dots nest_after_dots {$1::$2}
1790 | decl_statement nest_after_stm {$1@$2}
1791
1792 nest_after_exp:
1793 /* empty */ {[]}
1794 | stm_dots nest_after_dots {$1::$2}
1795
1796 /* ------------------------------------------------------------------------ */
1797 /*Whencode*/
1798
1799 when_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
1807 eexpr_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 */
1821 aexpr:
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
1835 eexpr_list_start:
1836 aexpr { [$1] }
1837 | aexpr TComma eexpr_list_start
1838 { $1::Ast0.wrap(Ast0.EComma(P.clt2mcode "," $2))::$3 }
1839
1840 comma_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
1848 eexpr_list_option: eexpr_list { $1 }
1849 | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
1850
1851 /****************************************************************************/
1852
1853 // non-empty lists - drop separator
1854 comma_list(elem):
1855 separated_nonempty_list(TComma,elem) { $1 }
1856
1857 midzero_list(elem,aft):
1858 a=elem b=list(mzl(aft))
1859 { let (mids,code) = List.split b in (mids,(a::code)) }
1860
1861 mzl(elem):
1862 a=TMid0 b=elem { (P.clt2mcode "|" a, b) }
1863
1864 edots_when(dotter,when_grammar):
1865 d=dotter { (d,None) }
1866 | d=dotter TWhen TNotEq w=when_grammar TLineEnd { (d,Some w) }
1867
1868 whens(when_grammar,simple_when_grammar,any_strict):
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 }
1873 | TWhenTrue TNotEq e = eexpr TLineEnd { [Ast0.WhenNotTrue e] }
1874 | TWhenFalse TNotEq e = eexpr TLineEnd { [Ast0.WhenNotFalse e] }
1875
1876 any_strict:
1877 TAny { Ast.WhenAny }
1878 | TStrict { Ast.WhenStrict }
1879 | TForall { Ast.WhenForall }
1880 | TExists { Ast.WhenExists }
1881
1882 /*****************************************************************************
1883 *
1884 *
1885 *****************************************************************************/
1886
1887 iso_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
1916 iso(term):
1917 TIso t=term { Common.Left t }
1918 | TRightIso t=term { Common.Right t }
1919
1920 /*****************************************************************************
1921 *
1922 *
1923 *****************************************************************************/
1924
1925 never_used: TPragma { () }
1926 | TPArob TMetaPos { () }
1927 | TScriptData { () }
1928
1929 script_meta_main: py=pure_ident TShOp TRuleName TDot cocci=pure_ident TMPtVirg
1930 { (P.id2name py, ($3, P.id2name cocci)) }