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
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 (* ensure that the names of virtual and real rules don't overlap *)
269 (function name -> Hashtbl.add Data.all_metadecls name [])
275 kindfn=metakind ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
276 { P.create_metadec ar ispure kindfn ids }
277 | kindfn=metakind_fresh ids=comma_list(pure_ident_or_meta_ident_with_seed)
279 { P.create_fresh_metadec kindfn ids }
280 | ar=arity ispure=pure
281 kindfn=metakind_atomic_maybe_virt
283 comma_list(pure_ident_or_meta_ident_with_idconstraint_virt(re_or_not_eqid))
285 { let (normal,virt) = Common.partition_either (fun x -> x) ids in
286 let (idfn,virtfn) = kindfn in
288 (P.create_metadec_with_constraints ar ispure idfn normal cr) @
289 (P.create_metadec_virt ar ispure virtfn virt cr) }
290 | ar=arity ispure=pure
291 kindfn=metakind_atomic
292 ids=comma_list(pure_ident_or_meta_ident_with_idconstraint(re_or_not_eqid))
294 { P.create_metadec_with_constraints ar ispure kindfn ids }
295 | ar=arity ispure=pure
296 kindfn=metakind_atomic_expi
297 ids=comma_list(pure_ident_or_meta_ident_with_econstraint(re_or_not_eqe_or_sub))
299 { P.create_metadec_with_constraints ar ispure kindfn ids }
300 | ar=arity ispure=pure
301 kindfn=metakind_atomic_expe
302 ids=comma_list(pure_ident_or_meta_ident_with_econstraint(not_ceq_or_sub))
304 { P.create_metadec_with_constraints ar ispure kindfn ids }
305 | ar=arity TPosition a=option(TPosAny)
306 ids=comma_list(pure_ident_or_meta_ident_with_x_eq(not_pos)) TMPtVirg
307 (* pb: position variables can't be inherited from normal rules, and then
308 there is no way to inherit from a generated rule, so there is no point
309 to have a position variable *)
310 { (if !Data.in_generating
311 then failwith "position variables not allowed in a generated rule file");
312 let kindfn arity name pure check_meta constraints =
313 let tok = check_meta(Ast.MetaPosDecl(arity,name)) in
314 let any = match a with None -> Ast.PER | Some _ -> Ast.ALL in
315 !Data.add_pos_meta name constraints any; tok in
316 P.create_metadec_with_constraints ar false kindfn ids }
317 | ar=arity ispure=pure
318 TParameter Tlist TOCro len=list_len TCCro
319 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
320 { P.create_len_metadec ar ispure
321 (fun lenname arity name pure check_meta ->
322 let tok = check_meta(Ast.MetaParamListDecl(arity,name,lenname)) in
323 !Data.add_paramlist_meta name lenname pure; tok)
325 | ar=arity ispure=pure
326 TExpression Tlist TOCro len=list_len TCCro
327 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
328 { P.create_len_metadec ar ispure
329 (fun lenname arity name pure check_meta ->
330 let tok = check_meta(Ast.MetaExpListDecl(arity,name,lenname)) in
331 !Data.add_explist_meta name lenname pure; tok)
335 pure_ident_or_meta_ident { Common.Left $1 }
336 | TInt { let (x,clt) = $1 in Common.Right (int_of_string x) }
338 %inline metakind_fresh:
340 { (fun name check_meta seed ->
341 let tok = check_meta(Ast.MetaFreshIdDecl(name,seed)) in
342 !Data.add_fresh_id_meta name; tok) }
344 /* metavariable kinds with no constraints, etc */
347 { (fun arity name pure check_meta ->
348 let tok = check_meta(Ast.MetaParamDecl(arity,name)) in
349 !Data.add_param_meta name pure; tok) }
351 { (fun arity name pure check_meta ->
352 let len = Ast.AnyLen in
353 let tok = check_meta(Ast.MetaParamListDecl(arity,name,len)) in
354 !Data.add_paramlist_meta name len pure; tok) }
356 { (fun arity name pure check_meta ->
357 let len = Ast.AnyLen in
358 let tok = check_meta(Ast.MetaExpListDecl(arity,name,len)) in
359 !Data.add_explist_meta name len pure; tok) }
361 { (fun arity name pure check_meta ->
362 let tok = check_meta(Ast.MetaTypeDecl(arity,name)) in
363 !Data.add_type_meta name pure; tok) }
365 { (fun arity name pure check_meta ->
366 let tok = check_meta(Ast.MetaInitDecl(arity,name)) in
367 !Data.add_init_meta name pure; tok) }
369 { (fun arity name pure check_meta ->
370 let tok = check_meta(Ast.MetaStmDecl(arity,name)) in
371 !Data.add_stm_meta name pure; tok) }
373 { (fun arity name pure check_meta ->
374 let tok = check_meta(Ast.MetaDeclDecl(arity,name)) in
375 !Data.add_decl_meta name pure; tok) }
377 { (fun arity name pure check_meta ->
378 let tok = check_meta(Ast.MetaFieldDecl(arity,name)) in
379 !Data.add_field_meta name pure; tok) }
381 { (fun arity name pure check_meta ->
382 let tok = check_meta(Ast.MetaStmListDecl(arity,name)) in
383 !Data.add_stmlist_meta name pure; tok) }
385 { (fun arity (_,name) pure check_meta ->
386 if arity = Ast.NONE && pure = Ast0.Impure
387 then (!Data.add_type_name name; [])
388 else raise (Semantic_cocci.Semantic "bad typedef")) }
390 { (fun arity (_,name) pure check_meta ->
391 if arity = Ast.NONE && pure = Ast0.Impure
392 then (!Data.add_declarer_name name; [])
393 else raise (Semantic_cocci.Semantic "bad declarer")) }
395 { (fun arity (_,name) pure check_meta ->
396 if arity = Ast.NONE && pure = Ast0.Impure
397 then (!Data.add_iterator_name name; [])
398 else raise (Semantic_cocci.Semantic "bad iterator")) }
400 %inline metakind_atomic_maybe_virt:
403 let idfn arity name pure check_meta constraints =
404 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
405 !Data.add_id_meta name constraints pure; tok in
406 let virtfn arity name pure check_meta virtual_env =
408 let vl = List.assoc name virtual_env in
409 !Data.add_virt_id_meta_found name vl; []
411 let name = ("virtual",name) in
412 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
413 !Data.add_virt_id_meta_not_found name pure; tok in
416 %inline metakind_atomic:
418 { (fun arity name pure check_meta constraints ->
419 let tok = check_meta(Ast.MetaFuncDecl(arity,name)) in
420 !Data.add_func_meta name constraints pure; tok) }
422 { (fun arity name pure check_meta constraints ->
423 let tok = check_meta(Ast.MetaLocalFuncDecl(arity,name)) in
424 !Data.add_local_func_meta name constraints pure;
427 { (fun arity name pure check_meta constraints ->
428 let tok = check_meta(Ast.MetaDeclarerDecl(arity,name)) in
429 !Data.add_declarer_meta name constraints pure; tok) }
431 { (fun arity name pure check_meta constraints ->
432 let tok = check_meta(Ast.MetaIteratorDecl(arity,name)) in
433 !Data.add_iterator_meta name constraints pure; tok) }
435 %inline metakind_atomic_expi:
437 { (fun arity name pure check_meta constraints ->
438 let tok = check_meta(Ast.MetaErrDecl(arity,name)) in
439 !Data.add_err_meta name constraints pure; tok) }
440 | l=option(TLocal) TIdExpression ty=ioption(meta_exp_type)
441 { (fun arity name pure check_meta constraints ->
444 !Data.add_idexp_meta ty name constraints pure;
445 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
447 !Data.add_local_idexp_meta ty name constraints pure;
448 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
449 | l=option(TLocal) TIdExpression m=nonempty_list(TMul)
450 { (fun arity name pure check_meta constraints ->
451 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
454 !Data.add_idexp_meta ty name constraints pure;
455 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
457 !Data.add_local_idexp_meta ty name constraints pure;
458 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
459 | TExpression ty=expression_type
460 { (fun arity name pure check_meta constraints ->
461 let ty = Some [ty] in
462 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
463 !Data.add_exp_meta ty name constraints pure; tok) }
464 | TConstant ty=ioption(meta_exp_type)
465 { (fun arity name pure check_meta constraints ->
466 let tok = check_meta(Ast.MetaConstDecl(arity,name,ty)) in
467 !Data.add_const_meta ty name constraints pure; tok) }
470 m=nonempty_list(TMul) { P.ty_pointerify Type_cocci.Unknown m }
472 { P.ty_pointerify (Type_cocci.EnumName Type_cocci.NoName) m }
473 | Tstruct m=list(TMul)
475 (Type_cocci.StructUnionName (Type_cocci.Struct,Type_cocci.NoName)) m }
476 | Tunion m=list(TMul)
478 (Type_cocci.StructUnionName (Type_cocci.Union,Type_cocci.NoName)) m }
480 %inline metakind_atomic_expe:
482 { (fun arity name pure check_meta constraints ->
483 let tok = check_meta(Ast.MetaExpDecl(arity,name,None)) in
484 !Data.add_exp_meta None name constraints pure; tok) }
485 | vl=meta_exp_type // no error if use $1 but doesn't type check
486 { (fun arity name pure check_meta constraints ->
488 (match constraints with
489 Ast0.NotExpCstrt constraints ->
492 match Ast0.unwrap c with
497 Type_cocci.BaseType(Type_cocci.IntType) -> true
498 | Type_cocci.BaseType(Type_cocci.ShortType) -> true
499 | Type_cocci.BaseType(Type_cocci.LongType) -> true
503 failwith "metavariable with int constraint must be an int"
507 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
508 !Data.add_exp_meta ty name constraints pure; tok)
513 { [Ast0_cocci.ast0_type_to_type t] }
514 | t=typedef_ctype TOCro TCCro
515 { [Type_cocci.Array (Ast0_cocci.ast0_type_to_type t)] }
516 | TOBrace t=comma_list(ctype) TCBrace m=list(TMul)
518 (function x -> P.ty_pointerify (Ast0_cocci.ast0_type_to_type x) m)
521 arity: TBang0 { Ast.UNIQUE }
523 | TPlus0 { Ast.MULTI }
524 | /* empty */ { Ast.NONE }
526 /* ---------------------------------------------------------------------- */
531 { Ast0.wrap(Ast0.BaseType(Ast.CharType,[P.clt2mcode "char" ty])) }
533 { Ast0.wrap(Ast0.BaseType(Ast.ShortType,[P.clt2mcode "short" ty])) }
535 { Ast0.wrap(Ast0.BaseType(Ast.IntType,[P.clt2mcode "int" ty])) }
537 { let (nm,pure,clt) = p in
538 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
539 | r=TRuleName TDot p=TIdent
540 { let nm = (r,P.id2name p) in
541 (* this is only possible when we are in a metavar decl. Otherwise,
542 it will be represented already as a MetaType *)
543 let _ = P.check_meta(Ast.MetaTypeDecl(Ast.NONE,nm)) in
544 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm (P.id2clt p),
545 Ast0.Impure (*will be ignored*))) }
547 { Ast0.wrap(Ast0.BaseType(Ast.LongType,[P.clt2mcode "long" ty])) }
548 | ty1=Tlong ty2=Tlong
552 [P.clt2mcode "long" ty1;P.clt2mcode "long" ty2])) }
557 { Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" ty])) }
559 { Ast0.wrap(Ast0.BaseType(Ast.DoubleType,[P.clt2mcode "double" ty])) }
561 { Ast0.wrap(Ast0.BaseType(Ast.FloatType,[P.clt2mcode "float" ty])) }
563 { Ast0.wrap(Ast0.BaseType(Ast.SizeType,[P.clt2mcode "size_t" ty])) }
565 { Ast0.wrap(Ast0.BaseType(Ast.SSizeType,[P.clt2mcode "ssize_t" ty])) }
567 { Ast0.wrap(Ast0.BaseType(Ast.PtrDiffType,[P.clt2mcode "ptrdiff_t" ty])) }
569 { Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, Some i)) }
570 | s=Tenum i=ioption(ident) l=TOBrace ids=enum_decl_list r=TCBrace
571 { (if i = None && !Data.in_iso
572 then failwith "enums must be named in the iso file");
573 Ast0.wrap(Ast0.EnumDef(Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, i)),
574 P.clt2mcode "{" l, ids, P.clt2mcode "}" r)) }
575 | s=struct_or_union i=ident
576 { Ast0.wrap(Ast0.StructUnionName(s, Some i)) }
577 | s=struct_or_union i=ioption(ident)
578 l=TOBrace d=struct_decl_list r=TCBrace
579 { (if i = None && !Data.in_iso
580 then failwith "structures must be named in the iso file");
581 Ast0.wrap(Ast0.StructUnionDef(Ast0.wrap(Ast0.StructUnionName(s, i)),
583 d, P.clt2mcode "}" r)) }
584 | s=TMetaType l=TOBrace d=struct_decl_list r=TCBrace
585 { let (nm,pure,clt) = s in
586 let ty = Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) in
587 Ast0.wrap(Ast0.StructUnionDef(ty,P.clt2mcode "{" l,d,P.clt2mcode "}" r)) }
589 { Ast0.wrap(Ast0.TypeName(P.id2mcode p)) }
593 r=Tsigned ty=signable_types
594 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,Some ty)) }
595 | r=Tunsigned ty=signable_types
596 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,Some ty)) }
597 | ty=signable_types { ty }
598 | ty=non_signable_types { ty }
601 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
602 { P.pointerify (P.make_cv cv ty) m }
604 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,None)) }
606 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,None)) }
607 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
608 { let (mids,code) = t in
610 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
612 /* signed, unsigned alone not allowed */
614 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
615 { P.pointerify (P.make_cv cv ty) m }
616 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
617 { let (mids,code) = t in
619 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
621 /* ---------------------------------------------------------------------- */
624 s=Tstruct { P.clt2mcode Ast.Struct s }
625 | u=Tunion { P.clt2mcode Ast.Union u }
629 | struct_decl_one { [$1] }
632 | TMetaField { P.meta_field $1 }
633 | t=ctype d=d_ident pv=TPtVirg
635 Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv)) }
636 | t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
637 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar pv=TPtVirg
641 (Ast0.FunctionPointer
642 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
643 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
644 Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv)) }
645 | cv=ioption(const_vol) i=pure_ident d=d_ident pv=TPtVirg
647 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
648 Ast0.wrap(Ast0.UnInit(None,fn idtype,id,P.clt2mcode ";" pv)) }
651 struct_decl_list_start { Ast0.wrap(Ast0.DOTS($1)) }
653 struct_decl_list_start:
655 | struct_decl struct_decl_list_start { $1@$2 }
656 | d=edots_when(TEllipsis,struct_decl_one) r=continue_struct_decl_list
657 { (P.mkddots_one "..." d)::r }
659 continue_struct_decl_list:
661 | struct_decl struct_decl_list_start { $1@$2 }
665 /* ---------------------------------------------------------------------- */
666 /* very restricted what kinds of expressions can appear in an enum decl */
669 | ident { Ast0.wrap(Ast0.Ident($1)) }
671 { let id = Ast0.wrap(Ast0.Ident($1)) in
674 (id,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,
678 ident { Ast0.wrap(Ast0.Ident($1)) }
680 { let (x,clt) = $1 in
681 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
683 { let (nm,constraints,pure,ty,clt) = $1 in
685 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
687 { let (nm,constraints,pure,ty,clt) = $1 in
689 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
691 { let (nm,constraints,pure,ty,clt) = $1 in
693 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
696 nonempty_list_start(enum_decl_one,edots_when(TEllipsis,enum_decl_one))
697 { Ast0.wrap(Ast0.DOTS($1 P.mkedots (fun c -> Ast0.EComma c))) }
699 /*****************************************************************************/
701 /* have to inline everything to avoid conflicts? switch to proper
702 declarations, statements, and expressions for the subterms */
706 b=loption(minus_start)
707 /*ew=loption(error_words)*/
708 { match f@b(*@ew*) with
709 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
710 | code -> Top_level.top_level code }
714 b=loption(plus_start)
715 /*ew=loption(error_words)*/
716 { Top_level.top_level (f@b(*@ew*)) }
721 /*ew=loption(error_words)*/
722 { match f@[b](*@ew*) with
723 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
724 | code -> Top_level.top_level code }
729 /*ew=loption(error_words)*/
730 { Top_level.top_level (f@[b](*@ew*)) }
735 (Ast0.FILEINFO(P.id2mcode $1,
741 (Ast0.Include(P.clt2mcode "#include"
742 (P.drop_pos (P.drop_aft (P.id2clt $1))),
743 let (arity,ln,lln,offset,col,strbef,straft,pos) =
746 (arity,ln,lln,offset,0,strbef,straft,pos) in
748 (Ast.Local (Parse_aux.str2inc (P.id2name $1)))
752 (Ast0.Include(P.clt2mcode "#include"
753 (P.drop_pos (P.drop_aft (P.id2clt $1))),
754 let (arity,ln,lln,offset,col,strbef,straft,pos) =
757 (arity,ln,lln,offset,0,strbef,straft,pos) in
759 (Ast.NonLocal (Parse_aux.str2inc (P.id2name $1)))
761 | d=defineop TLineEnd
762 { d (Ast0.wrap(Ast0.DOTS([]))) }
763 | d=defineop t=ctype TLineEnd
764 { let ty = Ast0.wrap(Ast0.TopExp(Ast0.wrap(Ast0.TypeExp(t)))) in
765 d (Ast0.wrap(Ast0.DOTS([ty]))) }
766 | defineop b=toplevel_seq_start(toplevel_after_dots) TLineEnd
770 (match Ast0.unwrap e with
772 [Ast0.rewrap e (Ast0.TopExp(Ast0.set_arg_exp (e1)))]
775 $1 (Ast0.wrap(Ast0.DOTS(body))) }
779 { let (clt,ident) = $1 in
783 (P.clt2mcode "#define" clt,
785 TMetaId((nm,constraints,pure,clt)) ->
786 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
788 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
791 (Semantic_cocci.Semantic
792 "unexpected name for a #define")),
793 Ast0.wrap Ast0.NoParams,
795 | TDefineParam define_param_list_option TCPar
796 { let (clt,ident,parenoff,parencol) = $1 in
797 (* clt is the start of the #define itself *)
798 let (arity,line,lline,offset,col,strbef,straft,pos) = clt in
801 (arity,line,lline,parenoff,parencol,[],[],Ast0.NoMetaPos) in
805 (P.clt2mcode "#define" clt,
807 TMetaId((nm,constraints,pure,clt)) ->
808 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
810 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
813 (Semantic_cocci.Semantic
814 "unexpected name for a #define")),
815 Ast0.wrap (Ast0.DParams (lp,$2,P.clt2mcode ")" $3)),body)) }
817 /* ---------------------------------------------------------------------- */
819 dparam: ident { Ast0.wrap(Ast0.DParam $1) }
821 define_param_list_option:
822 empty_list_start(dparam,TEllipsis)
826 (fun _ d -> Ast0.wrap(Ast0.DPdots(P.clt2mcode "," d)))
827 (fun c -> Ast0.DPComma c))) }
829 /*****************************************************************************/
832 s=ioption(storage) t=ctype
833 id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
838 (Ast0.FunctionType(Some t,
839 P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
840 id, P.clt2mcode ";" pt)) }
844 TFunDecl i=func_ident lp=TOPar d=decl_list(decl) rp=TCPar
845 lb=TOBrace b=fun_start rb=TCBrace
846 { P.verify_parameter_declarations (Ast0.undots d);
847 Ast0.wrap(Ast0.FunDecl((Ast0.default_info(),Ast0.context_befaft()),
849 P.clt2mcode "(" lp, d,
851 P.clt2mcode "{" lb, b,
852 P.clt2mcode "}" rb)) }
859 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
860 raise (Semantic_cocci.Semantic "duplicate storage")
861 with Not_found -> (Ast0.FStorage($1))::$2 }
862 | t=ctype r=fninfo_nt { (Ast0.FType(t))::r }
865 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
866 raise (Semantic_cocci.Semantic "duplicate inline")
867 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
870 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
871 raise (Semantic_cocci.Semantic "multiple attributes")
872 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
879 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
880 raise (Semantic_cocci.Semantic "duplicate storage")
881 with Not_found -> (Ast0.FStorage($1))::$2 }
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 "duplicate init")
891 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
894 s=Tstatic { P.clt2mcode Ast.Static s }
895 | s=Tauto { P.clt2mcode Ast.Auto s }
896 | s=Tregister { P.clt2mcode Ast.Register s }
897 | s=Textern { P.clt2mcode Ast.Extern s }
899 decl: t=ctype i=ident
900 { Ast0.wrap(Ast0.Param(t, Some i)) }
901 | t=ctype { (*verify in FunDecl*) Ast0.wrap(Ast0.Param(t, None)) }
902 | t=ctype lp=TOPar s=TMul i=ident rp=TCPar
903 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
906 (Ast0.FunctionPointer
907 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
908 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
909 Ast0.wrap(Ast0.Param(fnptr, Some i)) }
911 { let (nm,pure,clt) = $1 in
912 Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) }
916 | t=ctype lp=TOPar s=TMul rp=TCPar
917 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
920 (Ast0.FunctionPointer
921 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
922 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
923 Ast0.wrap(Ast0.Param(fnptr, None)) }
926 Tconst { P.clt2mcode Ast.Const $1 }
927 | Tvolatile { P.clt2mcode Ast.Volatile $1 }
929 /*****************************************************************************/
932 includes { $1 } /* shouldn't be allowed to be a single_statement... */
937 | TIf TOPar eexpr TCPar single_statement %prec TIf
938 { P.ifthen $1 $2 $3 $4 $5 }
939 | TIf TOPar eexpr TCPar single_statement TElse single_statement
940 { P.ifthenelse $1 $2 $3 $4 $5 $6 $7 }
941 | TFor TOPar option(eexpr) TPtVirg option(eexpr) TPtVirg
942 option(eexpr) TCPar single_statement
943 { P.forloop $1 $2 $3 $4 $5 $6 $7 $8 $9 }
944 | TWhile TOPar eexpr TCPar single_statement
945 { P.whileloop $1 $2 $3 $4 $5 }
946 | TDo single_statement TWhile TOPar eexpr TCPar TPtVirg
947 { P.doloop $1 $2 $3 $4 $5 $6 $7 }
948 | iter_ident TOPar eexpr_list_option TCPar single_statement
949 { P.iterator $1 $2 $3 $4 $5 }
950 | TSwitch TOPar eexpr TCPar TOBrace list(decl_var) list(case_line) TCBrace
951 { P.switch $1 $2 $3 $4 $5 (List.concat $6) $7 $8 }
952 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
953 | TReturn TPtVirg { P.ret $1 $2 }
954 | TBreak TPtVirg { P.break $1 $2 }
955 | TContinue TPtVirg { P.cont $1 $2 }
956 | ident TDotDot { P.label $1 $2 }
957 | TGoto ident TPtVirg { P.goto $1 $2 $3 }
958 | TOBrace fun_start TCBrace
962 TEllipsis w=list(whenppdecs)
963 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." $1, List.concat w)) }
964 | TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
965 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." $1, b,
966 P.clt2mcode "...>" c, List.concat w, false)) }
967 | TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
968 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." $1, b,
969 P.clt2mcode "...+>" c, List.concat w, true)) }
971 %inline stm_dots_ell:
972 a=TEllipsis w=list(whenppdecs)
973 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." a, List.concat w)) }
975 %inline stm_dots_nest:
976 a=TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
977 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." a, b,
978 P.clt2mcode "...>" c, List.concat w, false)) }
979 | a=TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
980 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." a, b,
981 P.clt2mcode "...+>" c, List.concat w, true)) }
983 whenppdecs: w=whens(when_start,rule_elem_statement,any_strict)
986 /* a statement that fits into a single rule_elem. should nests be included?
987 what about statement metavariables? */
990 { Ast0.wrap(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),$1)) }
991 | expr TPtVirg { P.exp_stm $1 $2 }
992 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
993 | TReturn TPtVirg { P.ret $1 $2 }
994 | TBreak TPtVirg { P.break $1 $2 }
995 | TContinue TPtVirg { P.cont $1 $2 }
996 | TOPar0 midzero_list(rule_elem_statement,rule_elem_statement) TCPar0
997 { let (mids,code) = $2 in
999 (Ast0.Disj(P.clt2mcode "(" $1,
1000 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
1001 mids, P.clt2mcode ")" $3)) }
1003 /* a statement on its own */
1006 | TOPar0 midzero_list(statement,statement) TCPar0
1007 /* degenerate case, elements are single statements and thus don't
1009 { let (mids,code) = $2 in
1011 (Ast0.Disj(P.clt2mcode "(" $1,
1012 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
1013 mids, P.clt2mcode ")" $3)) }
1016 TDefault TDotDot fun_start
1018 (Ast0.Default(P.clt2mcode "default" $1,P.clt2mcode ":" $2,$3)) }
1019 | TCase eexpr TDotDot fun_start
1020 { Ast0.wrap(Ast0.Case(P.clt2mcode "case" $1,$2,P.clt2mcode ":" $3,$4)) }
1021 /* | lp=TOPar0 t=midzero_list(case_line,case_line) rp=TCPar0
1022 { let (mids,code) = ([],[t]) in
1024 (Ast0.DisjCase(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) } */
1026 /* In the following, an identifier as a type is not fully supported. Indeed,
1027 the language is ambiguous: what is foo * bar; */
1028 /* The AST DisjDecl cannot be generated because it would be ambiguous with
1029 a disjunction on a statement with a declaration in each branch */
1032 { [Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv))] }
1033 | TMetaDecl { [P.meta_decl $1] }
1034 | s=ioption(storage) t=ctype d=comma_list(d_ident) pv=TPtVirg
1036 (function (id,fn) ->
1037 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)))
1039 | f=funproto { [f] }
1040 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
1042 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
1043 /* type is a typedef name */
1044 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
1045 d=comma_list(d_ident) pv=TPtVirg
1047 (function (id,fn) ->
1049 P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1050 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)))
1052 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
1053 e=initialize pv=TPtVirg
1054 { let (id,fn) = d in
1055 !Data.add_type_name (P.id2name i);
1056 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1057 [Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
1058 P.clt2mcode ";" pv))] }
1059 /* function pointer type */
1060 | s=ioption(storage)
1061 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1062 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1064 { let (id,fn) = d in
1067 (Ast0.FunctionPointer
1068 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1069 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1070 [Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv))] }
1071 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
1072 { [Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
1073 P.clt2mcode ")" $4,P.clt2mcode ";" $5))] }
1074 | s=ioption(storage)
1075 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1076 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1077 q=TEq e=initialize pv=TPtVirg
1078 { let (id,fn) = d in
1081 (Ast0.FunctionPointer
1082 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1083 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1084 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
1085 | s=Ttypedef t=typedef_ctype id=comma_list(typedef_ident) pv=TPtVirg
1086 { let s = P.clt2mcode "typedef" s in
1089 Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv)))
1094 { Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv)) }
1095 | TMetaDecl { P.meta_decl $1 }
1096 | s=ioption(storage) t=ctype d=d_ident pv=TPtVirg
1097 { let (id,fn) = d in
1098 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1100 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
1101 { let (id,fn) = d in
1102 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv)) }
1103 /* type is a typedef name */
1104 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
1105 d=d_ident pv=TPtVirg
1106 { let (id,fn) = d in
1107 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1108 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)) }
1109 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
1110 e=initialize pv=TPtVirg
1111 { let (id,fn) = d in
1112 !Data.add_type_name (P.id2name i);
1113 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1114 Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
1115 P.clt2mcode ";" pv)) }
1116 /* function pointer type */
1117 | s=ioption(storage)
1118 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1119 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1121 { let (id,fn) = d in
1124 (Ast0.FunctionPointer
1125 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1126 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1127 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1128 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
1129 { Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
1130 P.clt2mcode ")" $4,P.clt2mcode ";" $5)) }
1131 | s=ioption(storage)
1132 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1133 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1134 q=TEq e=initialize pv=TPtVirg
1135 { let (id,fn) = d in
1138 (Ast0.FunctionPointer
1139 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1140 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1141 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))}
1145 ident list(array_dec)
1149 (function (l,i,r) ->
1152 (Ast0.Array(rest,P.clt2mcode "[" l,i,P.clt2mcode "]" r)))
1155 array_dec: l=TOCro i=option(eexpr) r=TCCro { (l,i,r) }
1159 { Ast0.wrap(Ast0.InitExpr($1)) }
1160 | TOBrace initialize_list TCBrace
1161 { if P.struct_initializer $2
1163 let il = P.drop_dot_commas $2 in
1164 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
1166 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) }
1168 {let (nm,pure,clt) = $1 in
1169 Ast0.wrap(Ast0.MetaInit(P.clt2mcode nm clt,pure)) }
1172 /*arithexpr and not eexpr because can have ambiguity with comma*/
1173 /*dots and nests probably not allowed at top level, haven't looked into why*/
1174 arith_expr(eexpr,invalid) { Ast0.wrap(Ast0.InitExpr($1)) }
1175 | TOBrace initialize_list TCBrace
1176 { if P.struct_initializer $2
1178 let il = P.drop_dot_commas $2 in
1179 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
1181 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) }
1182 /* gccext:, labeled elements */
1183 | list(designator) TEq initialize2 /*can we have another of these on the rhs?*/
1184 { Ast0.wrap(Ast0.InitGccExt($1,P.clt2mcode "=" $2,$3)) }
1185 | ident TDotDot initialize2
1186 { Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */
1190 { Ast0.DesignatorField (P.clt2mcode "." $1,$2) }
1192 { Ast0.DesignatorIndex (P.clt2mcode "[" $1,$2,P.clt2mcode "]" $3) }
1193 | TOCro eexpr TEllipsis eexpr TCCro
1194 { Ast0.DesignatorRange (P.clt2mcode "[" $1,$2,P.clt2mcode "..." $3,
1195 $4,P.clt2mcode "]" $5) }
1198 empty_list_start(initialize2,edots_when(TEllipsis,initialize))
1199 { Ast0.wrap(Ast0.DOTS($1 P.mkidots (fun c -> Ast0.IComma c))) }
1201 /* a statement that is part of a list */
1204 { let (nm,pure,clt) = $1 in
1205 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1210 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1212 | statement { [$1] }
1213 /* this doesn't allow expressions at top level, because the parser doesn't
1214 know whether there is one. If there is one, this is not sequencible.
1215 If there is not one, then it is. It seems complicated to get around
1216 this at the parser level. We would have to have a check afterwards to
1217 allow this. One case where this would be useful is for a when. Now
1218 we allow a sequence of whens, so one can be on only statements and
1219 one can be on only expressions. */
1220 | TOPar0 t=midzero_list(fun_start,fun_start) TCPar0
1221 { let (mids,code) = t in
1224 match Ast0.unwrap x with Ast0.DOTS([]) -> true | _ -> false)
1228 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, code, mids,
1229 P.clt2mcode ")" $3))] }
1231 /* a statement that is part of a list */
1232 decl_statement_expr:
1234 { let (nm,pure,clt) = $1 in
1235 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1240 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1242 | statement { [$1] }
1243 /* this doesn't allow expressions at top level, because the parser doesn't
1244 know whether there is one. If there is one, this is not sequencible.
1245 If there is not one, then it is. It seems complicated to get around
1246 this at the parser level. We would have to have a check afterwards to
1247 allow this. One case where this would be useful is for a when. Now
1248 we allow a sequence of whens, so one can be on only statements and
1249 one can be on only expressions. */
1250 | TOPar0 t=midzero_list(fun_after_stm,fun_after_dots_or) TCPar0
1251 { let (mids,code) = t in
1252 if List.for_all (function [] -> true | _ -> false) code
1256 List.map (function x -> Ast0.wrap(Ast0.DOTS x)) code in
1257 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, dot_code, mids,
1258 P.clt2mcode ")" $3))] }
1260 /*****************************************************************************/
1262 /* The following cannot contain <... ...> at the top level. This can only
1263 be allowed as an expression when the expression is delimited on both sides
1264 by expression-specific markers. In that case, the rule eexpr is used, which
1265 allows <... ...> anywhere. Hopefully, this will not be too much of a problem
1267 expr: basic_expr(expr,invalid) { $1 }
1268 /* allows ... and nests */
1269 eexpr: basic_expr(eexpr,dot_expressions) { $1 }
1270 /* allows nests but not .... */
1271 dexpr: basic_expr(eexpr,nest_expressions) { $1 }
1274 eexpr { Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))) }
1277 TInvalid { raise (Semantic_cocci.Semantic "not matchable") }
1280 TEllipsis { Ast0.wrap(Ast0.Edots(P.clt2mcode "..." $1,None)) }
1281 | nest_expressions { $1 }
1283 /* not clear what whencode would mean, so just drop it */
1285 TOEllipsis e=expr_dots(TEllipsis) c=TCEllipsis
1286 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<..." $1,
1287 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1288 P.clt2mcode "...>" c, None, false)) }
1289 | TPOEllipsis e=expr_dots(TEllipsis) c=TPCEllipsis
1290 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<+..." $1,
1291 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1292 P.clt2mcode "...+>" c, None, true)) }
1294 //whenexp: TWhen TNotEq w=eexpr TLineEnd { w }
1296 basic_expr(recurser,primary_extra):
1297 assign_expr(recurser,primary_extra) { $1 }
1300 cond_expr(r,pe) { $1 }
1301 | unary_expr(r,pe) TAssign assign_expr_bis
1302 { let (op,clt) = $2 in
1303 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1304 Ast0.set_arg_exp $3,false)) }
1305 | unary_expr(r,pe) TEq assign_expr_bis
1308 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1311 cond_expr(eexpr,dot_expressions) { $1 }
1312 | unary_expr(eexpr,dot_expressions) TAssign assign_expr_bis
1313 { let (op,clt) = $2 in
1314 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1315 Ast0.set_arg_exp $3,false)) }
1316 | unary_expr(eexpr,dot_expressions) TEq assign_expr_bis
1319 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1322 arith_expr(r,pe) { $1 }
1323 | l=arith_expr(r,pe) w=TWhy t=option(eexpr) dd=TDotDot r=cond_expr(r,pe)
1324 { Ast0.wrap(Ast0.CondExpr (l, P.clt2mcode "?" w, t,
1325 P.clt2mcode ":" dd, r)) }
1328 cast_expr(r,pe) { $1 }
1329 | arith_expr(r,pe) TMul arith_expr(r,pe)
1330 { P.arith_op Ast.Mul $1 $2 $3 }
1331 | arith_expr(r,pe) TDmOp arith_expr(r,pe)
1332 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1333 | arith_expr(r,pe) TPlus arith_expr(r,pe)
1334 { P.arith_op Ast.Plus $1 $2 $3 }
1335 | arith_expr(r,pe) TMinus arith_expr(r,pe)
1336 { P.arith_op Ast.Minus $1 $2 $3 }
1337 | arith_expr(r,pe) TShLOp arith_expr(r,pe)
1338 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1339 | arith_expr(r,pe) TShROp arith_expr(r,pe)
1340 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1341 | arith_expr(r,pe) TLogOp arith_expr(r,pe)
1342 { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
1343 | arith_expr(r,pe) TEqEq arith_expr(r,pe)
1344 { P.logic_op Ast.Eq $1 $2 $3 }
1345 | arith_expr(r,pe) TNotEq arith_expr(r,pe)
1346 { P.logic_op Ast.NotEq $1 $2 $3 }
1347 | arith_expr(r,pe) TAnd arith_expr(r,pe)
1348 { P.arith_op Ast.And $1 $2 $3 }
1349 | arith_expr(r,pe) TOr arith_expr(r,pe)
1350 { P.arith_op Ast.Or $1 $2 $3 }
1351 | arith_expr(r,pe) TXor arith_expr(r,pe)
1352 { P.arith_op Ast.Xor $1 $2 $3 }
1353 | arith_expr(r,pe) TAndLog arith_expr(r,pe)
1354 { P.logic_op Ast.AndLog $1 $2 $3 }
1355 | arith_expr(r,pe) TOrLog arith_expr(r,pe)
1356 { P.logic_op Ast.OrLog $1 $2 $3 }
1359 unary_expr(r,pe) { $1 }
1360 | lp=TOPar t=ctype rp=TCPar e=cast_expr(r,pe)
1361 { Ast0.wrap(Ast0.Cast (P.clt2mcode "(" lp, t,
1362 P.clt2mcode ")" rp, e)) }
1365 postfix_expr(r,pe) { $1 }
1366 | TInc unary_expr(r,pe)
1367 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
1368 | TDec unary_expr(r,pe)
1369 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
1370 | unary_op cast_expr(r,pe)
1371 { let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
1372 | TBang unary_expr(r,pe)
1373 { let mcode = P.clt2mcode Ast.Not $1 in
1374 Ast0.wrap(Ast0.Unary($2, mcode)) }
1375 | TSizeof unary_expr(r,pe)
1376 { Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
1377 | s=TSizeof lp=TOPar t=ctype rp=TCPar
1378 { Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
1379 P.clt2mcode "(" lp,t,
1380 P.clt2mcode ")" rp)) }
1382 unary_op: TAnd { P.clt2mcode Ast.GetRef $1 }
1383 | TMul { P.clt2mcode Ast.DeRef $1 }
1384 | TPlus { P.clt2mcode Ast.UnPlus $1 }
1385 | TMinus { P.clt2mcode Ast.UnMinus $1 }
1386 | TTilde { P.clt2mcode Ast.Tilde $1 }
1389 primary_expr(r,pe) { $1 }
1390 | postfix_expr(r,pe) TOCro eexpr TCCro
1391 { Ast0.wrap(Ast0.ArrayAccess ($1,P.clt2mcode "[" $2,$3,
1392 P.clt2mcode "]" $4)) }
1393 | postfix_expr(r,pe) TDot ident
1394 { Ast0.wrap(Ast0.RecordAccess($1, P.clt2mcode "." $2, $3)) }
1395 | postfix_expr(r,pe) TPtrOp ident
1396 { Ast0.wrap(Ast0.RecordPtAccess($1, P.clt2mcode "->" $2,
1398 | postfix_expr(r,pe) TInc
1399 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Inc $2)) }
1400 | postfix_expr(r,pe) TDec
1401 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Dec $2)) }
1402 | postfix_expr(r,pe) TOPar eexpr_list_option TCPar
1403 { Ast0.wrap(Ast0.FunCall($1,P.clt2mcode "(" $2,
1405 P.clt2mcode ")" $4)) }
1407 primary_expr(recurser,primary_extra):
1408 func_ident { Ast0.wrap(Ast0.Ident($1)) }
1410 { let (x,clt) = $1 in
1411 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1413 { let (x,clt) = $1 in
1414 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Float x) clt)) }
1416 { let (x,clt) = $1 in
1417 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.String x) clt)) }
1419 { let (x,clt) = $1 in
1420 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Char x) clt)) }
1422 { let (nm,constraints,pure,ty,clt) = $1 in
1424 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
1426 { let (nm,constraints,pure,clt) = $1 in
1427 Ast0.wrap(Ast0.MetaErr(P.clt2mcode nm clt,constraints,pure)) }
1429 { let (nm,constraints,pure,ty,clt) = $1 in
1431 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
1433 { let (nm,constraints,pure,ty,clt) = $1 in
1435 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
1437 { let (nm,constraints,pure,ty,clt) = $1 in
1439 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.LocalID,pure)) }
1441 { Ast0.wrap(Ast0.Paren(P.clt2mcode "(" $1,$2,
1442 P.clt2mcode ")" $3)) }
1443 | TOPar0 midzero_list(recurser,eexpr) TCPar0
1444 { let (mids,code) = $2 in
1445 Ast0.wrap(Ast0.DisjExpr(P.clt2mcode "(" $1,
1447 P.clt2mcode ")" $3)) }
1448 | primary_extra { $1 }
1451 r=no_dot_start_end(dexpr,edots_when(dotter,eexpr)) { r }
1454 no_dot_start_end(grammar,dotter):
1455 g=grammar dg=list(pair(dotter,grammar))
1456 { function dot_builder ->
1457 g :: (List.concat(List.map (function (d,g) -> [dot_builder d;g]) dg)) }
1459 /*****************************************************************************/
1465 | TIdentifier { "identifier" }
1466 | TExpression { "expression" }
1467 | TStatement { "statement" }
1468 | TFunction { "function" }
1469 | TLocal { "local" }
1471 | TParameter { "parameter" }
1472 | TIdExpression { "idexpression" }
1473 | TInitialiser { "initialiser" }
1475 | TFresh { "fresh" }
1476 | TConstant { "constant" }
1477 | TError { "error" }
1478 | TWords { "words" }
1480 | TContext { "context" }
1481 | TGenerated { "generated" }
1482 | TTypedef { "typedef" }
1483 | TDeclarer { "declarer" }
1484 | TIterator { "iterator" }
1486 | TPosition { "position" }
1489 TRuleName TDot pure_ident { (Some $1,P.id2name $3) }
1490 | TRuleName TDot pure_ident_kwd { (Some $1,$3) }
1492 pure_ident_or_meta_ident:
1493 pure_ident { (None,P.id2name $1) }
1494 | pure_ident_kwd { (None,$1) }
1497 pure_ident_or_meta_ident_with_seed:
1498 pure_ident_or_meta_ident { ($1,Ast.NoVal) }
1499 | pure_ident_or_meta_ident TEq
1500 separated_nonempty_list(TCppConcatOp,seed_elem)
1502 [Ast.SeedString s] -> ($1,Ast.StringSeed s)
1503 | _ -> ($1,Ast.ListSeed $3) }
1506 TString { let (x,_) = $1 in Ast.SeedString x }
1507 | TMetaId { let (x,_,_,_) = $1 in Ast.SeedId x }
1508 | TRuleName TDot pure_ident
1509 { let nm = ($1,P.id2name $3) in
1510 P.check_meta(Ast.MetaIdDecl(Ast.NONE,nm));
1513 pure_ident_or_meta_ident_with_x_eq(x_eq):
1514 i=pure_ident_or_meta_ident l=loption(x_eq)
1519 pure_ident_or_meta_ident_with_econstraint(x_eq):
1520 i=pure_ident_or_meta_ident optc=option(x_eq)
1523 None -> (i, Ast0.NoConstraint)
1527 pure_ident_or_meta_ident_with_idconstraint_virt(constraint_type):
1528 i=pure_ident_or_meta_ident c=option(constraint_type)
1532 None -> (i, Ast.IdNoConstraint)
1533 | Some constraint_ -> (i,constraint_))
1535 | TVirtual TDot pure_ident { Common.Right (P.id2name $3) }
1537 pure_ident_or_meta_ident_with_idconstraint(constraint_type):
1538 i=pure_ident_or_meta_ident c=option(constraint_type)
1541 None -> (i, Ast.IdNoConstraint)
1542 | Some constraint_ -> (i,constraint_)
1546 re=regexp_eqid {Ast.IdRegExpConstraint re}
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.IdRegExp (s,Str.regexp s)
1557 | TTildeExclEq re=TString
1559 then failwith "constraints not allowed in iso file");
1560 (if !Data.in_generating
1561 then failwith "constraints not allowed in a generated rule file");
1562 let (s,_) = re in Ast.IdNotRegExp (s,Str.regexp s)
1566 TNotEq i=pure_ident_or_meta_ident
1568 then failwith "constraints not allowed in iso file");
1569 (if !Data.in_generating
1570 (* pb: constraints not stored with metavars; too lazy to search for
1571 them in the pattern *)
1572 then failwith "constraints not allowed in a generated rule file");
1576 P.check_inherited_constraint i
1577 (function mv -> Ast.MetaIdDecl(Ast.NONE,mv)) in
1578 Ast.IdNegIdSet([],[i])
1579 | (None,i) -> Ast.IdNegIdSet([i],[])) }
1580 | TNotEq TOBrace l=comma_list(pure_ident_or_meta_ident) TCBrace
1582 then failwith "constraints not allowed in iso file");
1583 (if !Data.in_generating
1584 then failwith "constraints not allowed in a generated rule file");
1587 (function (str,meta) ->
1589 (Some rn,id) as i ->
1591 P.check_inherited_constraint i
1592 (function mv -> Ast.MetaIdDecl(Ast.NONE,mv)) in
1594 | (None,i) -> (i::str,meta))
1596 Ast.IdNegIdSet(str,meta)
1599 re_or_not_eqe_or_sub:
1600 re=regexp_eqid {Ast0.NotIdCstrt re}
1601 | ne=not_eqe {Ast0.NotExpCstrt ne}
1602 | s=sub {Ast0.SubExpCstrt s}
1605 ceq=not_ceq {Ast0.NotExpCstrt ceq}
1606 | s=sub {Ast0.SubExpCstrt s}
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");
1614 [Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))]
1616 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1618 then failwith "constraints not allowed in iso file");
1619 (if !Data.in_generating
1620 then failwith "constraints not allowed in a generated rule file");
1623 Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))))
1628 TNotEq i=ident_or_const
1630 then failwith "constraints not allowed in iso file");
1631 (if !Data.in_generating
1632 then failwith "constraints not allowed in a generated rule file");
1634 | TNotEq TOBrace l=comma_list(ident_or_const) TCBrace
1636 then failwith "constraints not allowed in iso file");
1637 (if !Data.in_generating
1638 then failwith "constraints not allowed in a generated rule file");
1642 (* has to be inherited because not clear how to check subterm constraints
1643 in the functorized CTL engine, so need the variable to be bound
1644 already when bind the subterm constrained metavariable *)
1647 then failwith "constraints not allowed in iso file");
1648 (if !Data.in_generating
1649 then failwith "constraints not allowed in a generated rule file");
1651 P.check_inherited_constraint i
1652 (function mv -> Ast.MetaExpDecl(Ast.NONE,mv,None)) in
1654 | TSub TOBrace l=comma_list(meta_ident) TCBrace
1656 then failwith "constraints not allowed in iso file");
1657 (if !Data.in_generating
1658 then failwith "constraints not allowed in a generated rule file");
1661 P.check_inherited_constraint i
1662 (function mv -> Ast.MetaExpDecl(Ast.NONE,mv,None)))
1666 i=pure_ident { Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))) }
1668 { let (x,clt) = $1 in
1669 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1674 then failwith "constraints not allowed in iso file");
1675 (if !Data.in_generating
1676 then failwith "constraints not allowed in a generated rule file");
1678 P.check_inherited_constraint i
1679 (function mv -> Ast.MetaPosDecl(Ast.NONE,mv)) in
1681 | TNotEq TOBrace l=comma_list(meta_ident) TCBrace
1683 then failwith "constraints not allowed in iso file");
1684 (if !Data.in_generating
1685 then failwith "constraints not allowed in a generated rule file");
1688 P.check_inherited_constraint i
1689 (function mv -> Ast.MetaPosDecl(Ast.NONE,mv)))
1692 func_ident: pure_ident
1693 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1695 { let (nm,constraints,pure,clt) = $1 in
1696 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1698 { let (nm,constraints,pure,clt) = $1 in
1699 Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
1701 { let (nm,constraints,pure,clt) = $1 in
1703 (Ast0.MetaLocalFunc(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.Id(P.id2mcode $1)) }
1722 { let (nm,constraints,pure,clt) = $1 in
1723 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1727 { Ast0.wrap(Ast0.TypeName(P.id2mcode $1)) }
1729 { let (nm,pure,clt) = $1 in
1730 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
1732 /*****************************************************************************/
1735 empty_list_start(one_dec(decl),TEllipsis)
1739 (fun _ d -> Ast0.wrap(Ast0.Pdots(P.clt2mcode "..." d)))
1740 (fun c -> Ast0.PComma c))) }
1745 { let (nm,lenname,pure,clt) = $1 in
1746 let nm = P.clt2mcode nm clt in
1749 Ast.AnyLen -> Ast0.AnyListLen
1750 | Ast.MetaLen nm -> Ast0.MetaListLen(P.clt2mcode nm clt)
1751 | Ast.CstLen n -> Ast0.CstListLen n in
1752 Ast0.wrap(Ast0.MetaParamList(nm,lenname,pure)) }
1754 /* ---------------------------------------------------------------------- */
1755 /* comma list parser, used for fn params, fn args, enums, initlists,
1758 /* enums: enum_decl, edots_when(TEllipsis,enum_decl_one)
1759 fun s d -> P.mkedots "..." d
1760 fun c -> Ast0.EComma c
1763 empty_list_start(elem,dotter):
1764 /* empty */ { fun build_dots build_comma -> [] }
1765 | nonempty_list_start(elem,dotter) { $1 }
1767 nonempty_list_start(elem,dotter): /* dots allowed */
1768 elem { fun build_dots build_comma -> [$1] }
1770 { fun build_dots build_comma ->
1771 $1::[Ast0.wrap(build_comma(P.clt2mcode "," $2))] }
1772 | elem TComma nonempty_list_start(elem,dotter)
1773 { fun build_dots build_comma ->
1774 $1::(Ast0.wrap(build_comma(P.clt2mcode "," $2)))::
1775 ($3 build_dots build_comma) }
1776 | TNothing nonempty_list_start(elem,dotter) { $2 }
1777 | d=dotter { fun build_dots build_comma -> [(build_dots "..." d)] }
1779 { fun build_dots build_comma ->
1780 [(build_dots "..." d);Ast0.wrap(build_comma(P.clt2mcode "," $2))] }
1781 | d=dotter TComma r=continue_list(elem,dotter)
1782 { fun build_dots build_comma ->
1783 (build_dots "..." d)::
1784 (Ast0.wrap(build_comma(P.clt2mcode "," $2)))::
1785 (r build_dots build_comma) }
1787 continue_list(elem,dotter): /* dots not allowed */
1788 elem { fun build_dots build_comma -> [$1] }
1790 { fun build_dots build_comma ->
1791 $1::[Ast0.wrap(build_comma(P.clt2mcode "," $2))] }
1792 | elem TComma nonempty_list_start(elem,dotter)
1793 { fun build_dots build_comma ->
1794 $1::(Ast0.wrap(build_comma(P.clt2mcode "," $2)))::
1795 ($3 build_dots build_comma) }
1796 | TNothing nonempty_list_start(elem,dotter) { $2 }
1798 /* ---------------------------------------------------------------------- */
1800 /* error words make it complicated to be able to use error as a metavariable
1801 name or a type in a metavariable list; for that we would like to allow TError
1802 as an ident, but that makes conflicts with this rule. To add back error words,
1803 need to find some appropriate delimiter for it, but it has not been used much
1806 TError TWords TEq TOCro cl=comma_list(dexpr) TCCro
1807 { [Ast0.wrap(Ast0.ERRORWORDS(cl))] }
1810 /* ---------------------------------------------------------------------- */
1811 /* sequences of statements and expressions */
1813 /* There are number of cases that must be considered:
1816 Dots and nests allowed at the beginning or end
1817 Expressions allowed at the beginning or end
1818 One function allowed, by itself
1820 Dots and nests allowed at the beginning or end
1821 Expressions not allowed at the beginning or end
1822 Functions not allowed
1823 3. The body of a nest:
1824 Dots and nests not allowed at the beginning or end
1825 Expressions allowed at the beginning or end
1826 Functions not allowed
1828 Dots and nests not allowed at the beginning but allowed at the end
1829 Expressions allowed at the beginning or end
1830 Functions not allowed
1832 These are implemented by the rules minus_toplevel_sequence,
1833 plus_toplevel_sequence, function_body_sequence, nest_body_sequence, and
1836 /* ------------------------------------------------------------------------ */
1837 /* Minus top level */
1839 /* doesn't allow only ... */
1841 fundecl { [Ast0.wrap(Ast0.DECL($1))] }
1842 | ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1843 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1844 | toplevel_seq_startne(toplevel_after_dots_init)
1845 { List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1 }
1847 toplevel_seq_startne(after_dots_init):
1848 a=stm_dots_ell b=after_dots_init { a::b }
1849 | a=stm_dots_nest b=after_dots_init { a::b }
1850 | a=stm_dots_nest { [a] }
1851 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1852 | decl_statement_expr toplevel_after_stm { $1@$2 }
1854 toplevel_seq_start(after_dots_init):
1855 stm_dots after_dots_init { $1::$2 }
1856 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1857 | decl_statement_expr toplevel_after_stm { $1@$2 }
1859 toplevel_after_dots_init:
1860 TNothing toplevel_after_exp {$2}
1861 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1862 | decl_statement_expr toplevel_after_stm {$1@$2}
1866 | stm_dots toplevel_after_dots {$1::$2}
1868 toplevel_after_dots:
1870 | TNothing toplevel_after_exp {$2}
1871 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1872 | decl_statement_expr toplevel_after_stm {$1@$2}
1876 | stm_dots toplevel_after_dots {$1::$2}
1877 | decl_statement toplevel_after_stm {$1@$2}
1880 TOInit initialize_list TCBrace
1881 { if P.struct_initializer $2
1883 let il = P.drop_dot_commas $2 in
1884 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
1886 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) }
1888 /* ------------------------------------------------------------------------ */
1889 /* Plus top level */
1891 /* does allow only ... also allows multiple top-level functions */
1893 ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1894 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1895 | stm_dots plus_after_dots
1896 { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1897 | expr plus_after_exp
1898 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1899 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1900 | decl_statement_expr plus_after_stm
1901 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1905 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1909 | TNothing plus_after_exp {$2}
1910 | expr plus_after_exp
1911 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1912 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1913 | decl_statement_expr plus_after_stm
1914 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1918 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1919 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1920 | decl_statement plus_after_stm
1921 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1923 /* ------------------------------------------------------------------------ */
1927 fun_after_stm { Ast0.wrap(Ast0.DOTS($1)) }
1931 | stm_dots fun_after_dots {$1::$2}
1932 | decl_statement fun_after_stm {$1@$2}
1936 | TNothing fun_after_exp {$2}
1937 | expr fun_after_exp {Ast0.wrap(Ast0.Exp($1))::$2}
1938 | decl_statement_expr fun_after_stm {$1@$2}
1941 stm_dots fun_after_dots {$1::$2}
1943 /* hack to allow mixing statements and expressions in an or */
1946 | TNothing fun_after_exp_or {$2}
1947 | expr fun_after_exp_or {Ast0.wrap(Ast0.Exp($1))::$2}
1948 | decl_statement_expr fun_after_stm {$1@$2}
1952 | stm_dots fun_after_dots {$1::$2}
1954 /* ------------------------------------------------------------------------ */
1958 nest_after_dots { Ast0.wrap(Ast0.DOTS($1)) }
1961 decl_statement_expr nest_after_stm {$1@$2}
1962 | TNothing nest_after_exp {$2}
1963 | expr nest_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1967 | stm_dots nest_after_dots {$1::$2}
1968 | decl_statement nest_after_stm {$1@$2}
1972 | stm_dots nest_after_dots {$1::$2}
1974 /* ------------------------------------------------------------------------ */
1978 expr toplevel_after_exp
1979 { Ast0.wrap(Ast0.DOTS((Ast0.wrap(Ast0.Exp($1)))::$2)) }
1980 | decl_statement toplevel_after_stm
1981 { Ast0.wrap(Ast0.DOTS($1@$2)) }
1983 /* ---------------------------------------------------------------------- */
1985 /* arg expr. may contain a type or a explist metavariable */
1987 dexpr { Ast0.set_arg_exp $1 }
1989 { let (nm,lenname,pure,clt) = $1 in
1990 let nm = P.clt2mcode nm clt in
1993 Ast.AnyLen -> Ast0.AnyListLen
1994 | Ast.MetaLen nm -> Ast0.MetaListLen(P.clt2mcode nm clt)
1995 | Ast.CstLen n -> Ast0.CstListLen n in
1996 Ast0.wrap(Ast0.MetaExprList(nm,lenname,pure)) }
1998 { Ast0.set_arg_exp(Ast0.wrap(Ast0.TypeExp($1))) }
2001 empty_list_start(aexpr,TEllipsis)
2005 (fun _ d -> Ast0.wrap(Ast0.Edots(P.clt2mcode "..." d,None)))
2006 (fun c -> Ast0.EComma c))) }
2008 /****************************************************************************/
2010 // non-empty lists - drop separator
2012 separated_nonempty_list(TComma,elem) { $1 }
2014 midzero_list(elem,aft):
2015 a=elem b=list(mzl(aft))
2016 { let (mids,code) = List.split b in (mids,(a::code)) }
2019 a=TMid0 b=elem { (P.clt2mcode "|" a, b) }
2021 edots_when(dotter,when_grammar):
2022 d=dotter { (d,None) }
2023 | d=dotter TWhen TNotEq w=when_grammar TLineEnd { (d,Some w) }
2025 whens(when_grammar,simple_when_grammar,any_strict):
2026 TWhen TNotEq w=when_grammar TLineEnd { [Ast0.WhenNot w] }
2027 | TWhen TEq w=simple_when_grammar TLineEnd { [Ast0.WhenAlways w] }
2028 | TWhen comma_list(any_strict) TLineEnd
2029 { List.map (function x -> Ast0.WhenModifier(x)) $2 }
2030 | TWhenTrue TNotEq e = eexpr TLineEnd { [Ast0.WhenNotTrue e] }
2031 | TWhenFalse TNotEq e = eexpr TLineEnd { [Ast0.WhenNotFalse e] }
2034 TAny { Ast.WhenAny }
2035 | TStrict { Ast.WhenStrict }
2036 | TForall { Ast.WhenForall }
2037 | TExists { Ast.WhenExists }
2039 /*****************************************************************************
2042 *****************************************************************************/
2045 TIsoExpression e1=eexpr el=list(iso(eexpr)) EOF
2046 { let fn x = Ast0.ExprTag x in P.iso_adjust fn fn e1 el }
2047 | TIsoArgExpression e1=eexpr el=list(iso(eexpr)) EOF
2048 { let fn x = Ast0.ArgExprTag x in P.iso_adjust fn fn e1 el }
2049 | TIsoTestExpression e1=eexpr el=list(iso(eexpr)) EOF
2050 { let fn x = Ast0.TestExprTag x in P.iso_adjust fn fn e1 el }
2051 | TIsoToTestExpression e1=eexpr el=list(iso(eexpr)) EOF
2052 { let ffn x = Ast0.ExprTag x in
2053 let fn x = Ast0.TestExprTag x in
2054 P.iso_adjust ffn fn e1 el }
2055 | TIsoStatement s1=single_statement sl=list(iso(single_statement)) EOF
2056 { let fn x = Ast0.StmtTag x in P.iso_adjust fn fn s1 sl }
2057 | TIsoType t1=ctype tl=list(iso(ctype)) EOF
2058 { let fn x = Ast0.TypeCTag x in P.iso_adjust fn fn t1 tl }
2059 | TIsoTopLevel e1=nest_start el=list(iso(nest_start)) EOF
2060 { let fn x = Ast0.DotsStmtTag x in P.iso_adjust fn fn e1 el }
2061 | TIsoDeclaration d1=decl_var dl=list(iso(decl_var)) EOF
2062 { let check_one = function
2066 (Semantic_cocci.Semantic
2067 "only one variable per declaration in an isomorphism rule") in
2068 let d1 = check_one d1 in
2072 Common.Left x -> Common.Left(check_one x)
2073 | Common.Right x -> Common.Right(check_one x))
2075 let fn x = Ast0.DeclTag x in P.iso_adjust fn fn d1 dl }
2078 TIso t=term { Common.Left t }
2079 | TRightIso t=term { Common.Right t }
2081 /*****************************************************************************
2084 *****************************************************************************/
2086 never_used: TPragma { () }
2087 | TPArob TMetaPos { () }
2088 | TScriptData { () }
2091 py=pure_ident TMPtVirg
2092 { ((Some (P.id2name py), None), None) }
2093 | py=pure_ident script_name_decl TMPtVirg
2094 { ((Some (P.id2name py), None), Some $2) }
2095 | TOPar TUnderscore TComma ast=pure_ident TCPar script_name_decl TMPtVirg
2096 { ((None, Some (P.id2name ast)), Some $6) }
2097 | TOPar str=pure_ident TComma TUnderscore TCPar script_name_decl TMPtVirg
2098 { ((Some (P.id2name str), None), Some $6) }
2099 | TOPar str=pure_ident TComma ast=pure_ident TCPar script_name_decl TMPtVirg
2100 { ((Some (P.id2name str), Some (P.id2name ast)), Some $6) }
2103 TShLOp TRuleName TDot cocci=pure_ident
2104 { let nm = P.id2name cocci in
2105 let mv = Parse_aux.lookup $2 nm in
2107 | TShLOp TVirtual TDot cocci=pure_ident
2108 { let nm = P.id2name cocci in
2109 let name = ("virtual", nm) in
2110 let mv = Ast.MetaIdDecl(Ast.NONE,name) in