2 * Copyright 2010, INRIA, University of Copenhagen
3 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
4 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
5 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
6 * This file is part of Coccinelle.
8 * Coccinelle is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, according to version 2 of the License.
12 * Coccinelle is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
20 * The authors reserve the right to distribute this or future versions of
21 * Coccinelle under other licenses.
27 (* Not clear how to allow function declarations to specify a return type
28 and how to allow both to be specified as static, because they are in
29 different rules. The rules seem to have to be combined, which would allow
30 functions to be declared as local variables *)
32 (* Not clear how to let a function have a parameter of type void. At the
33 moment, void is allowed to be the type of a variable, which is wrong, and a
34 parameter needs both a type and an identifier *)
35 module Ast0 = Ast0_cocci
36 module Ast = Ast_cocci
42 %token TIdentifier TExpression TStatement TFunction TLocal TType TParameter
43 %token TIdExpression TInitialiser TDeclaration TField
44 %token Tlist TFresh TConstant TError TWords TWhy0 TPlus0 TBang0
45 %token TPure TContext TGenerated
46 %token TTypedef TDeclarer TIterator TName TPosition TPosAny
47 %token TUsing TDisable TExtends TDepends TOn TEver TNever TExists TForall
48 %token TScript TInitialize TFinalize TNothing TVirtual
49 %token<string> TRuleName
51 %token<Data.clt> Tchar Tshort Tint Tdouble Tfloat Tlong
52 %token<Data.clt> Tsize_t Tssize_t Tptrdiff_t
53 %token<Data.clt> Tvoid Tstruct Tunion Tenum
54 %token<Data.clt> Tunsigned Tsigned
56 %token<Data.clt> Tstatic Tauto Tregister Textern Tinline Ttypedef
57 %token<Data.clt> Tconst Tvolatile
58 %token<string * Data.clt> Tattr
60 %token <Data.clt> TIf TElse TWhile TFor TDo TSwitch TCase TDefault TReturn
61 %token <Data.clt> TBreak TContinue TGoto TSizeof TFunDecl
62 %token <string * Data.clt> TIdent TTypeId TDeclarerId TIteratorId
63 %token <Ast_cocci.added_string * Data.clt> TPragma
65 %token <Parse_aux.idinfo> TMetaId TMetaFunc TMetaLocalFunc
66 %token <Parse_aux.idinfo> TMetaIterator TMetaDeclarer
67 %token <Parse_aux.expinfo> TMetaErr
68 %token <Parse_aux.info> TMetaParam TMetaStm TMetaStmList TMetaType
69 %token <Parse_aux.info> TMetaInit TMetaDecl TMetaField
70 %token <Parse_aux.list_info> TMetaParamList TMetaExpList
71 %token <Parse_aux.typed_expinfo> TMetaExp TMetaIdExp TMetaLocalIdExp TMetaConst
72 %token <Parse_aux.pos_info> TMetaPos
74 %token TArob TArobArob TPArob
75 %token <string> TScriptData
77 %token <Data.clt> TEllipsis TOEllipsis TCEllipsis TPOEllipsis TPCEllipsis
78 %token <Data.clt> TWhen TWhenTrue TWhenFalse TAny TStrict TLineEnd
80 %token <Data.clt> TWhy TDotDot TBang TOPar TOPar0
81 %token <Data.clt> TMid0 TCPar TCPar0
83 %token <string> TPathIsoFile
84 %token <string * Data.clt> TIncludeL TIncludeNL
85 %token <Data.clt * token> TDefine TUndef
86 %token <Data.clt * token * int * int> TDefineParam
87 %token <string * Data.clt> TMinusFile TPlusFile
89 %token <Data.clt> TInc TDec
91 %token <string * Data.clt> TString TChar TFloat TInt
93 %token <Data.clt> TOrLog
94 %token <Data.clt> TAndLog
96 %token <Data.clt> TXor
97 %token <Data.clt> TAnd
98 %token <Data.clt> TEqEq TNotEq TTildeEq TTildeExclEq TSub
99 %token <Ast_cocci.logicalOp * Data.clt> TLogOp /* TInf TSup TInfEq TSupEq */
100 %token <Ast_cocci.arithOp * Data.clt> TShLOp TShROp /* TShl TShr */
101 %token <Ast_cocci.arithOp * Data.clt> TDmOp /* TDiv TMod */
102 %token <Data.clt> TPlus TMinus
103 %token <Data.clt> TMul TTilde
105 %token <Data.clt> TOBrace TCBrace TOInit
106 %token <Data.clt> TOCro TCCro
108 %token <Data.clt> TPtrOp
110 %token TMPtVirg TCppConcatOp
111 %token <Data.clt> TEq TDot TComma TPtVirg
112 %token <Ast_cocci.assignOp * Data.clt> TAssign
114 %token TIso TRightIso TIsoExpression TIsoStatement TIsoDeclaration TIsoType
115 %token TIsoTopLevel TIsoArgExpression TIsoTestExpression TIsoToTestExpression
121 /* operator precedence */
131 %left TLogOp /* TInf TSup TInfEq TSupEq */
132 %left TShLOp TShROp /* TShl TShr */
134 %left TMul TDmOp /* TDiv TMod */
140 %type <Ast0_cocci.rule> minus_main
142 %start minus_exp_main
143 %type <Ast0_cocci.rule> minus_exp_main
146 %type <Ast0_cocci.rule> plus_main
149 %type <Ast0_cocci.rule> plus_exp_main
152 %type <Data.incl_iso list> include_main
155 %type <Ast_cocci.rulename>
159 %type <Ast_cocci.rulename>
163 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> meta_main
165 %start <(string option (*string*) * string option (*ast*)) * (Ast_cocci.meta_name * Ast_cocci.metavar) option> script_meta_main
168 %type <Ast0_cocci.anything list list> iso_main
171 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> iso_meta_main
174 %type <unit> never_used
179 minus_main: minus_body EOF { $1 } | m=minus_body TArobArob { m }
180 | m=minus_body TArob { m }
181 plus_main: plus_body EOF { $1 } | p=plus_body TArobArob { p }
182 | p=plus_body TArob { p }
183 minus_exp_main: minus_exp_body EOF { $1 } | m=minus_exp_body TArobArob { m }
184 | m=minus_exp_body TArob { m }
185 plus_exp_main: plus_exp_body EOF { $1 } | p=plus_exp_body TArobArob { p }
186 | p=plus_exp_body TArob { p }
187 meta_main: m=metadec { m (!Ast0.rule_name) }
188 iso_meta_main: m=metadec { m "" }
190 /*****************************************************************************
193 *****************************************************************************/
197 | TContext { Ast0.Context }
198 | TPure TContext { Ast0.PureContext }
199 | TContext TPure { Ast0.PureContext }
200 | /* empty */ { Ast0.Impure }
203 nm=pure_ident TArob { P.make_iso_rule_name_result (P.id2name nm) }
206 nm=ioption(pure_ident) extends d=depends i=loption(choose_iso)
207 a=loption(disable) e=exists ee=is_expression TArob
208 { P.make_cocci_rule_name_result nm d i a e ee }
209 | TGenerated extends d=depends i=loption(choose_iso)
210 a=loption(disable) e=exists ee=is_expression TArob
211 /* these rules have no name as a cheap way to ensure that no normal
212 rule inherits their metavariables or depends on them */
213 { P.make_generated_rule_name_result None d i a e ee }
214 | TScript TDotDot lang=pure_ident nm=ioption(pure_ident) d=depends TArob
215 { P.make_script_rule_name_result lang nm d }
216 | TInitialize TDotDot lang=pure_ident d=depends TArob
217 { P.make_initial_script_rule_name_result lang d }
218 | TFinalize TDotDot lang=pure_ident d=depends TArob
219 { P.make_final_script_rule_name_result lang d }
223 | TExtends parent=TRuleName
224 { !Data.install_bindings (parent) }
227 /* empty */ { Ast.NoDep }
228 | TDepends TOn parents=dep { parents }
232 | dep TAndLog dep { Ast.AndDep($1, $3) }
233 | dep TOrLog dep { Ast.OrDep ($1, $3) }
236 TRuleName { Ast.Dep $1 }
237 | TBang TRuleName { Ast.AntiDep $2 }
238 | TEver TRuleName { Ast.EverDep $2 }
239 | TNever TRuleName { Ast.NeverDep $2 }
240 | TOPar dep TCPar { $2 }
243 TUsing separated_nonempty_list(TComma,TString) { List.map P.id2name $2 }
246 TDisable separated_nonempty_list(TComma,pure_ident) { List.map P.id2name $2 }
249 TExists { Ast.Exists }
250 | TForall { Ast.Forall }
251 | { Ast.Undetermined }
253 is_expression: // for more flexible parsing of top level expressions
255 | TExpression { true }
258 list(incl) TArob { $1 }
259 | list(incl) TArobArob { $1 }
262 TIncludeL { let (x,_) = $1 in Data.Include(x) }
263 | TUsing TString { Data.Iso(Common.Left(P.id2name $2)) }
264 | TUsing TPathIsoFile { Data.Iso(Common.Right $2) }
265 | TVirtual comma_list(pure_ident)
266 { let names = List.map P.id2name $2 in
267 Iteration.parsed_virtual_rules :=
268 Common.union_set names !Iteration.parsed_virtual_rules;
269 (* ensure that the names of virtual and real rules don't overlap *)
271 (function name -> Hashtbl.add Data.all_metadecls name [])
277 kindfn=metakind ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
278 { P.create_metadec ar ispure kindfn ids }
279 | kindfn=metakind_fresh ids=comma_list(pure_ident_or_meta_ident_with_seed)
281 { P.create_fresh_metadec kindfn ids }
282 | ar=arity ispure=pure
283 kindfn=metakind_atomic_maybe_virt
285 comma_list(pure_ident_or_meta_ident_with_idconstraint_virt(re_or_not_eqid))
287 { let (normal,virt) = Common.partition_either (fun x -> x) ids in
288 let (idfn,virtfn) = kindfn in
290 (P.create_metadec_with_constraints ar ispure idfn normal cr) @
291 (P.create_metadec_virt ar ispure virtfn virt cr) }
292 | ar=arity ispure=pure
293 kindfn=metakind_atomic
294 ids=comma_list(pure_ident_or_meta_ident_with_idconstraint(re_or_not_eqid))
296 { P.create_metadec_with_constraints ar ispure kindfn ids }
297 | ar=arity ispure=pure
298 kindfn=metakind_atomic_expi
299 ids=comma_list(pure_ident_or_meta_ident_with_econstraint(re_or_not_eqe_or_sub))
301 { P.create_metadec_with_constraints ar ispure kindfn ids }
302 | ar=arity ispure=pure
303 kindfn=metakind_atomic_expe
304 ids=comma_list(pure_ident_or_meta_ident_with_econstraint(not_ceq_or_sub))
306 { P.create_metadec_with_constraints ar ispure kindfn ids }
307 | ar=arity TPosition a=option(TPosAny)
308 ids=comma_list(pure_ident_or_meta_ident_with_x_eq(not_pos)) TMPtVirg
309 (* pb: position variables can't be inherited from normal rules, and then
310 there is no way to inherit from a generated rule, so there is no point
311 to have a position variable *)
312 { (if !Data.in_generating
313 then failwith "position variables not allowed in a generated rule file");
314 let kindfn arity name pure check_meta constraints =
315 let tok = check_meta(Ast.MetaPosDecl(arity,name)) in
316 let any = match a with None -> Ast.PER | Some _ -> Ast.ALL in
317 !Data.add_pos_meta name constraints any; tok in
318 P.create_metadec_with_constraints ar false kindfn ids }
319 | ar=arity ispure=pure
320 TParameter Tlist TOCro len=list_len TCCro
321 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
322 { P.create_len_metadec ar ispure
323 (fun lenname arity name pure check_meta ->
324 let tok = check_meta(Ast.MetaParamListDecl(arity,name,lenname)) in
325 !Data.add_paramlist_meta name lenname pure; tok)
327 | ar=arity ispure=pure
328 TExpression Tlist TOCro len=list_len TCCro
329 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
330 { P.create_len_metadec ar ispure
331 (fun lenname arity name pure check_meta ->
332 let tok = check_meta(Ast.MetaExpListDecl(arity,name,lenname)) in
333 !Data.add_explist_meta name lenname pure; tok)
337 pure_ident_or_meta_ident { Common.Left $1 }
338 | TInt { let (x,clt) = $1 in Common.Right (int_of_string x) }
340 %inline metakind_fresh:
342 { (fun name check_meta seed ->
343 let tok = check_meta(Ast.MetaFreshIdDecl(name,seed)) in
344 !Data.add_fresh_id_meta name; tok) }
346 /* metavariable kinds with no constraints, etc */
349 { (fun arity name pure check_meta ->
350 let tok = check_meta(Ast.MetaParamDecl(arity,name)) in
351 !Data.add_param_meta name pure; tok) }
353 { (fun arity name pure check_meta ->
354 let len = Ast.AnyLen in
355 let tok = check_meta(Ast.MetaParamListDecl(arity,name,len)) in
356 !Data.add_paramlist_meta name len pure; tok) }
358 { (fun arity name pure check_meta ->
359 let len = Ast.AnyLen in
360 let tok = check_meta(Ast.MetaExpListDecl(arity,name,len)) in
361 !Data.add_explist_meta name len pure; tok) }
363 { (fun arity name pure check_meta ->
364 let tok = check_meta(Ast.MetaTypeDecl(arity,name)) in
365 !Data.add_type_meta name pure; tok) }
367 { (fun arity name pure check_meta ->
368 let tok = check_meta(Ast.MetaInitDecl(arity,name)) in
369 !Data.add_init_meta name pure; tok) }
371 { (fun arity name pure check_meta ->
372 let tok = check_meta(Ast.MetaStmDecl(arity,name)) in
373 !Data.add_stm_meta name pure; tok) }
375 { (fun arity name pure check_meta ->
376 let tok = check_meta(Ast.MetaDeclDecl(arity,name)) in
377 !Data.add_decl_meta name pure; tok) }
379 { (fun arity name pure check_meta ->
380 let tok = check_meta(Ast.MetaFieldDecl(arity,name)) in
381 !Data.add_field_meta name pure; tok) }
383 { (fun arity name pure check_meta ->
384 let tok = check_meta(Ast.MetaStmListDecl(arity,name)) in
385 !Data.add_stmlist_meta name pure; tok) }
387 { (fun arity (_,name) pure check_meta ->
388 if arity = Ast.NONE && pure = Ast0.Impure
389 then (!Data.add_type_name name; [])
390 else raise (Semantic_cocci.Semantic "bad typedef")) }
392 { (fun arity (_,name) pure check_meta ->
393 if arity = Ast.NONE && pure = Ast0.Impure
394 then (!Data.add_declarer_name name; [])
395 else raise (Semantic_cocci.Semantic "bad declarer")) }
397 { (fun arity (_,name) pure check_meta ->
398 if arity = Ast.NONE && pure = Ast0.Impure
399 then (!Data.add_iterator_name name; [])
400 else raise (Semantic_cocci.Semantic "bad iterator")) }
402 %inline metakind_atomic_maybe_virt:
405 let idfn arity name pure check_meta constraints =
406 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
407 !Data.add_id_meta name constraints pure; tok in
408 let virtfn arity name pure check_meta virtual_env =
410 let vl = List.assoc name virtual_env in
411 !Data.add_virt_id_meta_found name vl; []
413 Iteration.parsed_virtual_identifiers :=
414 Common.union_set [name]
415 !Iteration.parsed_virtual_identifiers;
416 let name = ("virtual",name) in
417 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
418 !Data.add_virt_id_meta_not_found name pure; tok in
421 %inline metakind_atomic:
423 { (fun arity name pure check_meta constraints ->
424 let tok = check_meta(Ast.MetaFuncDecl(arity,name)) in
425 !Data.add_func_meta name constraints pure; tok) }
427 { (fun arity name pure check_meta constraints ->
428 let tok = check_meta(Ast.MetaLocalFuncDecl(arity,name)) in
429 !Data.add_local_func_meta name constraints pure;
432 { (fun arity name pure check_meta constraints ->
433 let tok = check_meta(Ast.MetaDeclarerDecl(arity,name)) in
434 !Data.add_declarer_meta name constraints pure; tok) }
436 { (fun arity name pure check_meta constraints ->
437 let tok = check_meta(Ast.MetaIteratorDecl(arity,name)) in
438 !Data.add_iterator_meta name constraints pure; tok) }
440 %inline metakind_atomic_expi:
442 { (fun arity name pure check_meta constraints ->
443 let tok = check_meta(Ast.MetaErrDecl(arity,name)) in
444 !Data.add_err_meta name constraints pure; tok) }
445 | l=option(TLocal) TIdExpression ty=ioption(meta_exp_type)
446 { (fun arity name pure check_meta constraints ->
449 !Data.add_idexp_meta ty name constraints pure;
450 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
452 !Data.add_local_idexp_meta ty name constraints pure;
453 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
454 | l=option(TLocal) TIdExpression m=nonempty_list(TMul)
455 { (fun arity name pure check_meta constraints ->
456 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
459 !Data.add_idexp_meta ty name constraints pure;
460 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
462 !Data.add_local_idexp_meta ty name constraints pure;
463 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
464 | TExpression ty=expression_type
465 { (fun arity name pure check_meta constraints ->
466 let ty = Some [ty] in
467 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
468 !Data.add_exp_meta ty name constraints pure; tok) }
469 | TConstant ty=ioption(meta_exp_type)
470 { (fun arity name pure check_meta constraints ->
471 let tok = check_meta(Ast.MetaConstDecl(arity,name,ty)) in
472 !Data.add_const_meta ty name constraints pure; tok) }
475 m=nonempty_list(TMul) { P.ty_pointerify Type_cocci.Unknown m }
477 { P.ty_pointerify (Type_cocci.EnumName Type_cocci.NoName) m }
478 | Tstruct m=list(TMul)
480 (Type_cocci.StructUnionName (Type_cocci.Struct,Type_cocci.NoName)) m }
481 | Tunion m=list(TMul)
483 (Type_cocci.StructUnionName (Type_cocci.Union,Type_cocci.NoName)) m }
485 %inline metakind_atomic_expe:
487 { (fun arity name pure check_meta constraints ->
488 let tok = check_meta(Ast.MetaExpDecl(arity,name,None)) in
489 !Data.add_exp_meta None name constraints pure; tok) }
490 | vl=meta_exp_type // no error if use $1 but doesn't type check
491 { (fun arity name pure check_meta constraints ->
493 (match constraints with
494 Ast0.NotExpCstrt constraints ->
497 match Ast0.unwrap c with
502 Type_cocci.BaseType(Type_cocci.IntType) -> true
503 | Type_cocci.BaseType(Type_cocci.ShortType) -> true
504 | Type_cocci.BaseType(Type_cocci.LongType) -> true
508 failwith "metavariable with int constraint must be an int"
512 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
513 !Data.add_exp_meta ty name constraints pure; tok)
518 { [Ast0_cocci.ast0_type_to_type t] }
519 | t=typedef_ctype TOCro TCCro
520 { [Type_cocci.Array (Ast0_cocci.ast0_type_to_type t)] }
521 | TOBrace t=comma_list(ctype) TCBrace m=list(TMul)
523 (function x -> P.ty_pointerify (Ast0_cocci.ast0_type_to_type x) m)
526 arity: TBang0 { Ast.UNIQUE }
528 | TPlus0 { Ast.MULTI }
529 | /* empty */ { Ast.NONE }
531 /* ---------------------------------------------------------------------- */
536 { Ast0.wrap(Ast0.BaseType(Ast.CharType,[P.clt2mcode "char" ty])) }
538 { Ast0.wrap(Ast0.BaseType(Ast.ShortType,[P.clt2mcode "short" ty])) }
540 { Ast0.wrap(Ast0.BaseType(Ast.IntType,[P.clt2mcode "int" ty])) }
542 { let (nm,pure,clt) = p in
543 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
544 | r=TRuleName TDot p=TIdent
545 { let nm = (r,P.id2name p) in
546 (* this is only possible when we are in a metavar decl. Otherwise,
547 it will be represented already as a MetaType *)
548 let _ = P.check_meta(Ast.MetaTypeDecl(Ast.NONE,nm)) in
549 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm (P.id2clt p),
550 Ast0.Impure (*will be ignored*))) }
552 { Ast0.wrap(Ast0.BaseType(Ast.LongType,[P.clt2mcode "long" ty])) }
553 | ty1=Tlong ty2=Tlong
557 [P.clt2mcode "long" ty1;P.clt2mcode "long" ty2])) }
562 { Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" ty])) }
564 { Ast0.wrap(Ast0.BaseType(Ast.DoubleType,[P.clt2mcode "double" ty])) }
566 { Ast0.wrap(Ast0.BaseType(Ast.FloatType,[P.clt2mcode "float" ty])) }
568 { Ast0.wrap(Ast0.BaseType(Ast.SizeType,[P.clt2mcode "size_t" ty])) }
570 { Ast0.wrap(Ast0.BaseType(Ast.SSizeType,[P.clt2mcode "ssize_t" ty])) }
572 { Ast0.wrap(Ast0.BaseType(Ast.PtrDiffType,[P.clt2mcode "ptrdiff_t" ty])) }
574 { Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, Some i)) }
575 | s=Tenum i=ioption(ident) l=TOBrace ids=enum_decl_list r=TCBrace
576 { (if i = None && !Data.in_iso
577 then failwith "enums must be named in the iso file");
578 Ast0.wrap(Ast0.EnumDef(Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, i)),
579 P.clt2mcode "{" l, ids, P.clt2mcode "}" r)) }
580 | s=struct_or_union i=type_ident // allow typedef name
581 { Ast0.wrap(Ast0.StructUnionName(s, Some i)) }
582 | s=struct_or_union i=ioption(type_ident)
583 l=TOBrace d=struct_decl_list r=TCBrace
584 { (if i = None && !Data.in_iso
585 then failwith "structures must be named in the iso file");
586 Ast0.wrap(Ast0.StructUnionDef(Ast0.wrap(Ast0.StructUnionName(s, i)),
588 d, P.clt2mcode "}" r)) }
589 | s=TMetaType l=TOBrace d=struct_decl_list r=TCBrace
590 { let (nm,pure,clt) = s in
591 let ty = Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) in
592 Ast0.wrap(Ast0.StructUnionDef(ty,P.clt2mcode "{" l,d,P.clt2mcode "}" r)) }
594 { Ast0.wrap(Ast0.TypeName(P.id2mcode p)) }
598 r=Tsigned ty=signable_types
599 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,Some ty)) }
600 | r=Tunsigned ty=signable_types
601 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,Some ty)) }
602 | ty=signable_types { ty }
603 | ty=non_signable_types { ty }
606 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
607 { P.pointerify (P.make_cv cv ty) m }
609 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,None)) }
611 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,None)) }
612 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
613 { let (mids,code) = t in
615 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
617 /* signed, unsigned alone not allowed */
619 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
620 { P.pointerify (P.make_cv cv ty) m }
621 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
622 { let (mids,code) = t in
624 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
626 /* ---------------------------------------------------------------------- */
629 s=Tstruct { P.clt2mcode Ast.Struct s }
630 | u=Tunion { P.clt2mcode Ast.Union u }
634 | struct_decl_one { [$1] }
637 | TMetaField { P.meta_field $1 }
638 | t=ctype d=d_ident pv=TPtVirg
640 Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv)) }
641 | t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
642 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar pv=TPtVirg
646 (Ast0.FunctionPointer
647 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
648 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
649 Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv)) }
650 | cv=ioption(const_vol) i=pure_ident d=d_ident pv=TPtVirg
652 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
653 Ast0.wrap(Ast0.UnInit(None,fn idtype,id,P.clt2mcode ";" pv)) }
656 struct_decl_list_start { Ast0.wrap(Ast0.DOTS($1)) }
658 struct_decl_list_start:
660 | struct_decl struct_decl_list_start { $1@$2 }
661 | d=edots_when(TEllipsis,struct_decl_one) r=continue_struct_decl_list
662 { (P.mkddots_one "..." d)::r }
664 continue_struct_decl_list:
666 | struct_decl struct_decl_list_start { $1@$2 }
670 /* ---------------------------------------------------------------------- */
671 /* very restricted what kinds of expressions can appear in an enum decl */
674 | ident { Ast0.wrap(Ast0.Ident($1)) }
676 { let id = Ast0.wrap(Ast0.Ident($1)) in
679 (id,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,
683 ident { Ast0.wrap(Ast0.Ident($1)) }
685 { let (x,clt) = $1 in
686 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
688 { let (nm,constraints,pure,ty,clt) = $1 in
690 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
692 { let (nm,constraints,pure,ty,clt) = $1 in
694 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
696 { let (nm,constraints,pure,ty,clt) = $1 in
698 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
701 nonempty_list_start(enum_decl_one,edots_when(TEllipsis,enum_decl_one))
702 { Ast0.wrap(Ast0.DOTS($1 P.mkedots (fun c -> Ast0.EComma c))) }
704 /*****************************************************************************/
706 /* have to inline everything to avoid conflicts? switch to proper
707 declarations, statements, and expressions for the subterms */
711 b=loption(minus_start)
712 /*ew=loption(error_words)*/
713 { match f@b(*@ew*) with
714 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
715 | code -> Top_level.top_level code }
719 b=loption(plus_start)
720 /*ew=loption(error_words)*/
721 { Top_level.top_level (f@b(*@ew*)) }
726 /*ew=loption(error_words)*/
727 { match f@[b](*@ew*) with
728 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
729 | code -> Top_level.top_level code }
734 /*ew=loption(error_words)*/
735 { Top_level.top_level (f@[b](*@ew*)) }
740 (Ast0.FILEINFO(P.id2mcode $1,
746 (Ast0.Include(P.clt2mcode "#include"
747 (P.drop_pos (P.drop_aft (P.id2clt $1))),
748 let (arity,ln,lln,offset,col,strbef,straft,pos) =
751 (arity,ln,lln,offset,0,strbef,straft,pos) in
753 (Ast.Local (Parse_aux.str2inc (P.id2name $1)))
757 (Ast0.Include(P.clt2mcode "#include"
758 (P.drop_pos (P.drop_aft (P.id2clt $1))),
759 let (arity,ln,lln,offset,col,strbef,straft,pos) =
762 (arity,ln,lln,offset,0,strbef,straft,pos) in
764 (Ast.NonLocal (Parse_aux.str2inc (P.id2name $1)))
767 { let (clt,ident) = $1 in
770 (P.clt2mcode "#undef" clt,
772 TMetaId((nm,constraints,pure,clt)) ->
773 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
775 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
778 (Semantic_cocci.Semantic
779 "unexpected name for a #define")))) }
780 | d=defineop TLineEnd
781 { d (Ast0.wrap(Ast0.DOTS([]))) }
782 | d=defineop t=ctype TLineEnd
783 { let ty = Ast0.wrap(Ast0.TopExp(Ast0.wrap(Ast0.TypeExp(t)))) in
784 d (Ast0.wrap(Ast0.DOTS([ty]))) }
785 | defineop b=toplevel_seq_start(toplevel_after_dots) TLineEnd
789 (match Ast0.unwrap e with
791 [Ast0.rewrap e (Ast0.TopExp(Ast0.set_arg_exp (e1)))]
794 $1 (Ast0.wrap(Ast0.DOTS(body))) }
798 { let (clt,ident) = $1 in
802 (P.clt2mcode "#define" clt,
804 TMetaId((nm,constraints,pure,clt)) ->
805 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
807 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
810 (Semantic_cocci.Semantic
811 "unexpected name for a #define")),
812 Ast0.wrap Ast0.NoParams,
814 | TDefineParam define_param_list_option TCPar
815 { let (clt,ident,parenoff,parencol) = $1 in
816 (* clt is the start of the #define itself *)
817 let (arity,line,lline,offset,col,strbef,straft,pos) = clt in
820 (arity,line,lline,parenoff,parencol,[],[],Ast0.NoMetaPos) in
824 (P.clt2mcode "#define" clt,
826 TMetaId((nm,constraints,pure,clt)) ->
827 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
829 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
832 (Semantic_cocci.Semantic
833 "unexpected name for a #define")),
834 Ast0.wrap (Ast0.DParams (lp,$2,P.clt2mcode ")" $3)),body)) }
836 /* ---------------------------------------------------------------------- */
838 dparam: ident { Ast0.wrap(Ast0.DParam $1) }
840 define_param_list_option:
841 empty_list_start(dparam,TEllipsis)
845 (fun _ d -> Ast0.wrap(Ast0.DPdots(P.clt2mcode "," d)))
846 (fun c -> Ast0.DPComma c))) }
848 /*****************************************************************************/
851 s=ioption(storage) t=ctype
852 id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
857 (Ast0.FunctionType(Some t,
858 P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
859 id, P.clt2mcode ";" pt)) }
863 TFunDecl i=func_ident lp=TOPar d=decl_list(decl) rp=TCPar
864 lb=TOBrace b=fun_start rb=TCBrace
865 { P.verify_parameter_declarations (Ast0.undots d);
866 Ast0.wrap(Ast0.FunDecl((Ast0.default_info(),Ast0.context_befaft()),
868 P.clt2mcode "(" lp, d,
870 P.clt2mcode "{" lb, b,
871 P.clt2mcode "}" rb)) }
878 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
879 raise (Semantic_cocci.Semantic "duplicate storage")
880 with Not_found -> (Ast0.FStorage($1))::$2 }
881 | t=ctype r=fninfo_nt { (Ast0.FType(t))::r }
884 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
885 raise (Semantic_cocci.Semantic "duplicate inline")
886 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
889 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
890 raise (Semantic_cocci.Semantic "multiple attributes")
891 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
898 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
899 raise (Semantic_cocci.Semantic "duplicate storage")
900 with Not_found -> (Ast0.FStorage($1))::$2 }
903 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
904 raise (Semantic_cocci.Semantic "duplicate inline")
905 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
908 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
909 raise (Semantic_cocci.Semantic "duplicate init")
910 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
913 s=Tstatic { P.clt2mcode Ast.Static s }
914 | s=Tauto { P.clt2mcode Ast.Auto s }
915 | s=Tregister { P.clt2mcode Ast.Register s }
916 | s=Textern { P.clt2mcode Ast.Extern s }
918 decl: t=ctype i=ident
919 { Ast0.wrap(Ast0.Param(t, Some i)) }
920 | t=ctype { (*verify in FunDecl*) Ast0.wrap(Ast0.Param(t, None)) }
921 | t=ctype lp=TOPar s=TMul i=ident rp=TCPar
922 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
925 (Ast0.FunctionPointer
926 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
927 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
928 Ast0.wrap(Ast0.Param(fnptr, Some i)) }
930 { let (nm,pure,clt) = $1 in
931 Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) }
935 | t=ctype lp=TOPar s=TMul rp=TCPar
936 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
939 (Ast0.FunctionPointer
940 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
941 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
942 Ast0.wrap(Ast0.Param(fnptr, None)) }
945 Tconst { P.clt2mcode Ast.Const $1 }
946 | Tvolatile { P.clt2mcode Ast.Volatile $1 }
948 /*****************************************************************************/
951 includes { $1 } /* shouldn't be allowed to be a single_statement... */
956 | TIf TOPar eexpr TCPar single_statement %prec TIf
957 { P.ifthen $1 $2 $3 $4 $5 }
958 | TIf TOPar eexpr TCPar single_statement TElse single_statement
959 { P.ifthenelse $1 $2 $3 $4 $5 $6 $7 }
960 | TFor TOPar option(eexpr) TPtVirg option(eexpr) TPtVirg
961 option(eexpr) TCPar single_statement
962 { P.forloop $1 $2 $3 $4 $5 $6 $7 $8 $9 }
963 | TWhile TOPar eexpr TCPar single_statement
964 { P.whileloop $1 $2 $3 $4 $5 }
965 | TDo single_statement TWhile TOPar eexpr TCPar TPtVirg
966 { P.doloop $1 $2 $3 $4 $5 $6 $7 }
967 | iter_ident TOPar eexpr_list_option TCPar single_statement
968 { P.iterator $1 $2 $3 $4 $5 }
969 | TSwitch TOPar eexpr TCPar TOBrace list(decl_var) list(case_line) TCBrace
970 { P.switch $1 $2 $3 $4 $5 (List.concat $6) $7 $8 }
971 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
972 | TReturn TPtVirg { P.ret $1 $2 }
973 | TBreak TPtVirg { P.break $1 $2 }
974 | TContinue TPtVirg { P.cont $1 $2 }
975 | ident TDotDot { P.label $1 $2 }
976 | TGoto ident TPtVirg { P.goto $1 $2 $3 }
977 | TOBrace fun_start TCBrace
981 TEllipsis w=list(whenppdecs)
982 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." $1, List.concat w)) }
983 | TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
984 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." $1, b,
985 P.clt2mcode "...>" c, List.concat w, false)) }
986 | TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
987 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." $1, b,
988 P.clt2mcode "...+>" c, List.concat w, true)) }
990 %inline stm_dots_ell:
991 a=TEllipsis w=list(whenppdecs)
992 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." a, List.concat w)) }
994 %inline stm_dots_nest:
995 a=TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
996 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." a, b,
997 P.clt2mcode "...>" c, List.concat w, false)) }
998 | a=TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
999 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." a, b,
1000 P.clt2mcode "...+>" c, List.concat w, true)) }
1002 whenppdecs: w=whens(when_start,rule_elem_statement,any_strict)
1005 /* a statement that fits into a single rule_elem. should nests be included?
1006 what about statement metavariables? */
1007 rule_elem_statement:
1009 { Ast0.wrap(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),$1)) }
1010 | expr TPtVirg { P.exp_stm $1 $2 }
1011 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
1012 | TReturn TPtVirg { P.ret $1 $2 }
1013 | TBreak TPtVirg { P.break $1 $2 }
1014 | TContinue TPtVirg { P.cont $1 $2 }
1015 | TOPar0 midzero_list(rule_elem_statement,rule_elem_statement) TCPar0
1016 { let (mids,code) = $2 in
1018 (Ast0.Disj(P.clt2mcode "(" $1,
1019 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
1020 mids, P.clt2mcode ")" $3)) }
1022 /* a statement on its own */
1025 | TOPar0 midzero_list(statement,statement) TCPar0
1026 /* degenerate case, elements are single statements and thus don't
1028 { let (mids,code) = $2 in
1030 (Ast0.Disj(P.clt2mcode "(" $1,
1031 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
1032 mids, P.clt2mcode ")" $3)) }
1035 TDefault TDotDot fun_start
1037 (Ast0.Default(P.clt2mcode "default" $1,P.clt2mcode ":" $2,$3)) }
1038 | TCase eexpr TDotDot fun_start
1039 { Ast0.wrap(Ast0.Case(P.clt2mcode "case" $1,$2,P.clt2mcode ":" $3,$4)) }
1040 /* | lp=TOPar0 t=midzero_list(case_line,case_line) rp=TCPar0
1041 { let (mids,code) = ([],[t]) in
1043 (Ast0.DisjCase(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) } */
1045 /* In the following, an identifier as a type is not fully supported. Indeed,
1046 the language is ambiguous: what is foo * bar; */
1047 /* The AST DisjDecl cannot be generated because it would be ambiguous with
1048 a disjunction on a statement with a declaration in each branch */
1051 { [Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv))] }
1052 | TMetaDecl { [P.meta_decl $1] }
1053 | s=ioption(storage) t=ctype d=comma_list(d_ident) pv=TPtVirg
1055 (function (id,fn) ->
1056 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)))
1058 | f=funproto { [f] }
1059 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
1061 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
1062 /* type is a typedef name */
1063 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
1064 d=comma_list(d_ident) pv=TPtVirg
1066 (function (id,fn) ->
1068 P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1069 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)))
1071 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
1072 e=initialize pv=TPtVirg
1073 { let (id,fn) = d in
1074 !Data.add_type_name (P.id2name i);
1075 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1076 [Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
1077 P.clt2mcode ";" pv))] }
1078 /* function pointer type */
1079 | s=ioption(storage)
1080 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1081 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1083 { let (id,fn) = d in
1086 (Ast0.FunctionPointer
1087 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1088 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1089 [Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv))] }
1090 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
1091 { [Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
1092 P.clt2mcode ")" $4,P.clt2mcode ";" $5))] }
1093 | s=ioption(storage)
1094 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1095 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1096 q=TEq e=initialize pv=TPtVirg
1097 { let (id,fn) = d in
1100 (Ast0.FunctionPointer
1101 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1102 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1103 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
1104 | s=Ttypedef t=typedef_ctype id=comma_list(typedef_ident) pv=TPtVirg
1105 { let s = P.clt2mcode "typedef" s in
1108 Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv)))
1113 { Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv)) }
1114 | TMetaDecl { P.meta_decl $1 }
1115 | s=ioption(storage) t=ctype d=d_ident pv=TPtVirg
1116 { let (id,fn) = d in
1117 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1119 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
1120 { let (id,fn) = d in
1121 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv)) }
1122 /* type is a typedef name */
1123 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
1124 d=d_ident pv=TPtVirg
1125 { let (id,fn) = d in
1126 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1127 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)) }
1128 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
1129 e=initialize pv=TPtVirg
1130 { let (id,fn) = d in
1131 !Data.add_type_name (P.id2name i);
1132 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1133 Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
1134 P.clt2mcode ";" pv)) }
1135 /* function pointer type */
1136 | s=ioption(storage)
1137 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1138 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1140 { let (id,fn) = d in
1143 (Ast0.FunctionPointer
1144 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1145 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1146 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1147 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
1148 { Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
1149 P.clt2mcode ")" $4,P.clt2mcode ";" $5)) }
1150 | s=ioption(storage)
1151 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1152 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1153 q=TEq e=initialize pv=TPtVirg
1154 { let (id,fn) = d in
1157 (Ast0.FunctionPointer
1158 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1159 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1160 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))}
1164 ident list(array_dec)
1168 (function (l,i,r) ->
1171 (Ast0.Array(rest,P.clt2mcode "[" l,i,P.clt2mcode "]" r)))
1174 array_dec: l=TOCro i=option(eexpr) r=TCCro { (l,i,r) }
1178 { Ast0.wrap(Ast0.InitExpr($1)) }
1179 | TOBrace initialize_list TCBrace
1180 { if P.struct_initializer $2
1182 let il = P.drop_dot_commas $2 in
1183 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
1185 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) }
1187 {let (nm,pure,clt) = $1 in
1188 Ast0.wrap(Ast0.MetaInit(P.clt2mcode nm clt,pure)) }
1191 /*arithexpr and not eexpr because can have ambiguity with comma*/
1192 /*dots and nests probably not allowed at top level, haven't looked into why*/
1193 arith_expr(eexpr,invalid) { Ast0.wrap(Ast0.InitExpr($1)) }
1194 | TOBrace initialize_list TCBrace
1195 { if P.struct_initializer $2
1197 let il = P.drop_dot_commas $2 in
1198 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
1200 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) }
1201 /* gccext:, labeled elements */
1202 | list(designator) TEq initialize2 /*can we have another of these on the rhs?*/
1203 { Ast0.wrap(Ast0.InitGccExt($1,P.clt2mcode "=" $2,$3)) }
1204 | ident TDotDot initialize2
1205 { Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */
1209 { Ast0.DesignatorField (P.clt2mcode "." $1,$2) }
1211 { Ast0.DesignatorIndex (P.clt2mcode "[" $1,$2,P.clt2mcode "]" $3) }
1212 | TOCro eexpr TEllipsis eexpr TCCro
1213 { Ast0.DesignatorRange (P.clt2mcode "[" $1,$2,P.clt2mcode "..." $3,
1214 $4,P.clt2mcode "]" $5) }
1217 empty_list_start(initialize2,edots_when(TEllipsis,initialize))
1218 { Ast0.wrap(Ast0.DOTS($1 P.mkidots (fun c -> Ast0.IComma c))) }
1220 /* a statement that is part of a list */
1223 { let (nm,pure,clt) = $1 in
1224 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1229 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1231 | statement { [$1] }
1232 /* this doesn't allow expressions at top level, because the parser doesn't
1233 know whether there is one. If there is one, this is not sequencible.
1234 If there is not one, then it is. It seems complicated to get around
1235 this at the parser level. We would have to have a check afterwards to
1236 allow this. One case where this would be useful is for a when. Now
1237 we allow a sequence of whens, so one can be on only statements and
1238 one can be on only expressions. */
1239 | TOPar0 t=midzero_list(fun_start,fun_start) TCPar0
1240 { let (mids,code) = t in
1243 match Ast0.unwrap x with Ast0.DOTS([]) -> true | _ -> false)
1247 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, code, mids,
1248 P.clt2mcode ")" $3))] }
1250 /* a statement that is part of a list */
1251 decl_statement_expr:
1253 { let (nm,pure,clt) = $1 in
1254 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1259 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1261 | statement { [$1] }
1262 /* this doesn't allow expressions at top level, because the parser doesn't
1263 know whether there is one. If there is one, this is not sequencible.
1264 If there is not one, then it is. It seems complicated to get around
1265 this at the parser level. We would have to have a check afterwards to
1266 allow this. One case where this would be useful is for a when. Now
1267 we allow a sequence of whens, so one can be on only statements and
1268 one can be on only expressions. */
1269 | TOPar0 t=midzero_list(fun_after_stm,fun_after_dots_or) TCPar0
1270 { let (mids,code) = t in
1271 if List.for_all (function [] -> true | _ -> false) code
1275 List.map (function x -> Ast0.wrap(Ast0.DOTS x)) code in
1276 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, dot_code, mids,
1277 P.clt2mcode ")" $3))] }
1279 /*****************************************************************************/
1281 /* expr cannot contain <... ...> at the top level. This can only
1282 be allowed as an expression when the expression is delimited on the left
1283 by an expression-specific marker. In that case, the rule eexpr is used, which
1284 allows <... ...> anywhere. Hopefully, this will not be too much of a problem
1286 dot_expressions is the most permissive. all three kinds of expressions use
1287 this once an expression_specific token has been seen */
1288 expr: basic_expr(expr,invalid) { $1 }
1289 /* allows ... and nests */
1290 eexpr: basic_expr(eexpr,dot_expressions) { $1 }
1291 /* allows nests but not .... */
1292 dexpr: basic_expr(eexpr,nest_expressions) { $1 }
1295 eexpr { Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))) }
1298 TInvalid { raise (Semantic_cocci.Semantic "not matchable") }
1301 TEllipsis { Ast0.wrap(Ast0.Edots(P.clt2mcode "..." $1,None)) }
1302 | nest_expressions { $1 }
1304 /* not clear what whencode would mean, so just drop it */
1306 TOEllipsis e=expr_dots(TEllipsis) c=TCEllipsis
1307 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<..." $1,
1308 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1309 P.clt2mcode "...>" c, None, false)) }
1310 | TPOEllipsis e=expr_dots(TEllipsis) c=TPCEllipsis
1311 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<+..." $1,
1312 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1313 P.clt2mcode "...+>" c, None, true)) }
1315 //whenexp: TWhen TNotEq w=eexpr TLineEnd { w }
1317 basic_expr(recurser,primary_extra):
1318 assign_expr(recurser,primary_extra) { $1 }
1321 cond_expr(r,pe) { $1 }
1322 | unary_expr(r,pe) TAssign assign_expr_bis
1323 { let (op,clt) = $2 in
1324 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1325 Ast0.set_arg_exp $3,false)) }
1326 | unary_expr(r,pe) TEq assign_expr_bis
1329 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1332 cond_expr(eexpr,dot_expressions) { $1 }
1333 | unary_expr(eexpr,dot_expressions) TAssign assign_expr_bis
1334 { let (op,clt) = $2 in
1335 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1336 Ast0.set_arg_exp $3,false)) }
1337 | unary_expr(eexpr,dot_expressions) TEq assign_expr_bis
1340 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1343 arith_expr(r,pe) { $1 }
1344 | l=arith_expr(r,pe) w=TWhy t=option(eexpr) dd=TDotDot r=eexpr/*see parser_c*/
1345 { Ast0.wrap(Ast0.CondExpr (l, P.clt2mcode "?" w, t,
1346 P.clt2mcode ":" dd, r)) }
1349 cast_expr(r,pe) { $1 }
1350 | arith_expr(r,pe) TMul arith_expr_bis
1351 { P.arith_op Ast.Mul $1 $2 $3 }
1352 | arith_expr(r,pe) TDmOp arith_expr_bis
1353 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1354 | arith_expr(r,pe) TPlus arith_expr_bis
1355 { P.arith_op Ast.Plus $1 $2 $3 }
1356 | arith_expr(r,pe) TMinus arith_expr_bis
1357 { P.arith_op Ast.Minus $1 $2 $3 }
1358 | arith_expr(r,pe) TShLOp arith_expr_bis
1359 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1360 | arith_expr(r,pe) TShROp arith_expr_bis
1361 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1362 | arith_expr(r,pe) TLogOp arith_expr_bis
1363 { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
1364 | arith_expr(r,pe) TEqEq arith_expr_bis
1365 { P.logic_op Ast.Eq $1 $2 $3 }
1366 | arith_expr(r,pe) TNotEq arith_expr_bis
1367 { P.logic_op Ast.NotEq $1 $2 $3 }
1368 | arith_expr(r,pe) TAnd arith_expr_bis
1369 { P.arith_op Ast.And $1 $2 $3 }
1370 | arith_expr(r,pe) TOr arith_expr_bis
1371 { P.arith_op Ast.Or $1 $2 $3 }
1372 | arith_expr(r,pe) TXor arith_expr_bis
1373 { P.arith_op Ast.Xor $1 $2 $3 }
1374 | arith_expr(r,pe) TAndLog arith_expr_bis
1375 { P.logic_op Ast.AndLog $1 $2 $3 }
1376 | arith_expr(r,pe) TOrLog arith_expr_bis
1377 { P.logic_op Ast.OrLog $1 $2 $3 }
1379 // allows dots now that an expression-specific token has been seen
1380 // need an extra rule because of recursion restrictions
1382 cast_expr(eexpr,dot_expressions) { $1 }
1383 | arith_expr_bis TMul arith_expr_bis
1384 { P.arith_op Ast.Mul $1 $2 $3 }
1385 | arith_expr_bis TDmOp arith_expr_bis
1386 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1387 | arith_expr_bis TPlus arith_expr_bis
1388 { P.arith_op Ast.Plus $1 $2 $3 }
1389 | arith_expr_bis TMinus arith_expr_bis
1390 { P.arith_op Ast.Minus $1 $2 $3 }
1391 | arith_expr_bis TShLOp arith_expr_bis
1392 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1393 | arith_expr_bis TShROp arith_expr_bis
1394 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1395 | arith_expr_bis TLogOp arith_expr_bis
1396 { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
1397 | arith_expr_bis TEqEq arith_expr_bis
1398 { P.logic_op Ast.Eq $1 $2 $3 }
1399 | arith_expr_bis TNotEq arith_expr_bis
1400 { P.logic_op Ast.NotEq $1 $2 $3 }
1401 | arith_expr_bis TAnd arith_expr_bis
1402 { P.arith_op Ast.And $1 $2 $3 }
1403 | arith_expr_bis TOr arith_expr_bis
1404 { P.arith_op Ast.Or $1 $2 $3 }
1405 | arith_expr_bis TXor arith_expr_bis
1406 { P.arith_op Ast.Xor $1 $2 $3 }
1407 | arith_expr_bis TAndLog arith_expr_bis
1408 { P.logic_op Ast.AndLog $1 $2 $3 }
1409 // no OrLog because it is left associative and this is for
1410 // a right argument, not sure why not the same problem for AndLog
1413 unary_expr(r,pe) { $1 }
1414 | lp=TOPar t=ctype rp=TCPar e=cast_expr(r,pe)
1415 { Ast0.wrap(Ast0.Cast (P.clt2mcode "(" lp, t,
1416 P.clt2mcode ")" rp, e)) }
1419 postfix_expr(r,pe) { $1 }
1420 | TInc unary_expr_bis
1421 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
1422 | TDec unary_expr_bis
1423 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
1424 | unary_op cast_expr(r,pe)
1425 { let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
1426 | TBang unary_expr_bis
1427 { let mcode = P.clt2mcode Ast.Not $1 in
1428 Ast0.wrap(Ast0.Unary($2, mcode)) }
1429 | TSizeof unary_expr_bis
1430 { Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
1431 | s=TSizeof lp=TOPar t=ctype rp=TCPar
1432 { Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
1433 P.clt2mcode "(" lp,t,
1434 P.clt2mcode ")" rp)) }
1436 // version that allows dots
1438 postfix_expr(eexpr,dot_expressions) { $1 }
1439 | TInc unary_expr_bis
1440 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
1441 | TDec unary_expr_bis
1442 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
1443 | unary_op cast_expr(eexpr,dot_expressions)
1444 { let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
1445 | TBang unary_expr_bis
1446 { let mcode = P.clt2mcode Ast.Not $1 in
1447 Ast0.wrap(Ast0.Unary($2, mcode)) }
1448 | TSizeof unary_expr_bis
1449 { Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
1450 | s=TSizeof lp=TOPar t=ctype rp=TCPar
1451 { Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
1452 P.clt2mcode "(" lp,t,
1453 P.clt2mcode ")" rp)) }
1455 unary_op: TAnd { P.clt2mcode Ast.GetRef $1 }
1456 | TMul { P.clt2mcode Ast.DeRef $1 }
1457 | TPlus { P.clt2mcode Ast.UnPlus $1 }
1458 | TMinus { P.clt2mcode Ast.UnMinus $1 }
1459 | TTilde { P.clt2mcode Ast.Tilde $1 }
1462 primary_expr(r,pe) { $1 }
1463 | postfix_expr(r,pe) TOCro eexpr TCCro
1464 { Ast0.wrap(Ast0.ArrayAccess ($1,P.clt2mcode "[" $2,$3,
1465 P.clt2mcode "]" $4)) }
1466 | postfix_expr(r,pe) TDot ident
1467 { Ast0.wrap(Ast0.RecordAccess($1, P.clt2mcode "." $2, $3)) }
1468 | postfix_expr(r,pe) TPtrOp ident
1469 { Ast0.wrap(Ast0.RecordPtAccess($1, P.clt2mcode "->" $2,
1471 | postfix_expr(r,pe) TInc
1472 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Inc $2)) }
1473 | postfix_expr(r,pe) TDec
1474 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Dec $2)) }
1475 | postfix_expr(r,pe) TOPar eexpr_list_option TCPar
1476 { Ast0.wrap(Ast0.FunCall($1,P.clt2mcode "(" $2,
1478 P.clt2mcode ")" $4)) }
1480 primary_expr(recurser,primary_extra):
1481 func_ident { Ast0.wrap(Ast0.Ident($1)) }
1483 { let (x,clt) = $1 in
1484 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1486 { let (x,clt) = $1 in
1487 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Float x) clt)) }
1489 { let (x,clt) = $1 in
1490 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.String x) clt)) }
1492 { let (x,clt) = $1 in
1493 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Char x) clt)) }
1495 { let (nm,constraints,pure,ty,clt) = $1 in
1497 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
1499 { let (nm,constraints,pure,clt) = $1 in
1500 Ast0.wrap(Ast0.MetaErr(P.clt2mcode nm clt,constraints,pure)) }
1502 { let (nm,constraints,pure,ty,clt) = $1 in
1504 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
1506 { let (nm,constraints,pure,ty,clt) = $1 in
1508 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
1510 { let (nm,constraints,pure,ty,clt) = $1 in
1512 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.LocalID,pure)) }
1514 { Ast0.wrap(Ast0.Paren(P.clt2mcode "(" $1,$2,
1515 P.clt2mcode ")" $3)) }
1516 | TOPar0 midzero_list(recurser,eexpr) TCPar0
1517 { let (mids,code) = $2 in
1518 Ast0.wrap(Ast0.DisjExpr(P.clt2mcode "(" $1,
1520 P.clt2mcode ")" $3)) }
1521 | primary_extra { $1 }
1524 r=no_dot_start_end(dexpr,edots_when(dotter,eexpr)) { r }
1527 no_dot_start_end(grammar,dotter):
1528 g=grammar dg=list(pair(dotter,grammar))
1529 { function dot_builder ->
1530 g :: (List.concat(List.map (function (d,g) -> [dot_builder d;g]) dg)) }
1532 /*****************************************************************************/
1538 | TIdentifier { "identifier" }
1539 | TExpression { "expression" }
1540 | TStatement { "statement" }
1541 | TFunction { "function" }
1542 | TLocal { "local" }
1544 | TParameter { "parameter" }
1545 | TIdExpression { "idexpression" }
1546 | TInitialiser { "initialiser" }
1548 | TFresh { "fresh" }
1549 | TConstant { "constant" }
1550 | TError { "error" }
1551 | TWords { "words" }
1553 | TContext { "context" }
1554 | TGenerated { "generated" }
1555 | TTypedef { "typedef" }
1556 | TDeclarer { "declarer" }
1557 | TIterator { "iterator" }
1559 | TPosition { "position" }
1562 TRuleName TDot pure_ident { (Some $1,P.id2name $3) }
1563 | TRuleName TDot pure_ident_kwd { (Some $1,$3) }
1565 pure_ident_or_meta_ident:
1566 pure_ident { (None,P.id2name $1) }
1567 | pure_ident_kwd { (None,$1) }
1570 pure_ident_or_meta_ident_with_seed:
1571 pure_ident_or_meta_ident { ($1,Ast.NoVal) }
1572 | pure_ident_or_meta_ident TEq
1573 separated_nonempty_list(TCppConcatOp,seed_elem)
1575 [Ast.SeedString s] -> ($1,Ast.StringSeed s)
1576 | _ -> ($1,Ast.ListSeed $3) }
1579 TString { let (x,_) = $1 in Ast.SeedString x }
1580 | TMetaId { let (x,_,_,_) = $1 in Ast.SeedId x }
1581 | TRuleName TDot pure_ident
1582 { let nm = ($1,P.id2name $3) in
1583 P.check_meta(Ast.MetaIdDecl(Ast.NONE,nm));
1586 pure_ident_or_meta_ident_with_x_eq(x_eq):
1587 i=pure_ident_or_meta_ident l=loption(x_eq)
1592 pure_ident_or_meta_ident_with_econstraint(x_eq):
1593 i=pure_ident_or_meta_ident optc=option(x_eq)
1596 None -> (i, Ast0.NoConstraint)
1600 pure_ident_or_meta_ident_with_idconstraint_virt(constraint_type):
1601 i=pure_ident_or_meta_ident c=option(constraint_type)
1605 None -> (i, Ast.IdNoConstraint)
1606 | Some constraint_ -> (i,constraint_))
1608 | TVirtual TDot pure_ident
1610 let nm = P.id2name $3 in
1611 Iteration.parsed_virtual_identifiers :=
1612 Common.union_set [nm]
1613 !Iteration.parsed_virtual_identifiers;
1617 pure_ident_or_meta_ident_with_idconstraint(constraint_type):
1618 i=pure_ident_or_meta_ident c=option(constraint_type)
1621 None -> (i, Ast.IdNoConstraint)
1622 | Some constraint_ -> (i,constraint_)
1626 re=regexp_eqid {Ast.IdRegExpConstraint re}
1632 then failwith "constraints not allowed in iso file");
1633 (if !Data.in_generating
1634 then failwith "constraints not allowed in a generated rule file");
1635 let (s,_) = re in Ast.IdRegExp (s,Str.regexp s)
1637 | TTildeExclEq re=TString
1639 then failwith "constraints not allowed in iso file");
1640 (if !Data.in_generating
1641 then failwith "constraints not allowed in a generated rule file");
1642 let (s,_) = re in Ast.IdNotRegExp (s,Str.regexp s)
1646 TNotEq i=pure_ident_or_meta_ident
1648 then failwith "constraints not allowed in iso file");
1649 (if !Data.in_generating
1650 (* pb: constraints not stored with metavars; too lazy to search for
1651 them in the pattern *)
1652 then failwith "constraints not allowed in a generated rule file");
1656 P.check_inherited_constraint i
1657 (function mv -> Ast.MetaIdDecl(Ast.NONE,mv)) in
1658 Ast.IdNegIdSet([],[i])
1659 | (None,i) -> Ast.IdNegIdSet([i],[])) }
1660 | TNotEq TOBrace l=comma_list(pure_ident_or_meta_ident) TCBrace
1662 then failwith "constraints not allowed in iso file");
1663 (if !Data.in_generating
1664 then failwith "constraints not allowed in a generated rule file");
1667 (function (str,meta) ->
1669 (Some rn,id) as i ->
1671 P.check_inherited_constraint i
1672 (function mv -> Ast.MetaIdDecl(Ast.NONE,mv)) in
1674 | (None,i) -> (i::str,meta))
1676 Ast.IdNegIdSet(str,meta)
1679 re_or_not_eqe_or_sub:
1680 re=regexp_eqid {Ast0.NotIdCstrt re}
1681 | ne=not_eqe {Ast0.NotExpCstrt ne}
1682 | s=sub {Ast0.SubExpCstrt s}
1685 ceq=not_ceq {Ast0.NotExpCstrt ceq}
1686 | s=sub {Ast0.SubExpCstrt s}
1691 then failwith "constraints not allowed in iso file");
1692 (if !Data.in_generating
1693 then failwith "constraints not allowed in a generated rule file");
1694 [Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))]
1696 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1698 then failwith "constraints not allowed in iso file");
1699 (if !Data.in_generating
1700 then failwith "constraints not allowed in a generated rule file");
1703 Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))))
1708 TNotEq i=ident_or_const
1710 then failwith "constraints not allowed in iso file");
1711 (if !Data.in_generating
1712 then failwith "constraints not allowed in a generated rule file");
1714 | TNotEq TOBrace l=comma_list(ident_or_const) TCBrace
1716 then failwith "constraints not allowed in iso file");
1717 (if !Data.in_generating
1718 then failwith "constraints not allowed in a generated rule file");
1722 (* has to be inherited because not clear how to check subterm constraints
1723 in the functorized CTL engine, so need the variable to be bound
1724 already when bind the subterm constrained metavariable *)
1727 then failwith "constraints not allowed in iso file");
1728 (if !Data.in_generating
1729 then failwith "constraints not allowed in a generated rule file");
1731 P.check_inherited_constraint i
1732 (function mv -> Ast.MetaExpDecl(Ast.NONE,mv,None)) in
1734 | TSub TOBrace l=comma_list(meta_ident) TCBrace
1736 then failwith "constraints not allowed in iso file");
1737 (if !Data.in_generating
1738 then failwith "constraints not allowed in a generated rule file");
1741 P.check_inherited_constraint i
1742 (function mv -> Ast.MetaExpDecl(Ast.NONE,mv,None)))
1746 i=pure_ident { Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))) }
1748 { let (x,clt) = $1 in
1749 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1754 then failwith "constraints not allowed in iso file");
1755 (if !Data.in_generating
1756 then failwith "constraints not allowed in a generated rule file");
1758 P.check_inherited_constraint i
1759 (function mv -> Ast.MetaPosDecl(Ast.NONE,mv)) in
1761 | TNotEq TOBrace l=comma_list(meta_ident) TCBrace
1763 then failwith "constraints not allowed in iso file");
1764 (if !Data.in_generating
1765 then failwith "constraints not allowed in a generated rule file");
1768 P.check_inherited_constraint i
1769 (function mv -> Ast.MetaPosDecl(Ast.NONE,mv)))
1772 func_ident: pure_ident
1773 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1775 { let (nm,constraints,pure,clt) = $1 in
1776 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1778 { let (nm,constraints,pure,clt) = $1 in
1779 Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
1781 { let (nm,constraints,pure,clt) = $1 in
1783 (Ast0.MetaLocalFunc(P.clt2mcode nm clt,constraints,pure)) }
1786 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1788 { let (nm,constraints,pure,clt) = $1 in
1789 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1791 type_ident: pure_ident
1792 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1794 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1796 { let (nm,constraints,pure,clt) = $1 in
1797 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1801 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1803 { let (nm,constraints,pure,clt) = $1 in
1804 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1808 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1810 { let (nm,constraints,pure,clt) = $1 in
1811 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1815 { Ast0.wrap(Ast0.TypeName(P.id2mcode $1)) }
1817 { let (nm,pure,clt) = $1 in
1818 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
1820 /*****************************************************************************/
1823 empty_list_start(one_dec(decl),TEllipsis)
1827 (fun _ d -> Ast0.wrap(Ast0.Pdots(P.clt2mcode "..." d)))
1828 (fun c -> Ast0.PComma c))) }
1833 { let (nm,lenname,pure,clt) = $1 in
1834 let nm = P.clt2mcode nm clt in
1837 Ast.AnyLen -> Ast0.AnyListLen
1838 | Ast.MetaLen nm -> Ast0.MetaListLen(P.clt2mcode nm clt)
1839 | Ast.CstLen n -> Ast0.CstListLen n in
1840 Ast0.wrap(Ast0.MetaParamList(nm,lenname,pure)) }
1842 /* ---------------------------------------------------------------------- */
1843 /* comma list parser, used for fn params, fn args, enums, initlists,
1846 /* enums: enum_decl, edots_when(TEllipsis,enum_decl_one)
1847 fun s d -> P.mkedots "..." d
1848 fun c -> Ast0.EComma c
1851 empty_list_start(elem,dotter):
1852 /* empty */ { fun build_dots build_comma -> [] }
1853 | nonempty_list_start(elem,dotter) { $1 }
1855 nonempty_list_start(elem,dotter): /* dots allowed */
1856 elem { fun build_dots build_comma -> [$1] }
1858 { fun build_dots build_comma ->
1859 $1::[Ast0.wrap(build_comma(P.clt2mcode "," $2))] }
1860 | elem TComma nonempty_list_start(elem,dotter)
1861 { fun build_dots build_comma ->
1862 $1::(Ast0.wrap(build_comma(P.clt2mcode "," $2)))::
1863 ($3 build_dots build_comma) }
1864 | TNothing nonempty_list_start(elem,dotter) { $2 }
1865 | d=dotter { fun build_dots build_comma -> [(build_dots "..." d)] }
1867 { fun build_dots build_comma ->
1868 [(build_dots "..." d);Ast0.wrap(build_comma(P.clt2mcode "," $2))] }
1869 | d=dotter TComma r=continue_list(elem,dotter)
1870 { fun build_dots build_comma ->
1871 (build_dots "..." d)::
1872 (Ast0.wrap(build_comma(P.clt2mcode "," $2)))::
1873 (r build_dots build_comma) }
1875 continue_list(elem,dotter): /* dots not allowed */
1876 elem { fun build_dots build_comma -> [$1] }
1878 { fun build_dots build_comma ->
1879 $1::[Ast0.wrap(build_comma(P.clt2mcode "," $2))] }
1880 | elem TComma nonempty_list_start(elem,dotter)
1881 { fun build_dots build_comma ->
1882 $1::(Ast0.wrap(build_comma(P.clt2mcode "," $2)))::
1883 ($3 build_dots build_comma) }
1884 | TNothing nonempty_list_start(elem,dotter) { $2 }
1886 /* ---------------------------------------------------------------------- */
1888 /* error words make it complicated to be able to use error as a metavariable
1889 name or a type in a metavariable list; for that we would like to allow TError
1890 as an ident, but that makes conflicts with this rule. To add back error words,
1891 need to find some appropriate delimiter for it, but it has not been used much
1894 TError TWords TEq TOCro cl=comma_list(dexpr) TCCro
1895 { [Ast0.wrap(Ast0.ERRORWORDS(cl))] }
1898 /* ---------------------------------------------------------------------- */
1899 /* sequences of statements and expressions */
1901 /* There are number of cases that must be considered:
1904 Dots and nests allowed at the beginning or end
1905 Expressions allowed at the beginning or end
1906 One function allowed, by itself
1908 Dots and nests allowed at the beginning or end
1909 Expressions not allowed at the beginning or end
1910 Functions not allowed
1911 3. The body of a nest:
1912 Dots and nests not allowed at the beginning or end
1913 Expressions allowed at the beginning or end
1914 Functions not allowed
1916 Dots and nests not allowed at the beginning but allowed at the end
1917 Expressions allowed at the beginning or end
1918 Functions not allowed
1920 These are implemented by the rules minus_toplevel_sequence,
1921 plus_toplevel_sequence, function_body_sequence, nest_body_sequence, and
1924 /* ------------------------------------------------------------------------ */
1925 /* Minus top level */
1927 /* doesn't allow only ... */
1929 fundecl { [Ast0.wrap(Ast0.DECL($1))] }
1930 | ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1931 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1932 | toplevel_seq_startne(toplevel_after_dots_init)
1933 { List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1 }
1935 toplevel_seq_startne(after_dots_init):
1936 a=stm_dots_ell b=after_dots_init { a::b }
1937 | a=stm_dots_nest b=after_dots_init { a::b }
1938 | a=stm_dots_nest { [a] }
1939 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1940 | decl_statement_expr toplevel_after_stm { $1@$2 }
1942 toplevel_seq_start(after_dots_init):
1943 stm_dots after_dots_init { $1::$2 }
1944 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1945 | decl_statement_expr toplevel_after_stm { $1@$2 }
1947 toplevel_after_dots_init:
1948 TNothing toplevel_after_exp {$2}
1949 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1950 | decl_statement_expr toplevel_after_stm {$1@$2}
1954 | stm_dots toplevel_after_dots {$1::$2}
1956 toplevel_after_dots:
1958 | TNothing toplevel_after_exp {$2}
1959 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1960 | decl_statement_expr toplevel_after_stm {$1@$2}
1964 | stm_dots toplevel_after_dots {$1::$2}
1965 | decl_statement toplevel_after_stm {$1@$2}
1968 TOInit initialize_list TCBrace
1969 { if P.struct_initializer $2
1971 let il = P.drop_dot_commas $2 in
1972 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
1974 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) }
1976 /* ------------------------------------------------------------------------ */
1977 /* Plus top level */
1979 /* does allow only ... also allows multiple top-level functions */
1981 ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1982 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1983 | stm_dots plus_after_dots
1984 { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1985 | expr plus_after_exp
1986 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1987 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1988 | decl_statement_expr plus_after_stm
1989 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1993 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1997 | TNothing plus_after_exp {$2}
1998 | expr plus_after_exp
1999 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
2000 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
2001 | decl_statement_expr plus_after_stm
2002 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
2006 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
2007 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
2008 | decl_statement plus_after_stm
2009 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
2011 /* ------------------------------------------------------------------------ */
2015 fun_after_stm { Ast0.wrap(Ast0.DOTS($1)) }
2019 | stm_dots fun_after_dots {$1::$2}
2020 | decl_statement fun_after_stm {$1@$2}
2024 | TNothing fun_after_exp {$2}
2025 | expr fun_after_exp {Ast0.wrap(Ast0.Exp($1))::$2}
2026 | decl_statement_expr fun_after_stm {$1@$2}
2029 stm_dots fun_after_dots {$1::$2}
2031 /* hack to allow mixing statements and expressions in an or */
2034 | TNothing fun_after_exp_or {$2}
2035 | expr fun_after_exp_or {Ast0.wrap(Ast0.Exp($1))::$2}
2036 | decl_statement_expr fun_after_stm {$1@$2}
2040 | stm_dots fun_after_dots {$1::$2}
2042 /* ------------------------------------------------------------------------ */
2046 nest_after_dots { Ast0.wrap(Ast0.DOTS($1)) }
2049 decl_statement_expr nest_after_stm {$1@$2}
2050 | TNothing nest_after_exp {$2}
2051 | expr nest_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
2055 | stm_dots nest_after_dots {$1::$2}
2056 | decl_statement nest_after_stm {$1@$2}
2060 | stm_dots nest_after_dots {$1::$2}
2062 /* ------------------------------------------------------------------------ */
2066 expr toplevel_after_exp
2067 { Ast0.wrap(Ast0.DOTS((Ast0.wrap(Ast0.Exp($1)))::$2)) }
2068 | decl_statement toplevel_after_stm
2069 { Ast0.wrap(Ast0.DOTS($1@$2)) }
2071 /* ---------------------------------------------------------------------- */
2073 /* arg expr. may contain a type or a explist metavariable */
2075 dexpr { Ast0.set_arg_exp $1 }
2077 { let (nm,lenname,pure,clt) = $1 in
2078 let nm = P.clt2mcode nm clt in
2081 Ast.AnyLen -> Ast0.AnyListLen
2082 | Ast.MetaLen nm -> Ast0.MetaListLen(P.clt2mcode nm clt)
2083 | Ast.CstLen n -> Ast0.CstListLen n in
2084 Ast0.wrap(Ast0.MetaExprList(nm,lenname,pure)) }
2086 { Ast0.set_arg_exp(Ast0.wrap(Ast0.TypeExp($1))) }
2089 empty_list_start(aexpr,TEllipsis)
2093 (fun _ d -> Ast0.wrap(Ast0.Edots(P.clt2mcode "..." d,None)))
2094 (fun c -> Ast0.EComma c))) }
2096 /****************************************************************************/
2098 // non-empty lists - drop separator
2100 separated_nonempty_list(TComma,elem) { $1 }
2102 midzero_list(elem,aft):
2103 a=elem b=list(mzl(aft))
2104 { let (mids,code) = List.split b in (mids,(a::code)) }
2107 a=TMid0 b=elem { (P.clt2mcode "|" a, b) }
2109 edots_when(dotter,when_grammar):
2110 d=dotter { (d,None) }
2111 | d=dotter TWhen TNotEq w=when_grammar TLineEnd { (d,Some w) }
2113 whens(when_grammar,simple_when_grammar,any_strict):
2114 TWhen TNotEq w=when_grammar TLineEnd { [Ast0.WhenNot w] }
2115 | TWhen TEq w=simple_when_grammar TLineEnd { [Ast0.WhenAlways w] }
2116 | TWhen comma_list(any_strict) TLineEnd
2117 { List.map (function x -> Ast0.WhenModifier(x)) $2 }
2118 | TWhenTrue TNotEq e = eexpr TLineEnd { [Ast0.WhenNotTrue e] }
2119 | TWhenFalse TNotEq e = eexpr TLineEnd { [Ast0.WhenNotFalse e] }
2122 TAny { Ast.WhenAny }
2123 | TStrict { Ast.WhenStrict }
2124 | TForall { Ast.WhenForall }
2125 | TExists { Ast.WhenExists }
2127 /*****************************************************************************
2130 *****************************************************************************/
2133 TIsoExpression e1=eexpr el=list(iso(eexpr)) EOF
2134 { let fn x = Ast0.ExprTag x in P.iso_adjust fn fn e1 el }
2135 | TIsoArgExpression e1=eexpr el=list(iso(eexpr)) EOF
2136 { let fn x = Ast0.ArgExprTag x in P.iso_adjust fn fn e1 el }
2137 | TIsoTestExpression e1=eexpr el=list(iso(eexpr)) EOF
2138 { let fn x = Ast0.TestExprTag x in P.iso_adjust fn fn e1 el }
2139 | TIsoToTestExpression e1=eexpr el=list(iso(eexpr)) EOF
2140 { let ffn x = Ast0.ExprTag x in
2141 let fn x = Ast0.TestExprTag x in
2142 P.iso_adjust ffn fn e1 el }
2143 | TIsoStatement s1=single_statement sl=list(iso(single_statement)) EOF
2144 { let fn x = Ast0.StmtTag x in P.iso_adjust fn fn s1 sl }
2145 | TIsoType t1=ctype tl=list(iso(ctype)) EOF
2146 { let fn x = Ast0.TypeCTag x in P.iso_adjust fn fn t1 tl }
2147 | TIsoTopLevel e1=nest_start el=list(iso(nest_start)) EOF
2148 { let fn x = Ast0.DotsStmtTag x in P.iso_adjust fn fn e1 el }
2149 | TIsoDeclaration d1=decl_var dl=list(iso(decl_var)) EOF
2150 { let check_one = function
2154 (Semantic_cocci.Semantic
2155 "only one variable per declaration in an isomorphism rule") in
2156 let d1 = check_one d1 in
2160 Common.Left x -> Common.Left(check_one x)
2161 | Common.Right x -> Common.Right(check_one x))
2163 let fn x = Ast0.DeclTag x in P.iso_adjust fn fn d1 dl }
2166 TIso t=term { Common.Left t }
2167 | TRightIso t=term { Common.Right t }
2169 /*****************************************************************************
2172 *****************************************************************************/
2174 never_used: TPragma { () }
2175 | TPArob TMetaPos { () }
2176 | TScriptData { () }
2179 py=pure_ident TMPtVirg
2180 { ((Some (P.id2name py), None), None) }
2181 | py=pure_ident script_name_decl TMPtVirg
2182 { ((Some (P.id2name py), None), Some $2) }
2183 | TOPar TUnderscore TComma ast=pure_ident TCPar script_name_decl TMPtVirg
2184 { ((None, Some (P.id2name ast)), Some $6) }
2185 | TOPar str=pure_ident TComma TUnderscore TCPar script_name_decl TMPtVirg
2186 { ((Some (P.id2name str), None), Some $6) }
2187 | TOPar str=pure_ident TComma ast=pure_ident TCPar script_name_decl TMPtVirg
2188 { ((Some (P.id2name str), Some (P.id2name ast)), Some $6) }
2191 TShLOp TRuleName TDot cocci=pure_ident
2192 { let nm = P.id2name cocci in
2193 let mv = Parse_aux.lookup $2 nm in
2195 | TShLOp TVirtual TDot cocci=pure_ident
2196 { let nm = P.id2name cocci in
2197 Iteration.parsed_virtual_identifiers :=
2198 Common.union_set [nm]
2199 !Iteration.parsed_virtual_identifiers;
2200 let name = ("virtual", nm) in
2201 let mv = Ast.MetaIdDecl(Ast.NONE,name) in