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> Tvoid Tstruct Tunion Tenum
53 %token<Data.clt> Tunsigned Tsigned
55 %token<Data.clt> Tstatic Tauto Tregister Textern Tinline Ttypedef
56 %token<Data.clt> Tconst Tvolatile
57 %token<string * Data.clt> Tattr
59 %token <Data.clt> TIf TElse TWhile TFor TDo TSwitch TCase TDefault TReturn
60 %token <Data.clt> TBreak TContinue TGoto TSizeof TFunDecl
61 %token <string * Data.clt> TIdent TTypeId TDeclarerId TIteratorId
62 %token <Ast_cocci.added_string * Data.clt> TPragma
64 %token <Parse_aux.idinfo> TMetaId TMetaFunc TMetaLocalFunc
65 %token <Parse_aux.idinfo> TMetaIterator TMetaDeclarer
66 %token <Parse_aux.expinfo> TMetaErr
67 %token <Parse_aux.info> TMetaParam TMetaStm TMetaStmList TMetaType
68 %token <Parse_aux.info> TMetaInit TMetaDecl TMetaField
69 %token <Parse_aux.list_info> TMetaParamList TMetaExpList
70 %token <Parse_aux.typed_expinfo> TMetaExp TMetaIdExp TMetaLocalIdExp TMetaConst
71 %token <Parse_aux.pos_info> TMetaPos
73 %token TArob TArobArob TPArob
74 %token <string> TScriptData
76 %token <Data.clt> TEllipsis TOEllipsis TCEllipsis TPOEllipsis TPCEllipsis
77 %token <Data.clt> TWhen TWhenTrue TWhenFalse TAny TStrict TLineEnd
79 %token <Data.clt> TWhy TDotDot TBang TOPar TOPar0
80 %token <Data.clt> TMid0 TCPar TCPar0
82 %token <string> TPathIsoFile
83 %token <string * Data.clt> TIncludeL TIncludeNL
84 %token <Data.clt * token> TDefine
85 %token <Data.clt * token * int * int> TDefineParam
86 %token <string * Data.clt> TMinusFile TPlusFile
88 %token <Data.clt> TInc TDec
90 %token <string * Data.clt> TString TChar TFloat TInt
92 %token <Data.clt> TOrLog
93 %token <Data.clt> TAndLog
95 %token <Data.clt> TXor
96 %token <Data.clt> TAnd
97 %token <Data.clt> TEqEq TNotEq TTildeEq TTildeExclEq TSub
98 %token <Ast_cocci.logicalOp * Data.clt> TLogOp /* TInf TSup TInfEq TSupEq */
99 %token <Ast_cocci.arithOp * Data.clt> TShLOp TShROp /* TShl TShr */
100 %token <Ast_cocci.arithOp * Data.clt> TDmOp /* TDiv TMod */
101 %token <Data.clt> TPlus TMinus
102 %token <Data.clt> TMul TTilde
104 %token <Data.clt> TOBrace TCBrace TOInit
105 %token <Data.clt> TOCro TCCro
107 %token <Data.clt> TPtrOp
109 %token TMPtVirg TCppConcatOp
110 %token <Data.clt> TEq TDot TComma TPtVirg
111 %token <Ast_cocci.assignOp * Data.clt> TAssign
113 %token TIso TRightIso TIsoExpression TIsoStatement TIsoDeclaration TIsoType
114 %token TIsoTopLevel TIsoArgExpression TIsoTestExpression TIsoToTestExpression
120 /* operator precedence */
130 %left TLogOp /* TInf TSup TInfEq TSupEq */
131 %left TShLOp TShROp /* TShl TShr */
133 %left TMul TDmOp /* TDiv TMod */
139 %type <Ast0_cocci.rule> minus_main
141 %start minus_exp_main
142 %type <Ast0_cocci.rule> minus_exp_main
145 %type <Ast0_cocci.rule> plus_main
148 %type <Ast0_cocci.rule> plus_exp_main
151 %type <Data.incl_iso list> include_main
154 %type <Ast_cocci.rulename>
158 %type <Ast_cocci.rulename>
162 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> meta_main
164 %start <(string option (*string*) * string option (*ast*)) * (Ast_cocci.meta_name * Ast_cocci.metavar) option> script_meta_main
167 %type <Ast0_cocci.anything list list> iso_main
170 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> iso_meta_main
173 %type <unit> never_used
178 minus_main: minus_body EOF { $1 } | m=minus_body TArobArob { m }
179 | m=minus_body TArob { m }
180 plus_main: plus_body EOF { $1 } | p=plus_body TArobArob { p }
181 | p=plus_body TArob { p }
182 minus_exp_main: minus_exp_body EOF { $1 } | m=minus_exp_body TArobArob { m }
183 | m=minus_exp_body TArob { m }
184 plus_exp_main: plus_exp_body EOF { $1 } | p=plus_exp_body TArobArob { p }
185 | p=plus_exp_body TArob { p }
186 meta_main: m=metadec { m (!Ast0.rule_name) }
187 iso_meta_main: m=metadec { m "" }
189 /*****************************************************************************
192 *****************************************************************************/
196 | TContext { Ast0.Context }
197 | TPure TContext { Ast0.PureContext }
198 | TContext TPure { Ast0.PureContext }
199 | /* empty */ { Ast0.Impure }
202 nm=pure_ident TArob { P.make_iso_rule_name_result (P.id2name nm) }
205 nm=ioption(pure_ident) extends d=depends i=loption(choose_iso)
206 a=loption(disable) e=exists ee=is_expression TArob
207 { P.make_cocci_rule_name_result nm d i a e ee }
208 | TGenerated extends d=depends i=loption(choose_iso)
209 a=loption(disable) e=exists ee=is_expression TArob
210 /* these rules have no name as a cheap way to ensure that no normal
211 rule inherits their metavariables or depends on them */
212 { P.make_generated_rule_name_result None d i a e ee }
213 | TScript TDotDot lang=pure_ident nm=ioption(pure_ident) d=depends TArob
214 { P.make_script_rule_name_result lang nm d }
215 | TInitialize TDotDot lang=pure_ident d=depends TArob
216 { P.make_initial_script_rule_name_result lang d }
217 | TFinalize TDotDot lang=pure_ident d=depends TArob
218 { P.make_final_script_rule_name_result lang d }
222 | TExtends parent=TRuleName
223 { !Data.install_bindings (parent) }
226 /* empty */ { Ast.NoDep }
227 | TDepends TOn parents=dep { parents }
231 | dep TAndLog dep { Ast.AndDep($1, $3) }
232 | dep TOrLog dep { Ast.OrDep ($1, $3) }
235 TRuleName { Ast.Dep $1 }
236 | TBang TRuleName { Ast.AntiDep $2 }
237 | TEver TRuleName { Ast.EverDep $2 }
238 | TNever TRuleName { Ast.NeverDep $2 }
239 | TOPar dep TCPar { $2 }
242 TUsing separated_nonempty_list(TComma,TString) { List.map P.id2name $2 }
245 TDisable separated_nonempty_list(TComma,pure_ident) { List.map P.id2name $2 }
248 TExists { Ast.Exists }
249 | TForall { Ast.Forall }
250 | { Ast.Undetermined }
252 is_expression: // for more flexible parsing of top level expressions
254 | TExpression { true }
257 list(incl) TArob { $1 }
258 | list(incl) TArobArob { $1 }
261 TIncludeL { let (x,_) = $1 in Data.Include(x) }
262 | TUsing TString { Data.Iso(Common.Left(P.id2name $2)) }
263 | TUsing TPathIsoFile { Data.Iso(Common.Right $2) }
264 | TVirtual comma_list(pure_ident)
265 { let names = List.map P.id2name $2 in
266 (* ensure that the names of virtual and real rules don't overlap *)
268 (function name -> Hashtbl.add Data.all_metadecls name [])
274 kindfn=metakind ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
275 { P.create_metadec ar ispure kindfn ids }
276 | kindfn=metakind_fresh ids=comma_list(pure_ident_or_meta_ident_with_seed)
278 { P.create_fresh_metadec kindfn ids }
279 | ar=arity ispure=pure
280 kindfn=metakind_atomic_maybe_virt
282 comma_list(pure_ident_or_meta_ident_with_idconstraint_virt(re_or_not_eqid))
284 { let (normal,virt) = Common.partition_either (fun x -> x) ids in
285 let (idfn,virtfn) = kindfn in
287 (P.create_metadec_with_constraints ar ispure idfn normal cr) @
288 (P.create_metadec_virt ar ispure virtfn virt cr) }
289 | ar=arity ispure=pure
290 kindfn=metakind_atomic
291 ids=comma_list(pure_ident_or_meta_ident_with_idconstraint(re_or_not_eqid))
293 { P.create_metadec_with_constraints ar ispure kindfn ids }
294 | ar=arity ispure=pure
295 kindfn=metakind_atomic_expi
296 ids=comma_list(pure_ident_or_meta_ident_with_econstraint(re_or_not_eqe_or_sub))
298 { P.create_metadec_with_constraints ar ispure kindfn ids }
299 | ar=arity ispure=pure
300 kindfn=metakind_atomic_expe
301 ids=comma_list(pure_ident_or_meta_ident_with_econstraint(not_ceq_or_sub))
303 { P.create_metadec_with_constraints ar ispure kindfn ids }
304 | ar=arity TPosition a=option(TPosAny)
305 ids=comma_list(pure_ident_or_meta_ident_with_x_eq(not_pos)) TMPtVirg
306 (* pb: position variables can't be inherited from normal rules, and then
307 there is no way to inherit from a generated rule, so there is no point
308 to have a position variable *)
309 { (if !Data.in_generating
310 then failwith "position variables not allowed in a generated rule file");
311 let kindfn arity name pure check_meta constraints =
312 let tok = check_meta(Ast.MetaPosDecl(arity,name)) in
313 let any = match a with None -> Ast.PER | Some _ -> Ast.ALL in
314 !Data.add_pos_meta name constraints any; tok in
315 P.create_metadec_with_constraints ar false kindfn ids }
316 | ar=arity ispure=pure
317 TParameter Tlist TOCro len=list_len TCCro
318 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
319 { P.create_len_metadec ar ispure
320 (fun lenname arity name pure check_meta ->
321 let tok = check_meta(Ast.MetaParamListDecl(arity,name,lenname)) in
322 !Data.add_paramlist_meta name lenname pure; tok)
324 | ar=arity ispure=pure
325 TExpression Tlist TOCro len=list_len TCCro
326 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
327 { P.create_len_metadec ar ispure
328 (fun lenname arity name pure check_meta ->
329 let tok = check_meta(Ast.MetaExpListDecl(arity,name,lenname)) in
330 !Data.add_explist_meta name lenname pure; tok)
334 pure_ident_or_meta_ident { Common.Left $1 }
335 | TInt { let (x,clt) = $1 in Common.Right (int_of_string x) }
337 %inline metakind_fresh:
339 { (fun name check_meta seed ->
340 let tok = check_meta(Ast.MetaFreshIdDecl(name,seed)) in
341 !Data.add_fresh_id_meta name; tok) }
343 /* metavariable kinds with no constraints, etc */
346 { (fun arity name pure check_meta ->
347 let tok = check_meta(Ast.MetaParamDecl(arity,name)) in
348 !Data.add_param_meta name pure; tok) }
350 { (fun arity name pure check_meta ->
351 let len = Ast.AnyLen in
352 let tok = check_meta(Ast.MetaParamListDecl(arity,name,len)) in
353 !Data.add_paramlist_meta name len pure; tok) }
355 { (fun arity name pure check_meta ->
356 let len = Ast.AnyLen in
357 let tok = check_meta(Ast.MetaExpListDecl(arity,name,len)) in
358 !Data.add_explist_meta name len pure; tok) }
360 { (fun arity name pure check_meta ->
361 let tok = check_meta(Ast.MetaTypeDecl(arity,name)) in
362 !Data.add_type_meta name pure; tok) }
364 { (fun arity name pure check_meta ->
365 let tok = check_meta(Ast.MetaInitDecl(arity,name)) in
366 !Data.add_init_meta name pure; tok) }
368 { (fun arity name pure check_meta ->
369 let tok = check_meta(Ast.MetaStmDecl(arity,name)) in
370 !Data.add_stm_meta name pure; tok) }
372 { (fun arity name pure check_meta ->
373 let tok = check_meta(Ast.MetaDeclDecl(arity,name)) in
374 !Data.add_decl_meta name pure; tok) }
376 { (fun arity name pure check_meta ->
377 let tok = check_meta(Ast.MetaFieldDecl(arity,name)) in
378 !Data.add_field_meta name pure; tok) }
380 { (fun arity name pure check_meta ->
381 let tok = check_meta(Ast.MetaStmListDecl(arity,name)) in
382 !Data.add_stmlist_meta name pure; tok) }
384 { (fun arity (_,name) pure check_meta ->
385 if arity = Ast.NONE && pure = Ast0.Impure
386 then (!Data.add_type_name name; [])
387 else raise (Semantic_cocci.Semantic "bad typedef")) }
389 { (fun arity (_,name) pure check_meta ->
390 if arity = Ast.NONE && pure = Ast0.Impure
391 then (!Data.add_declarer_name name; [])
392 else raise (Semantic_cocci.Semantic "bad declarer")) }
394 { (fun arity (_,name) pure check_meta ->
395 if arity = Ast.NONE && pure = Ast0.Impure
396 then (!Data.add_iterator_name name; [])
397 else raise (Semantic_cocci.Semantic "bad iterator")) }
399 %inline metakind_atomic_maybe_virt:
402 let idfn arity name pure check_meta constraints =
403 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
404 !Data.add_id_meta name constraints pure; tok in
405 let virtfn arity name pure check_meta virtual_env =
407 let vl = List.assoc name virtual_env in
408 !Data.add_virt_id_meta_found name vl; []
410 let name = ("virtual",name) in
411 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
412 !Data.add_virt_id_meta_not_found name pure; tok in
415 %inline metakind_atomic:
417 { (fun arity name pure check_meta constraints ->
418 let tok = check_meta(Ast.MetaFuncDecl(arity,name)) in
419 !Data.add_func_meta name constraints pure; tok) }
421 { (fun arity name pure check_meta constraints ->
422 let tok = check_meta(Ast.MetaLocalFuncDecl(arity,name)) in
423 !Data.add_local_func_meta name constraints pure;
426 { (fun arity name pure check_meta constraints ->
427 let tok = check_meta(Ast.MetaDeclarerDecl(arity,name)) in
428 !Data.add_declarer_meta name constraints pure; tok) }
430 { (fun arity name pure check_meta constraints ->
431 let tok = check_meta(Ast.MetaIteratorDecl(arity,name)) in
432 !Data.add_iterator_meta name constraints pure; tok) }
434 %inline metakind_atomic_expi:
436 { (fun arity name pure check_meta constraints ->
437 let tok = check_meta(Ast.MetaErrDecl(arity,name)) in
438 !Data.add_err_meta name constraints pure; tok) }
439 | l=option(TLocal) TIdExpression ty=ioption(meta_exp_type)
440 { (fun arity name pure check_meta constraints ->
443 !Data.add_idexp_meta ty name constraints pure;
444 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
446 !Data.add_local_idexp_meta ty name constraints pure;
447 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
448 | l=option(TLocal) TIdExpression m=nonempty_list(TMul)
449 { (fun arity name pure check_meta constraints ->
450 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
453 !Data.add_idexp_meta ty name constraints pure;
454 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
456 !Data.add_local_idexp_meta ty name constraints pure;
457 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
458 | TExpression ty=expression_type
459 { (fun arity name pure check_meta constraints ->
460 let ty = Some [ty] in
461 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
462 !Data.add_exp_meta ty name constraints pure; tok) }
463 | TConstant ty=ioption(meta_exp_type)
464 { (fun arity name pure check_meta constraints ->
465 let tok = check_meta(Ast.MetaConstDecl(arity,name,ty)) in
466 !Data.add_const_meta ty name constraints pure; tok) }
469 m=nonempty_list(TMul) { P.ty_pointerify Type_cocci.Unknown m }
471 { P.ty_pointerify (Type_cocci.EnumName Type_cocci.NoName) m }
472 | Tstruct m=list(TMul)
474 (Type_cocci.StructUnionName (Type_cocci.Struct,Type_cocci.NoName)) m }
475 | Tunion m=list(TMul)
477 (Type_cocci.StructUnionName (Type_cocci.Union,Type_cocci.NoName)) m }
479 %inline metakind_atomic_expe:
481 { (fun arity name pure check_meta constraints ->
482 let tok = check_meta(Ast.MetaExpDecl(arity,name,None)) in
483 !Data.add_exp_meta None name constraints pure; tok) }
484 | vl=meta_exp_type // no error if use $1 but doesn't type check
485 { (fun arity name pure check_meta constraints ->
487 (match constraints with
488 Ast0.NotExpCstrt constraints ->
491 match Ast0.unwrap c with
496 Type_cocci.BaseType(Type_cocci.IntType) -> true
497 | Type_cocci.BaseType(Type_cocci.ShortType) -> true
498 | Type_cocci.BaseType(Type_cocci.LongType) -> true
502 failwith "metavariable with int constraint must be an int"
506 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
507 !Data.add_exp_meta ty name constraints pure; tok)
512 { [Ast0_cocci.ast0_type_to_type t] }
513 | t=typedef_ctype TOCro TCCro
514 { [Type_cocci.Array (Ast0_cocci.ast0_type_to_type t)] }
515 | TOBrace t=comma_list(ctype) TCBrace m=list(TMul)
517 (function x -> P.ty_pointerify (Ast0_cocci.ast0_type_to_type x) m)
520 arity: TBang0 { Ast.UNIQUE }
522 | TPlus0 { Ast.MULTI }
523 | /* empty */ { Ast.NONE }
525 /* ---------------------------------------------------------------------- */
530 { Ast0.wrap(Ast0.BaseType(Ast.CharType,[P.clt2mcode "char" ty])) }
532 { Ast0.wrap(Ast0.BaseType(Ast.ShortType,[P.clt2mcode "short" ty])) }
534 { Ast0.wrap(Ast0.BaseType(Ast.IntType,[P.clt2mcode "int" ty])) }
536 { let (nm,pure,clt) = p in
537 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
538 | r=TRuleName TDot p=TIdent
539 { let nm = (r,P.id2name p) in
540 (* this is only possible when we are in a metavar decl. Otherwise,
541 it will be represented already as a MetaType *)
542 let _ = P.check_meta(Ast.MetaTypeDecl(Ast.NONE,nm)) in
543 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm (P.id2clt p),
544 Ast0.Impure (*will be ignored*))) }
546 { Ast0.wrap(Ast0.BaseType(Ast.LongType,[P.clt2mcode "long" ty])) }
547 | ty1=Tlong ty2=Tlong
551 [P.clt2mcode "long" ty1;P.clt2mcode "long" ty2])) }
556 { Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" ty])) }
558 { Ast0.wrap(Ast0.BaseType(Ast.DoubleType,[P.clt2mcode "double" ty])) }
560 { Ast0.wrap(Ast0.BaseType(Ast.FloatType,[P.clt2mcode "float" ty])) }
562 { Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, Some i)) }
563 | s=Tenum i=ioption(ident) l=TOBrace ids=enum_decl_list r=TCBrace
564 { (if i = None && !Data.in_iso
565 then failwith "enums must be named in the iso file");
566 Ast0.wrap(Ast0.EnumDef(Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, i)),
567 P.clt2mcode "{" l, ids, P.clt2mcode "}" r)) }
568 | s=struct_or_union i=ident
569 { Ast0.wrap(Ast0.StructUnionName(s, Some i)) }
570 | s=struct_or_union i=ioption(ident)
571 l=TOBrace d=struct_decl_list r=TCBrace
572 { (if i = None && !Data.in_iso
573 then failwith "structures must be named in the iso file");
574 Ast0.wrap(Ast0.StructUnionDef(Ast0.wrap(Ast0.StructUnionName(s, i)),
576 d, P.clt2mcode "}" r)) }
577 | s=TMetaType l=TOBrace d=struct_decl_list r=TCBrace
578 { let (nm,pure,clt) = s in
579 let ty = Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) in
580 Ast0.wrap(Ast0.StructUnionDef(ty,P.clt2mcode "{" l,d,P.clt2mcode "}" r)) }
582 { Ast0.wrap(Ast0.TypeName(P.id2mcode p)) }
586 r=Tsigned ty=signable_types
587 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,Some ty)) }
588 | r=Tunsigned ty=signable_types
589 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,Some ty)) }
590 | ty=signable_types { ty }
591 | ty=non_signable_types { ty }
594 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
595 { P.pointerify (P.make_cv cv ty) m }
597 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,None)) }
599 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,None)) }
600 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
601 { let (mids,code) = t in
603 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
605 /* signed, unsigned alone not allowed */
607 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
608 { P.pointerify (P.make_cv cv ty) m }
609 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
610 { let (mids,code) = t in
612 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
614 /* ---------------------------------------------------------------------- */
617 s=Tstruct { P.clt2mcode Ast.Struct s }
618 | u=Tunion { P.clt2mcode Ast.Union u }
622 | struct_decl_one { [$1] }
625 | TMetaField { P.meta_field $1 }
626 | t=ctype d=d_ident pv=TPtVirg
628 Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv)) }
629 | t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
630 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar pv=TPtVirg
634 (Ast0.FunctionPointer
635 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
636 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
637 Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv)) }
638 | cv=ioption(const_vol) i=pure_ident d=d_ident pv=TPtVirg
640 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
641 Ast0.wrap(Ast0.UnInit(None,fn idtype,id,P.clt2mcode ";" pv)) }
644 struct_decl_list_start { Ast0.wrap(Ast0.DOTS($1)) }
646 struct_decl_list_start:
648 | struct_decl struct_decl_list_start { $1@$2 }
649 | d=edots_when(TEllipsis,struct_decl_one) r=continue_struct_decl_list
650 { (P.mkddots_one "..." d)::r }
652 continue_struct_decl_list:
654 | struct_decl struct_decl_list_start { $1@$2 }
658 /* ---------------------------------------------------------------------- */
659 /* very restricted what kinds of expressions can appear in an enum decl */
662 | ident { Ast0.wrap(Ast0.Ident($1)) }
664 { let id = Ast0.wrap(Ast0.Ident($1)) in
667 (id,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,
671 ident { Ast0.wrap(Ast0.Ident($1)) }
673 { let (x,clt) = $1 in
674 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
676 { let (nm,constraints,pure,ty,clt) = $1 in
678 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
680 { let (nm,constraints,pure,ty,clt) = $1 in
682 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
684 { let (nm,constraints,pure,ty,clt) = $1 in
686 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
689 nonempty_list_start(enum_decl_one,edots_when(TEllipsis,enum_decl_one))
690 { Ast0.wrap(Ast0.DOTS($1 P.mkedots (fun c -> Ast0.EComma c))) }
692 /*****************************************************************************/
694 /* have to inline everything to avoid conflicts? switch to proper
695 declarations, statements, and expressions for the subterms */
699 b=loption(minus_start)
700 /*ew=loption(error_words)*/
701 { match f@b(*@ew*) with
702 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
703 | code -> Top_level.top_level code }
707 b=loption(plus_start)
708 /*ew=loption(error_words)*/
709 { Top_level.top_level (f@b(*@ew*)) }
714 /*ew=loption(error_words)*/
715 { match f@[b](*@ew*) with
716 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
717 | code -> Top_level.top_level code }
722 /*ew=loption(error_words)*/
723 { Top_level.top_level (f@[b](*@ew*)) }
728 (Ast0.FILEINFO(P.id2mcode $1,
734 (Ast0.Include(P.clt2mcode "#include"
735 (P.drop_pos (P.drop_aft (P.id2clt $1))),
736 let (arity,ln,lln,offset,col,strbef,straft,pos) =
739 (arity,ln,lln,offset,0,strbef,straft,pos) in
741 (Ast.Local (Parse_aux.str2inc (P.id2name $1)))
745 (Ast0.Include(P.clt2mcode "#include"
746 (P.drop_pos (P.drop_aft (P.id2clt $1))),
747 let (arity,ln,lln,offset,col,strbef,straft,pos) =
750 (arity,ln,lln,offset,0,strbef,straft,pos) in
752 (Ast.NonLocal (Parse_aux.str2inc (P.id2name $1)))
754 | d=defineop TLineEnd
755 { d (Ast0.wrap(Ast0.DOTS([]))) }
756 | d=defineop t=ctype TLineEnd
757 { let ty = Ast0.wrap(Ast0.TopExp(Ast0.wrap(Ast0.TypeExp(t)))) in
758 d (Ast0.wrap(Ast0.DOTS([ty]))) }
759 | defineop b=toplevel_seq_start(toplevel_after_dots) TLineEnd
763 (match Ast0.unwrap e with
765 [Ast0.rewrap e (Ast0.TopExp(Ast0.set_arg_exp (e1)))]
768 $1 (Ast0.wrap(Ast0.DOTS(body))) }
772 { let (clt,ident) = $1 in
776 (P.clt2mcode "#define" clt,
778 TMetaId((nm,constraints,pure,clt)) ->
779 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
781 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
784 (Semantic_cocci.Semantic
785 "unexpected name for a #define")),
786 Ast0.wrap Ast0.NoParams,
788 | TDefineParam define_param_list_option TCPar
789 { let (clt,ident,parenoff,parencol) = $1 in
790 (* clt is the start of the #define itself *)
791 let (arity,line,lline,offset,col,strbef,straft,pos) = clt in
794 (arity,line,lline,parenoff,parencol,[],[],Ast0.NoMetaPos) in
798 (P.clt2mcode "#define" clt,
800 TMetaId((nm,constraints,pure,clt)) ->
801 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
803 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
806 (Semantic_cocci.Semantic
807 "unexpected name for a #define")),
808 Ast0.wrap (Ast0.DParams (lp,$2,P.clt2mcode ")" $3)),body)) }
810 /* ---------------------------------------------------------------------- */
812 dparam: ident { Ast0.wrap(Ast0.DParam $1) }
814 define_param_list_option:
815 empty_list_start(dparam,TEllipsis)
819 (fun _ d -> Ast0.wrap(Ast0.DPdots(P.clt2mcode "," d)))
820 (fun c -> Ast0.DPComma c))) }
822 /*****************************************************************************/
825 s=ioption(storage) t=ctype
826 id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
831 (Ast0.FunctionType(Some t,
832 P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
833 id, P.clt2mcode ";" pt)) }
837 TFunDecl i=func_ident lp=TOPar d=decl_list(decl) rp=TCPar
838 lb=TOBrace b=fun_start rb=TCBrace
839 { P.verify_parameter_declarations (Ast0.undots d);
840 Ast0.wrap(Ast0.FunDecl((Ast0.default_info(),Ast0.context_befaft()),
842 P.clt2mcode "(" lp, d,
844 P.clt2mcode "{" lb, b,
845 P.clt2mcode "}" rb)) }
852 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
853 raise (Semantic_cocci.Semantic "duplicate storage")
854 with Not_found -> (Ast0.FStorage($1))::$2 }
855 | t=ctype r=fninfo_nt { (Ast0.FType(t))::r }
858 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
859 raise (Semantic_cocci.Semantic "duplicate inline")
860 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
863 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
864 raise (Semantic_cocci.Semantic "multiple attributes")
865 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
872 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
873 raise (Semantic_cocci.Semantic "duplicate storage")
874 with Not_found -> (Ast0.FStorage($1))::$2 }
877 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
878 raise (Semantic_cocci.Semantic "duplicate inline")
879 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
882 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
883 raise (Semantic_cocci.Semantic "duplicate init")
884 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
887 s=Tstatic { P.clt2mcode Ast.Static s }
888 | s=Tauto { P.clt2mcode Ast.Auto s }
889 | s=Tregister { P.clt2mcode Ast.Register s }
890 | s=Textern { P.clt2mcode Ast.Extern s }
892 decl: t=ctype i=ident
893 { Ast0.wrap(Ast0.Param(t, Some i)) }
894 | t=ctype { (*verify in FunDecl*) Ast0.wrap(Ast0.Param(t, None)) }
895 | t=ctype lp=TOPar s=TMul i=ident rp=TCPar
896 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
899 (Ast0.FunctionPointer
900 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
901 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
902 Ast0.wrap(Ast0.Param(fnptr, Some i)) }
904 { let (nm,pure,clt) = $1 in
905 Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) }
909 | t=ctype lp=TOPar s=TMul rp=TCPar
910 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
913 (Ast0.FunctionPointer
914 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
915 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
916 Ast0.wrap(Ast0.Param(fnptr, None)) }
919 Tconst { P.clt2mcode Ast.Const $1 }
920 | Tvolatile { P.clt2mcode Ast.Volatile $1 }
922 /*****************************************************************************/
925 includes { $1 } /* shouldn't be allowed to be a single_statement... */
930 | TIf TOPar eexpr TCPar single_statement %prec TIf
931 { P.ifthen $1 $2 $3 $4 $5 }
932 | TIf TOPar eexpr TCPar single_statement TElse single_statement
933 { P.ifthenelse $1 $2 $3 $4 $5 $6 $7 }
934 | TFor TOPar option(eexpr) TPtVirg option(eexpr) TPtVirg
935 option(eexpr) TCPar single_statement
936 { P.forloop $1 $2 $3 $4 $5 $6 $7 $8 $9 }
937 | TWhile TOPar eexpr TCPar single_statement
938 { P.whileloop $1 $2 $3 $4 $5 }
939 | TDo single_statement TWhile TOPar eexpr TCPar TPtVirg
940 { P.doloop $1 $2 $3 $4 $5 $6 $7 }
941 | iter_ident TOPar eexpr_list_option TCPar single_statement
942 { P.iterator $1 $2 $3 $4 $5 }
943 | TSwitch TOPar eexpr TCPar TOBrace list(decl_var) list(case_line) TCBrace
944 { P.switch $1 $2 $3 $4 $5 (List.concat $6) $7 $8 }
945 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
946 | TReturn TPtVirg { P.ret $1 $2 }
947 | TBreak TPtVirg { P.break $1 $2 }
948 | TContinue TPtVirg { P.cont $1 $2 }
949 | ident TDotDot { P.label $1 $2 }
950 | TGoto ident TPtVirg { P.goto $1 $2 $3 }
951 | TOBrace fun_start TCBrace
955 TEllipsis w=list(whenppdecs)
956 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." $1, List.concat w)) }
957 | TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
958 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." $1, b,
959 P.clt2mcode "...>" c, List.concat w, false)) }
960 | TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
961 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." $1, b,
962 P.clt2mcode "...+>" c, List.concat w, true)) }
964 %inline stm_dots_ell:
965 a=TEllipsis w=list(whenppdecs)
966 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." a, List.concat w)) }
968 %inline stm_dots_nest:
969 a=TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
970 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." a, b,
971 P.clt2mcode "...>" c, List.concat w, false)) }
972 | a=TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
973 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." a, b,
974 P.clt2mcode "...+>" c, List.concat w, true)) }
976 whenppdecs: w=whens(when_start,rule_elem_statement,any_strict)
979 /* a statement that fits into a single rule_elem. should nests be included?
980 what about statement metavariables? */
983 { Ast0.wrap(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),$1)) }
984 | expr TPtVirg { P.exp_stm $1 $2 }
985 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
986 | TReturn TPtVirg { P.ret $1 $2 }
987 | TBreak TPtVirg { P.break $1 $2 }
988 | TContinue TPtVirg { P.cont $1 $2 }
989 | TOPar0 midzero_list(rule_elem_statement,rule_elem_statement) TCPar0
990 { let (mids,code) = $2 in
992 (Ast0.Disj(P.clt2mcode "(" $1,
993 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
994 mids, P.clt2mcode ")" $3)) }
996 /* a statement on its own */
999 | TOPar0 midzero_list(statement,statement) TCPar0
1000 /* degenerate case, elements are single statements and thus don't
1002 { let (mids,code) = $2 in
1004 (Ast0.Disj(P.clt2mcode "(" $1,
1005 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
1006 mids, P.clt2mcode ")" $3)) }
1009 TDefault TDotDot fun_start
1011 (Ast0.Default(P.clt2mcode "default" $1,P.clt2mcode ":" $2,$3)) }
1012 | TCase eexpr TDotDot fun_start
1013 { Ast0.wrap(Ast0.Case(P.clt2mcode "case" $1,$2,P.clt2mcode ":" $3,$4)) }
1014 /* | lp=TOPar0 t=midzero_list(case_line,case_line) rp=TCPar0
1015 { let (mids,code) = ([],[t]) in
1017 (Ast0.DisjCase(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) } */
1019 /* In the following, an identifier as a type is not fully supported. Indeed,
1020 the language is ambiguous: what is foo * bar; */
1021 /* The AST DisjDecl cannot be generated because it would be ambiguous with
1022 a disjunction on a statement with a declaration in each branch */
1025 { [Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv))] }
1026 | TMetaDecl { [P.meta_decl $1] }
1027 | s=ioption(storage) t=ctype d=comma_list(d_ident) pv=TPtVirg
1029 (function (id,fn) ->
1030 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)))
1032 | f=funproto { [f] }
1033 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
1035 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
1036 /* type is a typedef name */
1037 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
1038 d=comma_list(d_ident) pv=TPtVirg
1040 (function (id,fn) ->
1042 P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1043 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)))
1045 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
1046 e=initialize pv=TPtVirg
1047 { let (id,fn) = d in
1048 !Data.add_type_name (P.id2name i);
1049 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1050 [Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
1051 P.clt2mcode ";" pv))] }
1052 /* function pointer type */
1053 | s=ioption(storage)
1054 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1055 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1057 { let (id,fn) = d in
1060 (Ast0.FunctionPointer
1061 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1062 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1063 [Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv))] }
1064 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
1065 { [Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
1066 P.clt2mcode ")" $4,P.clt2mcode ";" $5))] }
1067 | s=ioption(storage)
1068 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1069 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1070 q=TEq e=initialize pv=TPtVirg
1071 { let (id,fn) = d in
1074 (Ast0.FunctionPointer
1075 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1076 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1077 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
1078 | s=Ttypedef t=typedef_ctype id=comma_list(typedef_ident) pv=TPtVirg
1079 { let s = P.clt2mcode "typedef" s in
1082 Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv)))
1087 { Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv)) }
1088 | TMetaDecl { P.meta_decl $1 }
1089 | s=ioption(storage) t=ctype d=d_ident pv=TPtVirg
1090 { let (id,fn) = d in
1091 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1093 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
1094 { let (id,fn) = d in
1095 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv)) }
1096 /* type is a typedef name */
1097 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
1098 d=d_ident pv=TPtVirg
1099 { let (id,fn) = d in
1100 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1101 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)) }
1102 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
1103 e=initialize pv=TPtVirg
1104 { let (id,fn) = d in
1105 !Data.add_type_name (P.id2name i);
1106 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1107 Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
1108 P.clt2mcode ";" pv)) }
1109 /* function pointer type */
1110 | s=ioption(storage)
1111 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1112 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1114 { let (id,fn) = d in
1117 (Ast0.FunctionPointer
1118 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1119 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1120 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1121 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
1122 { Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
1123 P.clt2mcode ")" $4,P.clt2mcode ";" $5)) }
1124 | s=ioption(storage)
1125 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1126 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1127 q=TEq e=initialize pv=TPtVirg
1128 { let (id,fn) = d in
1131 (Ast0.FunctionPointer
1132 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1133 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1134 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))}
1138 ident list(array_dec)
1142 (function (l,i,r) ->
1145 (Ast0.Array(rest,P.clt2mcode "[" l,i,P.clt2mcode "]" r)))
1148 array_dec: l=TOCro i=option(eexpr) r=TCCro { (l,i,r) }
1152 { Ast0.wrap(Ast0.InitExpr($1)) }
1153 | TOBrace initialize_list TCBrace
1154 { if P.struct_initializer $2
1156 let il = P.drop_dot_commas $2 in
1157 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
1159 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) }
1161 {let (nm,pure,clt) = $1 in
1162 Ast0.wrap(Ast0.MetaInit(P.clt2mcode nm clt,pure)) }
1165 /*arithexpr and not eexpr because can have ambiguity with comma*/
1166 /*dots and nests probably not allowed at top level, haven't looked into why*/
1167 arith_expr(eexpr,invalid) { Ast0.wrap(Ast0.InitExpr($1)) }
1168 | TOBrace initialize_list TCBrace
1169 { if P.struct_initializer $2
1171 let il = P.drop_dot_commas $2 in
1172 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
1174 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) }
1175 /* gccext:, labeled elements */
1176 | list(designator) TEq initialize2 /*can we have another of these on the rhs?*/
1177 { Ast0.wrap(Ast0.InitGccExt($1,P.clt2mcode "=" $2,$3)) }
1178 | ident TDotDot initialize2
1179 { Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */
1183 { Ast0.DesignatorField (P.clt2mcode "." $1,$2) }
1185 { Ast0.DesignatorIndex (P.clt2mcode "[" $1,$2,P.clt2mcode "]" $3) }
1186 | TOCro eexpr TEllipsis eexpr TCCro
1187 { Ast0.DesignatorRange (P.clt2mcode "[" $1,$2,P.clt2mcode "..." $3,
1188 $4,P.clt2mcode "]" $5) }
1191 empty_list_start(initialize2,edots_when(TEllipsis,initialize))
1192 { Ast0.wrap(Ast0.DOTS($1 P.mkidots (fun c -> Ast0.IComma c))) }
1194 /* a statement that is part of a list */
1197 { let (nm,pure,clt) = $1 in
1198 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1203 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1205 | statement { [$1] }
1206 /* this doesn't allow expressions at top level, because the parser doesn't
1207 know whether there is one. If there is one, this is not sequencible.
1208 If there is not one, then it is. It seems complicated to get around
1209 this at the parser level. We would have to have a check afterwards to
1210 allow this. One case where this would be useful is for a when. Now
1211 we allow a sequence of whens, so one can be on only statements and
1212 one can be on only expressions. */
1213 | TOPar0 t=midzero_list(fun_start,fun_start) TCPar0
1214 { let (mids,code) = t in
1217 match Ast0.unwrap x with Ast0.DOTS([]) -> true | _ -> false)
1221 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, code, mids,
1222 P.clt2mcode ")" $3))] }
1224 /* a statement that is part of a list */
1225 decl_statement_expr:
1227 { let (nm,pure,clt) = $1 in
1228 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1233 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1235 | statement { [$1] }
1236 /* this doesn't allow expressions at top level, because the parser doesn't
1237 know whether there is one. If there is one, this is not sequencible.
1238 If there is not one, then it is. It seems complicated to get around
1239 this at the parser level. We would have to have a check afterwards to
1240 allow this. One case where this would be useful is for a when. Now
1241 we allow a sequence of whens, so one can be on only statements and
1242 one can be on only expressions. */
1243 | TOPar0 t=midzero_list(fun_after_stm,fun_after_dots_or) TCPar0
1244 { let (mids,code) = t in
1245 if List.for_all (function [] -> true | _ -> false) code
1249 List.map (function x -> Ast0.wrap(Ast0.DOTS x)) code in
1250 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, dot_code, mids,
1251 P.clt2mcode ")" $3))] }
1253 /*****************************************************************************/
1255 /* The following cannot contain <... ...> at the top level. This can only
1256 be allowed as an expression when the expression is delimited on both sides
1257 by expression-specific markers. In that case, the rule eexpr is used, which
1258 allows <... ...> anywhere. Hopefully, this will not be too much of a problem
1260 expr: basic_expr(expr,invalid) { $1 }
1261 /* allows ... and nests */
1262 eexpr: basic_expr(eexpr,dot_expressions) { $1 }
1263 /* allows nests but not .... */
1264 dexpr: basic_expr(eexpr,nest_expressions) { $1 }
1267 eexpr { Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))) }
1270 TInvalid { raise (Semantic_cocci.Semantic "not matchable") }
1273 TEllipsis { Ast0.wrap(Ast0.Edots(P.clt2mcode "..." $1,None)) }
1274 | nest_expressions { $1 }
1276 /* not clear what whencode would mean, so just drop it */
1278 TOEllipsis e=expr_dots(TEllipsis) c=TCEllipsis
1279 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<..." $1,
1280 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1281 P.clt2mcode "...>" c, None, false)) }
1282 | TPOEllipsis e=expr_dots(TEllipsis) c=TPCEllipsis
1283 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<+..." $1,
1284 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1285 P.clt2mcode "...+>" c, None, true)) }
1287 //whenexp: TWhen TNotEq w=eexpr TLineEnd { w }
1289 basic_expr(recurser,primary_extra):
1290 assign_expr(recurser,primary_extra) { $1 }
1293 cond_expr(r,pe) { $1 }
1294 | unary_expr(r,pe) TAssign assign_expr_bis
1295 { let (op,clt) = $2 in
1296 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1297 Ast0.set_arg_exp $3,false)) }
1298 | unary_expr(r,pe) TEq assign_expr_bis
1301 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1304 cond_expr(eexpr,dot_expressions) { $1 }
1305 | unary_expr(eexpr,dot_expressions) TAssign assign_expr_bis
1306 { let (op,clt) = $2 in
1307 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1308 Ast0.set_arg_exp $3,false)) }
1309 | unary_expr(eexpr,dot_expressions) TEq assign_expr_bis
1312 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1315 arith_expr(r,pe) { $1 }
1316 | l=arith_expr(r,pe) w=TWhy t=option(eexpr) dd=TDotDot r=cond_expr(r,pe)
1317 { Ast0.wrap(Ast0.CondExpr (l, P.clt2mcode "?" w, t,
1318 P.clt2mcode ":" dd, r)) }
1321 cast_expr(r,pe) { $1 }
1322 | arith_expr(r,pe) TMul arith_expr(r,pe)
1323 { P.arith_op Ast.Mul $1 $2 $3 }
1324 | arith_expr(r,pe) TDmOp arith_expr(r,pe)
1325 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1326 | arith_expr(r,pe) TPlus arith_expr(r,pe)
1327 { P.arith_op Ast.Plus $1 $2 $3 }
1328 | arith_expr(r,pe) TMinus arith_expr(r,pe)
1329 { P.arith_op Ast.Minus $1 $2 $3 }
1330 | arith_expr(r,pe) TShLOp arith_expr(r,pe)
1331 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1332 | arith_expr(r,pe) TShROp arith_expr(r,pe)
1333 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1334 | arith_expr(r,pe) TLogOp arith_expr(r,pe)
1335 { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
1336 | arith_expr(r,pe) TEqEq arith_expr(r,pe)
1337 { P.logic_op Ast.Eq $1 $2 $3 }
1338 | arith_expr(r,pe) TNotEq arith_expr(r,pe)
1339 { P.logic_op Ast.NotEq $1 $2 $3 }
1340 | arith_expr(r,pe) TAnd arith_expr(r,pe)
1341 { P.arith_op Ast.And $1 $2 $3 }
1342 | arith_expr(r,pe) TOr arith_expr(r,pe)
1343 { P.arith_op Ast.Or $1 $2 $3 }
1344 | arith_expr(r,pe) TXor arith_expr(r,pe)
1345 { P.arith_op Ast.Xor $1 $2 $3 }
1346 | arith_expr(r,pe) TAndLog arith_expr(r,pe)
1347 { P.logic_op Ast.AndLog $1 $2 $3 }
1348 | arith_expr(r,pe) TOrLog arith_expr(r,pe)
1349 { P.logic_op Ast.OrLog $1 $2 $3 }
1352 unary_expr(r,pe) { $1 }
1353 | lp=TOPar t=ctype rp=TCPar e=cast_expr(r,pe)
1354 { Ast0.wrap(Ast0.Cast (P.clt2mcode "(" lp, t,
1355 P.clt2mcode ")" rp, e)) }
1358 postfix_expr(r,pe) { $1 }
1359 | TInc unary_expr(r,pe)
1360 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
1361 | TDec unary_expr(r,pe)
1362 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
1363 | unary_op cast_expr(r,pe)
1364 { let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
1365 | TBang unary_expr(r,pe)
1366 { let mcode = P.clt2mcode Ast.Not $1 in
1367 Ast0.wrap(Ast0.Unary($2, mcode)) }
1368 | TSizeof unary_expr(r,pe)
1369 { Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
1370 | s=TSizeof lp=TOPar t=ctype rp=TCPar
1371 { Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
1372 P.clt2mcode "(" lp,t,
1373 P.clt2mcode ")" rp)) }
1375 unary_op: TAnd { P.clt2mcode Ast.GetRef $1 }
1376 | TMul { P.clt2mcode Ast.DeRef $1 }
1377 | TPlus { P.clt2mcode Ast.UnPlus $1 }
1378 | TMinus { P.clt2mcode Ast.UnMinus $1 }
1379 | TTilde { P.clt2mcode Ast.Tilde $1 }
1382 primary_expr(r,pe) { $1 }
1383 | postfix_expr(r,pe) TOCro eexpr TCCro
1384 { Ast0.wrap(Ast0.ArrayAccess ($1,P.clt2mcode "[" $2,$3,
1385 P.clt2mcode "]" $4)) }
1386 | postfix_expr(r,pe) TDot ident
1387 { Ast0.wrap(Ast0.RecordAccess($1, P.clt2mcode "." $2, $3)) }
1388 | postfix_expr(r,pe) TPtrOp ident
1389 { Ast0.wrap(Ast0.RecordPtAccess($1, P.clt2mcode "->" $2,
1391 | postfix_expr(r,pe) TInc
1392 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Inc $2)) }
1393 | postfix_expr(r,pe) TDec
1394 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Dec $2)) }
1395 | postfix_expr(r,pe) TOPar eexpr_list_option TCPar
1396 { Ast0.wrap(Ast0.FunCall($1,P.clt2mcode "(" $2,
1398 P.clt2mcode ")" $4)) }
1400 primary_expr(recurser,primary_extra):
1401 func_ident { Ast0.wrap(Ast0.Ident($1)) }
1403 { let (x,clt) = $1 in
1404 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1406 { let (x,clt) = $1 in
1407 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Float x) clt)) }
1409 { let (x,clt) = $1 in
1410 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.String x) clt)) }
1412 { let (x,clt) = $1 in
1413 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Char x) clt)) }
1415 { let (nm,constraints,pure,ty,clt) = $1 in
1417 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
1419 { let (nm,constraints,pure,clt) = $1 in
1420 Ast0.wrap(Ast0.MetaErr(P.clt2mcode nm clt,constraints,pure)) }
1422 { let (nm,constraints,pure,ty,clt) = $1 in
1424 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
1426 { let (nm,constraints,pure,ty,clt) = $1 in
1428 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
1430 { let (nm,constraints,pure,ty,clt) = $1 in
1432 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.LocalID,pure)) }
1434 { Ast0.wrap(Ast0.Paren(P.clt2mcode "(" $1,$2,
1435 P.clt2mcode ")" $3)) }
1436 | TOPar0 midzero_list(recurser,eexpr) TCPar0
1437 { let (mids,code) = $2 in
1438 Ast0.wrap(Ast0.DisjExpr(P.clt2mcode "(" $1,
1440 P.clt2mcode ")" $3)) }
1441 | primary_extra { $1 }
1444 r=no_dot_start_end(dexpr,edots_when(dotter,eexpr)) { r }
1447 no_dot_start_end(grammar,dotter):
1448 g=grammar dg=list(pair(dotter,grammar))
1449 { function dot_builder ->
1450 g :: (List.concat(List.map (function (d,g) -> [dot_builder d;g]) dg)) }
1452 /*****************************************************************************/
1458 | TIdentifier { "identifier" }
1459 | TExpression { "expression" }
1460 | TStatement { "statement" }
1461 | TFunction { "function" }
1462 | TLocal { "local" }
1464 | TParameter { "parameter" }
1465 | TIdExpression { "idexpression" }
1466 | TInitialiser { "initialiser" }
1468 | TFresh { "fresh" }
1469 | TConstant { "constant" }
1470 | TError { "error" }
1471 | TWords { "words" }
1473 | TContext { "context" }
1474 | TGenerated { "generated" }
1475 | TTypedef { "typedef" }
1476 | TDeclarer { "declarer" }
1477 | TIterator { "iterator" }
1479 | TPosition { "position" }
1482 TRuleName TDot pure_ident { (Some $1,P.id2name $3) }
1483 | TRuleName TDot pure_ident_kwd { (Some $1,$3) }
1485 pure_ident_or_meta_ident:
1486 pure_ident { (None,P.id2name $1) }
1487 | pure_ident_kwd { (None,$1) }
1490 pure_ident_or_meta_ident_with_seed:
1491 pure_ident_or_meta_ident { ($1,Ast.NoVal) }
1492 | pure_ident_or_meta_ident TEq
1493 separated_nonempty_list(TCppConcatOp,seed_elem)
1495 [Ast.SeedString s] -> ($1,Ast.StringSeed s)
1496 | _ -> ($1,Ast.ListSeed $3) }
1499 TString { let (x,_) = $1 in Ast.SeedString x }
1500 | TMetaId { let (x,_,_,_) = $1 in Ast.SeedId x }
1501 | TRuleName TDot pure_ident
1502 { let nm = ($1,P.id2name $3) in
1503 P.check_meta(Ast.MetaIdDecl(Ast.NONE,nm));
1506 pure_ident_or_meta_ident_with_x_eq(x_eq):
1507 i=pure_ident_or_meta_ident l=loption(x_eq)
1512 pure_ident_or_meta_ident_with_econstraint(x_eq):
1513 i=pure_ident_or_meta_ident optc=option(x_eq)
1516 None -> (i, Ast0.NoConstraint)
1520 pure_ident_or_meta_ident_with_idconstraint_virt(constraint_type):
1521 i=pure_ident_or_meta_ident c=option(constraint_type)
1525 None -> (i, Ast.IdNoConstraint)
1526 | Some constraint_ -> (i,constraint_))
1528 | TVirtual TDot pure_ident { Common.Right (P.id2name $3) }
1530 pure_ident_or_meta_ident_with_idconstraint(constraint_type):
1531 i=pure_ident_or_meta_ident c=option(constraint_type)
1534 None -> (i, Ast.IdNoConstraint)
1535 | Some constraint_ -> (i,constraint_)
1539 re=regexp_eqid {Ast.IdRegExpConstraint re}
1545 then failwith "constraints not allowed in iso file");
1546 (if !Data.in_generating
1547 then failwith "constraints not allowed in a generated rule file");
1548 let (s,_) = re in Ast.IdRegExp (s,Str.regexp s)
1550 | TTildeExclEq re=TString
1552 then failwith "constraints not allowed in iso file");
1553 (if !Data.in_generating
1554 then failwith "constraints not allowed in a generated rule file");
1555 let (s,_) = re in Ast.IdNotRegExp (s,Str.regexp s)
1559 TNotEq i=pure_ident_or_meta_ident
1561 then failwith "constraints not allowed in iso file");
1562 (if !Data.in_generating
1563 (* pb: constraints not stored with metavars; too lazy to search for
1564 them in the pattern *)
1565 then failwith "constraints not allowed in a generated rule file");
1569 P.check_inherited_constraint i
1570 (function mv -> Ast.MetaIdDecl(Ast.NONE,mv)) in
1571 Ast.IdNegIdSet([],[i])
1572 | (None,i) -> Ast.IdNegIdSet([i],[])) }
1573 | TNotEq TOBrace l=comma_list(pure_ident_or_meta_ident) TCBrace
1575 then failwith "constraints not allowed in iso file");
1576 (if !Data.in_generating
1577 then failwith "constraints not allowed in a generated rule file");
1580 (function (str,meta) ->
1582 (Some rn,id) as i ->
1584 P.check_inherited_constraint i
1585 (function mv -> Ast.MetaIdDecl(Ast.NONE,mv)) in
1587 | (None,i) -> (i::str,meta))
1589 Ast.IdNegIdSet(str,meta)
1592 re_or_not_eqe_or_sub:
1593 re=regexp_eqid {Ast0.NotIdCstrt re}
1594 | ne=not_eqe {Ast0.NotExpCstrt ne}
1595 | s=sub {Ast0.SubExpCstrt s}
1598 ceq=not_ceq {Ast0.NotExpCstrt ceq}
1599 | s=sub {Ast0.SubExpCstrt s}
1604 then failwith "constraints not allowed in iso file");
1605 (if !Data.in_generating
1606 then failwith "constraints not allowed in a generated rule file");
1607 [Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))]
1609 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1611 then failwith "constraints not allowed in iso file");
1612 (if !Data.in_generating
1613 then failwith "constraints not allowed in a generated rule file");
1616 Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))))
1621 TNotEq i=ident_or_const
1623 then failwith "constraints not allowed in iso file");
1624 (if !Data.in_generating
1625 then failwith "constraints not allowed in a generated rule file");
1627 | TNotEq TOBrace l=comma_list(ident_or_const) TCBrace
1629 then failwith "constraints not allowed in iso file");
1630 (if !Data.in_generating
1631 then failwith "constraints not allowed in a generated rule file");
1635 (* has to be inherited because not clear how to check subterm constraints
1636 in the functorized CTL engine, so need the variable to be bound
1637 already when bind the subterm constrained metavariable *)
1640 then failwith "constraints not allowed in iso file");
1641 (if !Data.in_generating
1642 then failwith "constraints not allowed in a generated rule file");
1644 P.check_inherited_constraint i
1645 (function mv -> Ast.MetaExpDecl(Ast.NONE,mv,None)) in
1647 | TSub TOBrace l=comma_list(meta_ident) TCBrace
1649 then failwith "constraints not allowed in iso file");
1650 (if !Data.in_generating
1651 then failwith "constraints not allowed in a generated rule file");
1654 P.check_inherited_constraint i
1655 (function mv -> Ast.MetaExpDecl(Ast.NONE,mv,None)))
1659 i=pure_ident { Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))) }
1661 { let (x,clt) = $1 in
1662 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1667 then failwith "constraints not allowed in iso file");
1668 (if !Data.in_generating
1669 then failwith "constraints not allowed in a generated rule file");
1671 P.check_inherited_constraint i
1672 (function mv -> Ast.MetaPosDecl(Ast.NONE,mv)) in
1674 | TNotEq TOBrace l=comma_list(meta_ident) TCBrace
1676 then failwith "constraints not allowed in iso file");
1677 (if !Data.in_generating
1678 then failwith "constraints not allowed in a generated rule file");
1681 P.check_inherited_constraint i
1682 (function mv -> Ast.MetaPosDecl(Ast.NONE,mv)))
1685 func_ident: pure_ident
1686 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1688 { let (nm,constraints,pure,clt) = $1 in
1689 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1691 { let (nm,constraints,pure,clt) = $1 in
1692 Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
1694 { let (nm,constraints,pure,clt) = $1 in
1696 (Ast0.MetaLocalFunc(P.clt2mcode nm clt,constraints,pure)) }
1699 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1701 { let (nm,constraints,pure,clt) = $1 in
1702 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1706 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1708 { let (nm,constraints,pure,clt) = $1 in
1709 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1713 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1715 { let (nm,constraints,pure,clt) = $1 in
1716 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1720 { Ast0.wrap(Ast0.TypeName(P.id2mcode $1)) }
1722 { let (nm,pure,clt) = $1 in
1723 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
1725 /*****************************************************************************/
1728 empty_list_start(one_dec(decl),TEllipsis)
1732 (fun _ d -> Ast0.wrap(Ast0.Pdots(P.clt2mcode "..." d)))
1733 (fun c -> Ast0.PComma c))) }
1738 { let (nm,lenname,pure,clt) = $1 in
1739 let nm = P.clt2mcode nm clt in
1742 Ast.AnyLen -> Ast0.AnyListLen
1743 | Ast.MetaLen nm -> Ast0.MetaListLen(P.clt2mcode nm clt)
1744 | Ast.CstLen n -> Ast0.CstListLen n in
1745 Ast0.wrap(Ast0.MetaParamList(nm,lenname,pure)) }
1747 /* ---------------------------------------------------------------------- */
1748 /* comma list parser, used for fn params, fn args, enums, initlists,
1751 /* enums: enum_decl, edots_when(TEllipsis,enum_decl_one)
1752 fun s d -> P.mkedots "..." d
1753 fun c -> Ast0.EComma c
1756 empty_list_start(elem,dotter):
1757 /* empty */ { fun build_dots build_comma -> [] }
1758 | nonempty_list_start(elem,dotter) { $1 }
1760 nonempty_list_start(elem,dotter): /* dots allowed */
1761 elem { fun build_dots build_comma -> [$1] }
1763 { fun build_dots build_comma ->
1764 $1::[Ast0.wrap(build_comma(P.clt2mcode "," $2))] }
1765 | elem TComma nonempty_list_start(elem,dotter)
1766 { fun build_dots build_comma ->
1767 $1::(Ast0.wrap(build_comma(P.clt2mcode "," $2)))::
1768 ($3 build_dots build_comma) }
1769 | TNothing nonempty_list_start(elem,dotter) { $2 }
1770 | d=dotter { fun build_dots build_comma -> [(build_dots "..." d)] }
1772 { fun build_dots build_comma ->
1773 [(build_dots "..." d);Ast0.wrap(build_comma(P.clt2mcode "," $2))] }
1774 | d=dotter TComma r=continue_list(elem,dotter)
1775 { fun build_dots build_comma ->
1776 (build_dots "..." d)::
1777 (Ast0.wrap(build_comma(P.clt2mcode "," $2)))::
1778 (r build_dots build_comma) }
1780 continue_list(elem,dotter): /* dots not allowed */
1781 elem { fun build_dots build_comma -> [$1] }
1783 { fun build_dots build_comma ->
1784 $1::[Ast0.wrap(build_comma(P.clt2mcode "," $2))] }
1785 | elem TComma nonempty_list_start(elem,dotter)
1786 { fun build_dots build_comma ->
1787 $1::(Ast0.wrap(build_comma(P.clt2mcode "," $2)))::
1788 ($3 build_dots build_comma) }
1789 | TNothing nonempty_list_start(elem,dotter) { $2 }
1791 /* ---------------------------------------------------------------------- */
1793 /* error words make it complicated to be able to use error as a metavariable
1794 name or a type in a metavariable list; for that we would like to allow TError
1795 as an ident, but that makes conflicts with this rule. To add back error words,
1796 need to find some appropriate delimiter for it, but it has not been used much
1799 TError TWords TEq TOCro cl=comma_list(dexpr) TCCro
1800 { [Ast0.wrap(Ast0.ERRORWORDS(cl))] }
1803 /* ---------------------------------------------------------------------- */
1804 /* sequences of statements and expressions */
1806 /* There are number of cases that must be considered:
1809 Dots and nests allowed at the beginning or end
1810 Expressions allowed at the beginning or end
1811 One function allowed, by itself
1813 Dots and nests allowed at the beginning or end
1814 Expressions not allowed at the beginning or end
1815 Functions not allowed
1816 3. The body of a nest:
1817 Dots and nests not allowed at the beginning or end
1818 Expressions allowed at the beginning or end
1819 Functions not allowed
1821 Dots and nests not allowed at the beginning but allowed at the end
1822 Expressions allowed at the beginning or end
1823 Functions not allowed
1825 These are implemented by the rules minus_toplevel_sequence,
1826 plus_toplevel_sequence, function_body_sequence, nest_body_sequence, and
1829 /* ------------------------------------------------------------------------ */
1830 /* Minus top level */
1832 /* doesn't allow only ... */
1834 fundecl { [Ast0.wrap(Ast0.DECL($1))] }
1835 | ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1836 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1837 | toplevel_seq_startne(toplevel_after_dots_init)
1838 { List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1 }
1840 toplevel_seq_startne(after_dots_init):
1841 a=stm_dots_ell b=after_dots_init { a::b }
1842 | a=stm_dots_nest b=after_dots_init { a::b }
1843 | a=stm_dots_nest { [a] }
1844 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1845 | decl_statement_expr toplevel_after_stm { $1@$2 }
1847 toplevel_seq_start(after_dots_init):
1848 stm_dots after_dots_init { $1::$2 }
1849 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1850 | decl_statement_expr toplevel_after_stm { $1@$2 }
1852 toplevel_after_dots_init:
1853 TNothing toplevel_after_exp {$2}
1854 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1855 | decl_statement_expr toplevel_after_stm {$1@$2}
1859 | stm_dots toplevel_after_dots {$1::$2}
1861 toplevel_after_dots:
1863 | TNothing toplevel_after_exp {$2}
1864 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1865 | decl_statement_expr toplevel_after_stm {$1@$2}
1869 | stm_dots toplevel_after_dots {$1::$2}
1870 | decl_statement toplevel_after_stm {$1@$2}
1873 TOInit initialize_list TCBrace
1874 { if P.struct_initializer $2
1876 let il = P.drop_dot_commas $2 in
1877 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
1879 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) }
1881 /* ------------------------------------------------------------------------ */
1882 /* Plus top level */
1884 /* does allow only ... also allows multiple top-level functions */
1886 ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1887 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1888 | stm_dots plus_after_dots
1889 { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1890 | expr plus_after_exp
1891 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1892 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1893 | decl_statement_expr plus_after_stm
1894 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1898 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1902 | TNothing plus_after_exp {$2}
1903 | expr plus_after_exp
1904 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1905 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1906 | decl_statement_expr plus_after_stm
1907 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1911 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1912 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1913 | decl_statement plus_after_stm
1914 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1916 /* ------------------------------------------------------------------------ */
1920 fun_after_stm { Ast0.wrap(Ast0.DOTS($1)) }
1924 | stm_dots fun_after_dots {$1::$2}
1925 | decl_statement fun_after_stm {$1@$2}
1929 | TNothing fun_after_exp {$2}
1930 | expr fun_after_exp {Ast0.wrap(Ast0.Exp($1))::$2}
1931 | decl_statement_expr fun_after_stm {$1@$2}
1934 stm_dots fun_after_dots {$1::$2}
1936 /* hack to allow mixing statements and expressions in an or */
1939 | TNothing fun_after_exp_or {$2}
1940 | expr fun_after_exp_or {Ast0.wrap(Ast0.Exp($1))::$2}
1941 | decl_statement_expr fun_after_stm {$1@$2}
1945 | stm_dots fun_after_dots {$1::$2}
1947 /* ------------------------------------------------------------------------ */
1951 nest_after_dots { Ast0.wrap(Ast0.DOTS($1)) }
1954 decl_statement_expr nest_after_stm {$1@$2}
1955 | TNothing nest_after_exp {$2}
1956 | expr nest_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1960 | stm_dots nest_after_dots {$1::$2}
1961 | decl_statement nest_after_stm {$1@$2}
1965 | stm_dots nest_after_dots {$1::$2}
1967 /* ------------------------------------------------------------------------ */
1971 expr toplevel_after_exp
1972 { Ast0.wrap(Ast0.DOTS((Ast0.wrap(Ast0.Exp($1)))::$2)) }
1973 | decl_statement toplevel_after_stm
1974 { Ast0.wrap(Ast0.DOTS($1@$2)) }
1976 /* ---------------------------------------------------------------------- */
1978 /* arg expr. may contain a type or a explist metavariable */
1980 dexpr { Ast0.set_arg_exp $1 }
1982 { let (nm,lenname,pure,clt) = $1 in
1983 let nm = P.clt2mcode nm clt in
1986 Ast.AnyLen -> Ast0.AnyListLen
1987 | Ast.MetaLen nm -> Ast0.MetaListLen(P.clt2mcode nm clt)
1988 | Ast.CstLen n -> Ast0.CstListLen n in
1989 Ast0.wrap(Ast0.MetaExprList(nm,lenname,pure)) }
1991 { Ast0.set_arg_exp(Ast0.wrap(Ast0.TypeExp($1))) }
1994 empty_list_start(aexpr,TEllipsis)
1998 (fun _ d -> Ast0.wrap(Ast0.Edots(P.clt2mcode "..." d,None)))
1999 (fun c -> Ast0.EComma c))) }
2001 /****************************************************************************/
2003 // non-empty lists - drop separator
2005 separated_nonempty_list(TComma,elem) { $1 }
2007 midzero_list(elem,aft):
2008 a=elem b=list(mzl(aft))
2009 { let (mids,code) = List.split b in (mids,(a::code)) }
2012 a=TMid0 b=elem { (P.clt2mcode "|" a, b) }
2014 edots_when(dotter,when_grammar):
2015 d=dotter { (d,None) }
2016 | d=dotter TWhen TNotEq w=when_grammar TLineEnd { (d,Some w) }
2018 whens(when_grammar,simple_when_grammar,any_strict):
2019 TWhen TNotEq w=when_grammar TLineEnd { [Ast0.WhenNot w] }
2020 | TWhen TEq w=simple_when_grammar TLineEnd { [Ast0.WhenAlways w] }
2021 | TWhen comma_list(any_strict) TLineEnd
2022 { List.map (function x -> Ast0.WhenModifier(x)) $2 }
2023 | TWhenTrue TNotEq e = eexpr TLineEnd { [Ast0.WhenNotTrue e] }
2024 | TWhenFalse TNotEq e = eexpr TLineEnd { [Ast0.WhenNotFalse e] }
2027 TAny { Ast.WhenAny }
2028 | TStrict { Ast.WhenStrict }
2029 | TForall { Ast.WhenForall }
2030 | TExists { Ast.WhenExists }
2032 /*****************************************************************************
2035 *****************************************************************************/
2038 TIsoExpression e1=eexpr el=list(iso(eexpr)) EOF
2039 { let fn x = Ast0.ExprTag x in P.iso_adjust fn fn e1 el }
2040 | TIsoArgExpression e1=eexpr el=list(iso(eexpr)) EOF
2041 { let fn x = Ast0.ArgExprTag x in P.iso_adjust fn fn e1 el }
2042 | TIsoTestExpression e1=eexpr el=list(iso(eexpr)) EOF
2043 { let fn x = Ast0.TestExprTag x in P.iso_adjust fn fn e1 el }
2044 | TIsoToTestExpression e1=eexpr el=list(iso(eexpr)) EOF
2045 { let ffn x = Ast0.ExprTag x in
2046 let fn x = Ast0.TestExprTag x in
2047 P.iso_adjust ffn fn e1 el }
2048 | TIsoStatement s1=single_statement sl=list(iso(single_statement)) EOF
2049 { let fn x = Ast0.StmtTag x in P.iso_adjust fn fn s1 sl }
2050 | TIsoType t1=ctype tl=list(iso(ctype)) EOF
2051 { let fn x = Ast0.TypeCTag x in P.iso_adjust fn fn t1 tl }
2052 | TIsoTopLevel e1=nest_start el=list(iso(nest_start)) EOF
2053 { let fn x = Ast0.DotsStmtTag x in P.iso_adjust fn fn e1 el }
2054 | TIsoDeclaration d1=decl_var dl=list(iso(decl_var)) EOF
2055 { let check_one = function
2059 (Semantic_cocci.Semantic
2060 "only one variable per declaration in an isomorphism rule") in
2061 let d1 = check_one d1 in
2065 Common.Left x -> Common.Left(check_one x)
2066 | Common.Right x -> Common.Right(check_one x))
2068 let fn x = Ast0.DeclTag x in P.iso_adjust fn fn d1 dl }
2071 TIso t=term { Common.Left t }
2072 | TRightIso t=term { Common.Right t }
2074 /*****************************************************************************
2077 *****************************************************************************/
2079 never_used: TPragma { () }
2080 | TPArob TMetaPos { () }
2081 | TScriptData { () }
2084 py=pure_ident TMPtVirg
2085 { ((Some (P.id2name py), None), None) }
2086 | py=pure_ident script_name_decl TMPtVirg
2087 { ((Some (P.id2name py), None), Some $2) }
2088 | TOPar TUnderscore TComma ast=pure_ident TCPar script_name_decl TMPtVirg
2089 { ((None, Some (P.id2name ast)), Some $6) }
2090 | TOPar str=pure_ident TComma TUnderscore TCPar script_name_decl TMPtVirg
2091 { ((Some (P.id2name str), None), Some $6) }
2092 | TOPar str=pure_ident TComma ast=pure_ident TCPar script_name_decl TMPtVirg
2093 { ((Some (P.id2name str), Some (P.id2name ast)), Some $6) }
2096 TShLOp TRuleName TDot cocci=pure_ident
2097 { let nm = P.id2name cocci in
2098 let mv = Parse_aux.lookup $2 nm in
2100 | TShLOp TVirtual TDot cocci=pure_ident
2101 { let nm = P.id2name cocci in
2102 let name = ("virtual", nm) in
2103 let mv = Ast.MetaIdDecl(Ast.NONE,name) in