2 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
3 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
4 * This file is part of Coccinelle.
6 * Coccinelle is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, according to version 2 of the License.
10 * Coccinelle is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
18 * The authors reserve the right to distribute this or future versions of
19 * Coccinelle under other licenses.
25 (* Not clear how to allow function declarations to specify a return type
26 and how to allow both to be specified as static, because they are in
27 different rules. The rules seem to have to be combined, which would allow
28 functions to be declared as local variables *)
30 (* Not clear how to let a function have a parameter of type void. At the
31 moment, void is allowed to be the type of a variable, which is wrong, and a
32 parameter needs both a type and an identifier *)
33 module Ast0 = Ast0_cocci
34 module Ast = Ast_cocci
40 %token TIdentifier TExpression TStatement TFunction TLocal TType TParameter
41 %token TIdExpression TInitialiser
42 %token Tlist TFresh TConstant TError TWords TWhy0 TPlus0 TBang0
43 %token TPure TContext TGenerated
44 %token TTypedef TDeclarer TIterator TName TPosition TPosAny
45 %token TUsing TDisable TExtends TDepends TOn TEver TNever TExists TForall
46 %token TScript TInitialize TFinalize TNothing TVirtual
47 %token<string> TRuleName
49 %token<Data.clt> Tchar Tshort Tint Tdouble Tfloat Tlong
50 %token<Data.clt> Tvoid Tstruct Tunion Tenum
51 %token<Data.clt> Tunsigned Tsigned
53 %token<Data.clt> Tstatic Tauto Tregister Textern Tinline Ttypedef
54 %token<Data.clt> Tconst Tvolatile
55 %token<string * Data.clt> Tattr
57 %token <Data.clt> TIf TElse TWhile TFor TDo TSwitch TCase TDefault TReturn
58 %token <Data.clt> TBreak TContinue TGoto TSizeof TFunDecl
59 %token <string * Data.clt> TIdent TTypeId TDeclarerId TIteratorId TPragma
61 %token <Parse_aux.idinfo> TMetaId TMetaFunc TMetaLocalFunc
62 %token <Parse_aux.idinfo> TMetaIterator TMetaDeclarer
63 %token <Parse_aux.expinfo> TMetaErr
64 %token <Parse_aux.info> TMetaParam TMetaStm TMetaStmList TMetaType
65 %token <Parse_aux.info> TMetaInit
66 %token <Parse_aux.list_info> TMetaParamList TMetaExpList
67 %token <Parse_aux.typed_expinfo> TMetaExp TMetaIdExp TMetaLocalIdExp TMetaConst
68 %token <Parse_aux.pos_info> TMetaPos
70 %token TArob TArobArob TPArob
71 %token <string> TScriptData
73 %token <Data.clt> TEllipsis TOEllipsis TCEllipsis TPOEllipsis TPCEllipsis
74 %token <Data.clt> TWhen TWhenTrue TWhenFalse TAny TStrict TLineEnd
76 %token <Data.clt> TWhy TDotDot TBang TOPar TOPar0
77 %token <Data.clt> TMid0 TCPar TCPar0
79 %token <string> TPathIsoFile
80 %token <string * Data.clt> TIncludeL TIncludeNL
81 %token <Data.clt * token> TDefine
82 %token <Data.clt * token * int * int> TDefineParam
83 %token <string * Data.clt> TMinusFile TPlusFile
85 %token <Data.clt> TInc TDec
87 %token <string * Data.clt> TString TChar TFloat TInt
89 %token <Data.clt> TOrLog
90 %token <Data.clt> TAndLog
92 %token <Data.clt> TXor
93 %token <Data.clt> TAnd
94 %token <Data.clt> TEqEq TNotEq TTildeEq TTildeExclEq
95 %token <Ast_cocci.logicalOp * Data.clt> TLogOp /* TInf TSup TInfEq TSupEq */
96 %token <Ast_cocci.arithOp * Data.clt> TShOp /* TShl TShr */
97 %token <Ast_cocci.arithOp * Data.clt> TDmOp /* TDiv TMod */
98 %token <Data.clt> TPlus TMinus
99 %token <Data.clt> TMul TTilde
101 %token <Data.clt> TOBrace TCBrace TOInit
102 %token <Data.clt> TOCro TCCro
104 %token <Data.clt> TPtrOp
106 %token TMPtVirg TCppConcatOp
107 %token <Data.clt> TEq TDot TComma TPtVirg
108 %token <Ast_cocci.assignOp * Data.clt> TAssign
110 %token TIso TRightIso TIsoExpression TIsoStatement TIsoDeclaration TIsoType
111 %token TIsoTopLevel TIsoArgExpression TIsoTestExpression
115 /* operator precedence */
125 %left TLogOp /* TInf TSup TInfEq TSupEq */
126 %left TShOp /* TShl TShr */
128 %left TMul TDmOp /* TDiv TMod */
134 %type <Ast0_cocci.rule> minus_main
136 %start minus_exp_main
137 %type <Ast0_cocci.rule> minus_exp_main
140 %type <Ast0_cocci.rule> plus_main
143 %type <Ast0_cocci.rule> plus_exp_main
146 %type <Data.incl_iso list> include_main
149 %type <Ast_cocci.rulename>
153 %type <Ast_cocci.rulename>
157 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> meta_main
159 %start <string * (string * string)> script_meta_main
162 %type <Ast0_cocci.anything list list> iso_main
165 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> iso_meta_main
168 %type <unit> never_used
173 minus_main: minus_body EOF { $1 } | m=minus_body TArobArob { m }
174 | m=minus_body TArob { m }
175 plus_main: plus_body EOF { $1 } | p=plus_body TArobArob { p }
176 | p=plus_body TArob { p }
177 minus_exp_main: minus_exp_body EOF { $1 } | m=minus_exp_body TArobArob { m }
178 | m=minus_exp_body TArob { m }
179 plus_exp_main: plus_exp_body EOF { $1 } | p=plus_exp_body TArobArob { p }
180 | p=plus_exp_body TArob { p }
181 meta_main: m=metadec { m (!Ast0.rule_name) }
182 iso_meta_main: m=metadec { m "" }
184 /*****************************************************************************
187 *****************************************************************************/
191 | TContext { Ast0.Context }
192 | TPure TContext { Ast0.PureContext }
193 | TContext TPure { Ast0.PureContext }
194 | /* empty */ { Ast0.Impure }
197 nm=pure_ident TArob { P.make_iso_rule_name_result (P.id2name nm) }
200 nm=ioption(pure_ident) extends d=depends i=loption(choose_iso)
201 a=loption(disable) e=exists ee=is_expression TArob
202 { P.make_cocci_rule_name_result nm d i a e ee }
203 | TGenerated extends d=depends i=loption(choose_iso)
204 a=loption(disable) e=exists ee=is_expression TArob
205 /* these rules have no name as a cheap way to ensure that no normal
206 rule inherits their metavariables or depends on them */
207 { P.make_generated_rule_name_result None d i a e ee }
208 | TScript TDotDot lang=pure_ident d=depends TArob
209 { P.make_script_rule_name_result lang d }
210 | TInitialize TDotDot lang=pure_ident TArob
211 { P.make_initial_script_rule_name_result lang }
212 | TFinalize TDotDot lang=pure_ident TArob
213 { P.make_final_script_rule_name_result lang }
217 | TExtends parent=TRuleName
218 { !Data.install_bindings (parent) }
221 /* empty */ { Ast.NoDep }
222 | TDepends TOn parents=dep { parents }
226 | dep TAndLog dep { Ast.AndDep($1, $3) }
227 | dep TOrLog dep { Ast.OrDep ($1, $3) }
230 TRuleName { Ast.Dep $1 }
231 | TBang TRuleName { Ast.AntiDep $2 }
232 | TEver TRuleName { Ast.EverDep $2 }
233 | TNever TRuleName { Ast.NeverDep $2 }
234 | TOPar dep TCPar { $2 }
237 TUsing separated_nonempty_list(TComma,TString) { List.map P.id2name $2 }
240 TDisable separated_nonempty_list(TComma,pure_ident) { List.map P.id2name $2 }
243 TExists { Ast.Exists }
244 | TForall { Ast.Forall }
245 | { Ast.Undetermined }
247 is_expression: // for more flexible parsing of top level expressions
249 | TExpression { true }
252 list(incl) TArob { $1 }
253 | list(incl) TArobArob { $1 }
256 TIncludeL { let (x,_) = $1 in Data.Include(x) }
257 | TUsing TString { Data.Iso(Common.Left(P.id2name $2)) }
258 | TUsing TPathIsoFile { Data.Iso(Common.Right $2) }
259 | TVirtual comma_list(pure_ident)
260 { let names = List.map P.id2name $2 in
261 (* ensure that the names of virtual and real rules don't overlap *)
263 (function name -> Hashtbl.add Data.all_metadecls name [])
269 kindfn=metakind ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
270 { P.create_metadec ar ispure kindfn ids }
271 | kindfn=metakind_fresh ids=comma_list(pure_ident_or_meta_ident_with_seed)
273 { P.create_fresh_metadec kindfn ids }
274 | ar=arity ispure=pure
275 kindfn=metakind_atomic
276 ids=comma_list(pure_ident_or_meta_ident_with_idconstraint(re_or_not_eqid)) TMPtVirg
277 { P.create_metadec_with_constraints ar ispure kindfn ids }
278 | ar=arity ispure=pure
279 kindfn=metakind_atomic_expi
280 ids=comma_list(pure_ident_or_meta_ident_with_econstraint(re_or_not_eqe)) TMPtVirg
281 { P.create_metadec_with_constraints ar ispure kindfn ids }
282 | ar=arity ispure=pure
283 kindfn=metakind_atomic_expe
284 ids=comma_list(pure_ident_or_meta_ident_with_x_eq(not_ceq)) TMPtVirg
285 { P.create_metadec_with_constraints ar ispure kindfn ids }
286 | ar=arity TPosition a=option(TPosAny)
287 ids=comma_list(pure_ident_or_meta_ident_with_x_eq(not_pos)) TMPtVirg
288 (* pb: position variables can't be inherited from normal rules, and then
289 there is no way to inherit from a generated rule, so there is no point
290 to have a position variable *)
291 { (if !Data.in_generating
292 then failwith "position variables not allowed in a generated rule file");
293 let kindfn arity name pure check_meta constraints =
294 let tok = check_meta(Ast.MetaPosDecl(arity,name)) in
295 let any = match a with None -> Ast.PER | Some _ -> Ast.ALL in
296 !Data.add_pos_meta name constraints any; tok in
297 P.create_metadec_with_constraints ar false kindfn ids }
298 | ar=arity ispure=pure
299 TParameter Tlist TOCro id=pure_ident_or_meta_ident TCCro
300 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
301 { P.create_len_metadec ar ispure
302 (fun lenname arity name pure check_meta ->
304 check_meta(Ast.MetaParamListDecl(arity,name,Some lenname)) in
305 !Data.add_paramlist_meta name (Some lenname) pure; tok)
307 | ar=arity ispure=pure
308 TExpression Tlist TOCro id=pure_ident_or_meta_ident TCCro
309 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
310 { P.create_len_metadec ar ispure
311 (fun lenname arity name pure check_meta ->
313 check_meta(Ast.MetaExpListDecl(arity,name,Some lenname)) in
314 !Data.add_explist_meta name (Some lenname) pure; tok)
317 %inline metakind_fresh:
319 { (fun name check_meta seed ->
320 let tok = check_meta(Ast.MetaFreshIdDecl(name,seed)) in
321 !Data.add_fresh_id_meta name; tok) }
325 { (fun arity name pure check_meta ->
326 let tok = check_meta(Ast.MetaParamDecl(arity,name)) in
327 !Data.add_param_meta name pure; tok) }
329 { (fun arity name pure check_meta ->
330 let tok = check_meta(Ast.MetaParamListDecl(arity,name,None)) in
331 !Data.add_paramlist_meta name None pure; tok) }
333 { (fun arity name pure check_meta ->
334 let tok = check_meta(Ast.MetaExpListDecl(arity,name,None)) in
335 !Data.add_explist_meta name None pure; tok) }
337 { (fun arity name pure check_meta ->
338 let tok = check_meta(Ast.MetaTypeDecl(arity,name)) in
339 !Data.add_type_meta name pure; tok) }
341 { (fun arity name pure check_meta ->
342 let tok = check_meta(Ast.MetaInitDecl(arity,name)) in
343 !Data.add_init_meta name pure; tok) }
345 { (fun arity name pure check_meta ->
346 let tok = check_meta(Ast.MetaStmDecl(arity,name)) in
347 !Data.add_stm_meta name pure; tok) }
349 { (fun arity name pure check_meta ->
350 let tok = check_meta(Ast.MetaStmListDecl(arity,name)) in
351 !Data.add_stmlist_meta name pure; tok) }
353 { (fun arity (_,name) pure check_meta ->
354 if arity = Ast.NONE && pure = Ast0.Impure
355 then (!Data.add_type_name name; [])
356 else raise (Semantic_cocci.Semantic "bad typedef")) }
358 { (fun arity (_,name) pure check_meta ->
359 if arity = Ast.NONE && pure = Ast0.Impure
360 then (!Data.add_declarer_name name; [])
361 else raise (Semantic_cocci.Semantic "bad declarer")) }
363 { (fun arity (_,name) pure check_meta ->
364 if arity = Ast.NONE && pure = Ast0.Impure
365 then (!Data.add_iterator_name name; [])
366 else raise (Semantic_cocci.Semantic "bad iterator")) }
368 %inline metakind_atomic:
370 { (fun arity name pure check_meta constraints ->
371 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
372 !Data.add_id_meta name constraints pure; tok) }
374 { (fun arity name pure check_meta constraints ->
375 let tok = check_meta(Ast.MetaFuncDecl(arity,name)) in
376 !Data.add_func_meta name constraints pure; tok) }
378 { (fun arity name pure check_meta constraints ->
379 let tok = check_meta(Ast.MetaLocalFuncDecl(arity,name)) in
380 !Data.add_local_func_meta name constraints pure;
383 { (fun arity name pure check_meta constraints ->
384 let tok = check_meta(Ast.MetaDeclarerDecl(arity,name)) in
385 !Data.add_declarer_meta name constraints pure; tok) }
387 { (fun arity name pure check_meta constraints ->
388 let tok = check_meta(Ast.MetaIteratorDecl(arity,name)) in
389 !Data.add_iterator_meta name constraints pure; tok) }
391 %inline metakind_atomic_expi:
393 { (fun arity name pure check_meta constraints ->
394 let tok = check_meta(Ast.MetaErrDecl(arity,name)) in
395 !Data.add_err_meta name constraints pure; tok) }
396 | l=option(TLocal) TIdExpression ty=ioption(meta_exp_type)
397 { (fun arity name pure check_meta constraints ->
400 !Data.add_idexp_meta ty name constraints pure;
401 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
403 !Data.add_local_idexp_meta ty name constraints pure;
404 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
405 | l=option(TLocal) TIdExpression m=nonempty_list(TMul)
406 { (fun arity name pure check_meta constraints ->
407 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
410 !Data.add_idexp_meta ty name constraints pure;
411 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
413 !Data.add_local_idexp_meta ty name constraints pure;
414 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
415 | TExpression m=nonempty_list(TMul)
416 { (fun arity name pure check_meta constraints ->
417 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
418 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
419 !Data.add_exp_meta ty name constraints pure; tok) }
420 | vl=meta_exp_type TOCro TCCro
421 { (fun arity name pure check_meta constraints ->
422 let ty = Some (List.map (function x -> Type_cocci.Array x) vl) in
423 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
424 !Data.add_exp_meta ty name constraints pure; tok) }
425 | TConstant ty=ioption(meta_exp_type)
426 { (fun arity name pure check_meta constraints ->
427 let tok = check_meta(Ast.MetaConstDecl(arity,name,ty)) in
428 !Data.add_const_meta ty name constraints pure; tok) }
430 %inline metakind_atomic_expe:
432 { (fun arity name pure check_meta constraints ->
433 let tok = check_meta(Ast.MetaExpDecl(arity,name,None)) in
434 !Data.add_exp_meta None name (Ast0.NotExpCstrt constraints) pure; tok) }
435 | vl=meta_exp_type // no error if use $1 but doesn't type check
436 { (fun arity name pure check_meta constraints ->
440 match Ast0.unwrap c with
445 Type_cocci.BaseType(Type_cocci.IntType) -> true
446 | Type_cocci.BaseType(Type_cocci.ShortType) -> true
447 | Type_cocci.BaseType(Type_cocci.LongType) -> true
450 then failwith "metavariable with int constraint must be an int"
453 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
454 !Data.add_exp_meta ty name (Ast0.NotExpCstrt constraints) pure; tok)
460 { [Ast0_cocci.ast0_type_to_type t] }
461 | TOBrace t=comma_list(ctype) TCBrace m=list(TMul)
463 (function x -> P.ty_pointerify (Ast0_cocci.ast0_type_to_type x) m)
466 arity: TBang0 { Ast.UNIQUE }
468 | TPlus0 { Ast.MULTI }
469 | /* empty */ { Ast.NONE }
471 /* ---------------------------------------------------------------------- */
476 { Ast0.wrap(Ast0.BaseType(Ast.CharType,[P.clt2mcode "char" ty])) }
478 { Ast0.wrap(Ast0.BaseType(Ast.ShortType,[P.clt2mcode "short" ty])) }
480 { Ast0.wrap(Ast0.BaseType(Ast.IntType,[P.clt2mcode "int" ty])) }
482 { let (nm,pure,clt) = p in
483 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
484 | r=TRuleName TDot p=TIdent
485 { let nm = (r,P.id2name p) in
486 (* this is only possible when we are in a metavar decl. Otherwise,
487 it will be represented already as a MetaType *)
488 let _ = P.check_meta(Ast.MetaTypeDecl(Ast.NONE,nm)) in
489 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm (P.id2clt p),
490 Ast0.Impure (*will be ignored*))) }
492 { Ast0.wrap(Ast0.BaseType(Ast.LongType,[P.clt2mcode "long" ty])) }
493 | ty1=Tlong ty2=Tlong
497 [P.clt2mcode "long" ty1;P.clt2mcode "long" ty2])) }
502 { Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" ty])) }
504 { Ast0.wrap(Ast0.BaseType(Ast.DoubleType,[P.clt2mcode "double" ty])) }
506 { Ast0.wrap(Ast0.BaseType(Ast.FloatType,[P.clt2mcode "float" ty])) }
508 { Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, i)) }
509 | s=struct_or_union i=ident
510 { Ast0.wrap(Ast0.StructUnionName(s, Some i)) }
511 | s=struct_or_union i=ioption(ident)
512 l=TOBrace d=struct_decl_list r=TCBrace
513 { (if i = None && !Data.in_iso
514 then failwith "structures must be named in the iso file");
515 Ast0.wrap(Ast0.StructUnionDef(Ast0.wrap(Ast0.StructUnionName(s, i)),
517 d, P.clt2mcode "}" r)) }
518 | s=TMetaType l=TOBrace d=struct_decl_list r=TCBrace
519 { let (nm,pure,clt) = s in
520 let ty = Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) in
521 Ast0.wrap(Ast0.StructUnionDef(ty,P.clt2mcode "{" l,d,P.clt2mcode "}" r)) }
523 { Ast0.wrap(Ast0.TypeName(P.id2mcode p)) }
527 r=Tsigned ty=signable_types
528 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,Some ty)) }
529 | r=Tunsigned ty=signable_types
530 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,Some ty)) }
531 | ty=signable_types { ty }
532 | ty=non_signable_types { ty }
535 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
536 { P.pointerify (P.make_cv cv ty) m }
538 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,None)) }
540 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,None)) }
541 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
542 { let (mids,code) = t in
544 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
546 /* signed, unsigned alone not allowed */
548 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
549 { P.pointerify (P.make_cv cv ty) m }
550 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
551 { let (mids,code) = t in
553 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
555 /* ---------------------------------------------------------------------- */
558 s=Tstruct { P.clt2mcode Ast.Struct s }
559 | u=Tunion { P.clt2mcode Ast.Union u }
563 | t=ctype d=d_ident pv=TPtVirg
565 [Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] }
566 | t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
567 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar pv=TPtVirg
571 (Ast0.FunctionPointer
572 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
573 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
574 [Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] }
575 | cv=ioption(const_vol) i=pure_ident d=d_ident pv=TPtVirg
577 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
578 [Ast0.wrap(Ast0.UnInit(None,fn idtype,id,P.clt2mcode ";" pv))] }
581 struct_decl_list_start { Ast0.wrap(Ast0.DOTS($1)) }
583 struct_decl_list_start:
585 | struct_decl struct_decl_list_start { $1@$2 }
586 | d=edots_when(TEllipsis,struct_decl) r=continue_struct_decl_list
587 { (P.mkddots "..." d)::r }
589 continue_struct_decl_list:
591 | struct_decl struct_decl_list_start { $1@$2 }
595 /*****************************************************************************/
597 /* have to inline everything to avoid conflicts? switch to proper
598 declarations, statements, and expressions for the subterms */
602 b=loption(minus_start)
603 /*ew=loption(error_words)*/
604 { match f@b(*@ew*) with
605 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
606 | code -> Top_level.top_level code }
610 b=loption(plus_start)
611 /*ew=loption(error_words)*/
612 { Top_level.top_level (f@b(*@ew*)) }
617 /*ew=loption(error_words)*/
618 { match f@[b](*@ew*) with
619 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
620 | code -> Top_level.top_level code }
625 /*ew=loption(error_words)*/
626 { Top_level.top_level (f@[b](*@ew*)) }
631 (Ast0.FILEINFO(P.id2mcode $1,
637 (Ast0.Include(P.clt2mcode "#include" (P.drop_aft (P.id2clt $1)),
638 let (arity,ln,lln,offset,col,strbef,straft,pos) =
641 (arity,ln,lln,offset,0,strbef,straft,pos) in
643 (Ast.Local (Parse_aux.str2inc (P.id2name $1)))
647 (Ast0.Include(P.clt2mcode "#include" (P.drop_aft (P.id2clt $1)),
648 let (arity,ln,lln,offset,col,strbef,straft,pos) =
651 (arity,ln,lln,offset,0,strbef,straft,pos) in
653 (Ast.NonLocal (Parse_aux.str2inc (P.id2name $1)))
655 | d=defineop t=ctype TLineEnd
656 { let ty = Ast0.wrap(Ast0.TopExp(Ast0.wrap(Ast0.TypeExp(t)))) in
657 d (Ast0.wrap(Ast0.DOTS([ty]))) }
658 | defineop b=toplevel_seq_start(toplevel_after_dots) TLineEnd
662 (match Ast0.unwrap e with
664 [Ast0.rewrap e (Ast0.TopExp(Ast0.set_arg_exp (e1)))]
667 $1 (Ast0.wrap(Ast0.DOTS(body))) }
671 { let (clt,ident) = $1 in
675 (P.clt2mcode "#define" clt,
677 TMetaId((nm,constraints,pure,clt)) ->
678 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
680 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
683 (Semantic_cocci.Semantic
684 "unexpected name for a #define")),
685 Ast0.wrap Ast0.NoParams,
687 | TDefineParam define_param_list_option TCPar
688 { let (clt,ident,parenoff,parencol) = $1 in
689 (* clt is the start of the #define itself *)
690 let (arity,line,lline,offset,col,strbef,straft,pos) = clt in
693 (arity,line,lline,parenoff,parencol,[],[],Ast0.NoMetaPos) in
697 (P.clt2mcode "#define" clt,
699 TMetaId((nm,constraints,pure,clt)) ->
700 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
702 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
705 (Semantic_cocci.Semantic
706 "unexpected name for a #define")),
707 Ast0.wrap (Ast0.DParams (lp,$2,P.clt2mcode ")" $3)),body)) }
709 /* ---------------------------------------------------------------------- */
711 define_param_list: define_param_list_start
713 match Ast0.unwrap x with Ast0.DPcircles(_) -> true | _ -> false in
714 if List.exists circle $1
715 then Ast0.wrap(Ast0.CIRCLES($1))
716 else Ast0.wrap(Ast0.DOTS($1)) }
718 define_param_list_start:
719 ident { [Ast0.wrap(Ast0.DParam $1)] }
720 | ident TComma define_param_list_start
721 { Ast0.wrap(Ast0.DParam $1)::
722 Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $2))::$3 }
723 | d=TEllipsis r=list(dp_comma_args(TEllipsis))
724 { (P.mkdpdots "..." d)::
725 (List.concat (List.map (function x -> x (P.mkdpdots "...")) r)) }
727 dp_comma_args(dotter):
729 { function dot_builder ->
730 [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," c)); dot_builder d] }
732 { function dot_builder ->
733 [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $1));
734 Ast0.wrap(Ast0.DParam $2)] }
736 define_param_list_option: define_param_list { $1 }
737 | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
739 /*****************************************************************************/
742 s=ioption(storage) t=ctype
743 id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
748 (Ast0.FunctionType(Some t,
749 P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
750 id, P.clt2mcode ";" pt)) }
754 TFunDecl i=func_ident lp=TOPar d=decl_list(decl) rp=TCPar
755 lb=TOBrace b=fun_start rb=TCBrace
756 { P.verify_parameter_declarations (Ast0.undots d);
757 Ast0.wrap(Ast0.FunDecl((Ast0.default_info(),Ast0.context_befaft()),
759 P.clt2mcode "(" lp, d,
761 P.clt2mcode "{" lb, b,
762 P.clt2mcode "}" rb)) }
769 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
770 raise (Semantic_cocci.Semantic "duplicate storage")
771 with Not_found -> (Ast0.FStorage($1))::$2 }
772 | t=ctype r=fninfo_nt { (Ast0.FType(t))::r }
775 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
776 raise (Semantic_cocci.Semantic "duplicate inline")
777 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
780 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
781 raise (Semantic_cocci.Semantic "multiple attributes")
782 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
789 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
790 raise (Semantic_cocci.Semantic "duplicate storage")
791 with Not_found -> (Ast0.FStorage($1))::$2 }
794 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
795 raise (Semantic_cocci.Semantic "duplicate inline")
796 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
799 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
800 raise (Semantic_cocci.Semantic "duplicate init")
801 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
804 s=Tstatic { P.clt2mcode Ast.Static s }
805 | s=Tauto { P.clt2mcode Ast.Auto s }
806 | s=Tregister { P.clt2mcode Ast.Register s }
807 | s=Textern { P.clt2mcode Ast.Extern s }
809 decl: t=ctype i=ident
810 { Ast0.wrap(Ast0.Param(t, Some i)) }
811 | t=ctype { (*verify in FunDecl*) Ast0.wrap(Ast0.Param(t, None)) }
812 | t=ctype lp=TOPar s=TMul i=ident rp=TCPar
813 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
816 (Ast0.FunctionPointer
817 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
818 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
819 Ast0.wrap(Ast0.Param(fnptr, Some i)) }
821 { let (nm,pure,clt) = $1 in
822 Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) }
826 | t=ctype lp=TOPar s=TMul rp=TCPar
827 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
830 (Ast0.FunctionPointer
831 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
832 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
833 Ast0.wrap(Ast0.Param(fnptr, None)) }
836 Tconst { P.clt2mcode Ast.Const $1 }
837 | Tvolatile { P.clt2mcode Ast.Volatile $1 }
839 /*****************************************************************************/
842 includes { $1 } /* shouldn't be allowed to be a single_statement... */
847 | TIf TOPar eexpr TCPar single_statement %prec TIf
848 { P.ifthen $1 $2 $3 $4 $5 }
849 | TIf TOPar eexpr TCPar single_statement TElse single_statement
850 { P.ifthenelse $1 $2 $3 $4 $5 $6 $7 }
851 | TFor TOPar option(eexpr) TPtVirg option(eexpr) TPtVirg
852 option(eexpr) TCPar single_statement
853 { P.forloop $1 $2 $3 $4 $5 $6 $7 $8 $9 }
854 | TWhile TOPar eexpr TCPar single_statement
855 { P.whileloop $1 $2 $3 $4 $5 }
856 | TDo single_statement TWhile TOPar eexpr TCPar TPtVirg
857 { P.doloop $1 $2 $3 $4 $5 $6 $7 }
858 | iter_ident TOPar eexpr_list_option TCPar single_statement
859 { P.iterator $1 $2 $3 $4 $5 }
860 | TSwitch TOPar eexpr TCPar TOBrace list(decl_var) list(case_line) TCBrace
861 { P.switch $1 $2 $3 $4 $5 (List.concat $6) $7 $8 }
862 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
863 | TReturn TPtVirg { P.ret $1 $2 }
864 | TBreak TPtVirg { P.break $1 $2 }
865 | TContinue TPtVirg { P.cont $1 $2 }
866 | ident TDotDot { P.label $1 $2 }
867 | TGoto ident TPtVirg { P.goto $1 $2 $3 }
868 | TOBrace fun_start TCBrace
872 TEllipsis w=list(whenppdecs)
873 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." $1, List.concat w)) }
874 | TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
875 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." $1, b,
876 P.clt2mcode "...>" c, List.concat w, false)) }
877 | TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
878 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." $1, b,
879 P.clt2mcode "...+>" c, List.concat w, true)) }
881 %inline stm_dots_ell:
882 a=TEllipsis w=list(whenppdecs)
883 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." a, List.concat w)) }
885 %inline stm_dots_nest:
886 a=TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
887 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." a, b,
888 P.clt2mcode "...>" c, List.concat w, false)) }
889 | a=TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
890 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." a, b,
891 P.clt2mcode "...+>" c, List.concat w, true)) }
893 whenppdecs: w=whens(when_start,rule_elem_statement,any_strict)
896 /* a statement that fits into a single rule_elem. should nests be included?
897 what about statement metavariables? */
900 { Ast0.wrap(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),$1)) }
901 | expr TPtVirg { P.exp_stm $1 $2 }
902 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
903 | TReturn TPtVirg { P.ret $1 $2 }
904 | TBreak TPtVirg { P.break $1 $2 }
905 | TContinue TPtVirg { P.cont $1 $2 }
906 | TOPar0 midzero_list(rule_elem_statement,rule_elem_statement) TCPar0
907 { let (mids,code) = $2 in
909 (Ast0.Disj(P.clt2mcode "(" $1,
910 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
911 mids, P.clt2mcode ")" $3)) }
913 /* a statement on its own */
916 | TOPar0 midzero_list(statement,statement) TCPar0
917 /* degenerate case, elements are single statements and thus don't
919 { let (mids,code) = $2 in
921 (Ast0.Disj(P.clt2mcode "(" $1,
922 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
923 mids, P.clt2mcode ")" $3)) }
926 TDefault TDotDot fun_start
928 (Ast0.Default(P.clt2mcode "default" $1,P.clt2mcode ":" $2,$3)) }
929 | TCase eexpr TDotDot fun_start
930 { Ast0.wrap(Ast0.Case(P.clt2mcode "case" $1,$2,P.clt2mcode ":" $3,$4)) }
931 /* | lp=TOPar0 t=midzero_list(case_line,case_line) rp=TCPar0
932 { let (mids,code) = ([],[t]) in
934 (Ast0.DisjCase(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) } */
936 /* In the following, an identifier as a type is not fully supported. Indeed,
937 the language is ambiguous: what is foo * bar; */
938 /* The AST DisjDecl cannot be generated because it would be ambiguous with
939 a disjunction on a statement with a declaration in each branch */
942 { [Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv))] }
943 | s=ioption(storage) t=ctype d=comma_list(d_ident) pv=TPtVirg
946 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)))
949 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
951 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
952 /* type is a typedef name */
953 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
954 d=comma_list(d_ident) pv=TPtVirg
958 P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
959 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)))
961 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
962 e=initialize pv=TPtVirg
964 !Data.add_type_name (P.id2name i);
965 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
966 [Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
967 P.clt2mcode ";" pv))] }
968 /* function pointer type */
970 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
971 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
976 (Ast0.FunctionPointer
977 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
978 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
979 [Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv))] }
980 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
981 { [Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
982 P.clt2mcode ")" $4,P.clt2mcode ";" $5))] }
984 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
985 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
986 q=TEq e=initialize pv=TPtVirg
990 (Ast0.FunctionPointer
991 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
992 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
993 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
994 | s=Ttypedef t=typedef_ctype id=comma_list(typedef_ident) pv=TPtVirg
995 { let s = P.clt2mcode "typedef" s in
998 Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv)))
1003 { Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv)) }
1004 | s=ioption(storage) t=ctype d=d_ident pv=TPtVirg
1005 { let (id,fn) = d in
1006 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1008 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
1009 { let (id,fn) = d in
1010 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv)) }
1011 /* type is a typedef name */
1012 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
1013 d=d_ident pv=TPtVirg
1014 { let (id,fn) = d in
1015 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1016 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)) }
1017 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
1018 e=initialize pv=TPtVirg
1019 { let (id,fn) = d in
1020 !Data.add_type_name (P.id2name i);
1021 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1022 Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
1023 P.clt2mcode ";" pv)) }
1024 /* function pointer type */
1025 | s=ioption(storage)
1026 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1027 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1029 { let (id,fn) = d in
1032 (Ast0.FunctionPointer
1033 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1034 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1035 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1036 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
1037 { Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
1038 P.clt2mcode ")" $4,P.clt2mcode ";" $5)) }
1039 | s=ioption(storage)
1040 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1041 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1042 q=TEq e=initialize pv=TPtVirg
1043 { let (id,fn) = d in
1046 (Ast0.FunctionPointer
1047 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1048 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1049 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))}
1053 ident list(array_dec)
1057 (function (l,i,r) ->
1060 (Ast0.Array(rest,P.clt2mcode "[" l,i,P.clt2mcode "]" r)))
1063 array_dec: l=TOCro i=option(eexpr) r=TCCro { (l,i,r) }
1067 { Ast0.wrap(Ast0.InitExpr($1)) }
1068 | TOBrace initialize_list TCBrace
1069 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1072 (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []),
1073 P.clt2mcode "}" $2)) }
1075 {let (nm,pure,clt) = $1 in
1076 Ast0.wrap(Ast0.MetaInit(P.clt2mcode nm clt,pure)) }
1079 /*arithexpr and not eexpr because can have ambiguity with comma*/
1080 /*dots and nests probably not allowed at top level, haven't looked into why*/
1081 arith_expr(eexpr,invalid) { Ast0.wrap(Ast0.InitExpr($1)) }
1082 | TOBrace initialize_list TCBrace
1083 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1086 (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []),
1087 P.clt2mcode "}" $2)) }
1088 /* gccext:, labeled elements */
1089 | list(designator) TEq initialize2
1090 { Ast0.wrap(Ast0.InitGccExt($1,P.clt2mcode "=" $2,$3)) }
1091 | ident TDotDot initialize2
1092 { Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */
1096 { Ast0.DesignatorField (P.clt2mcode "." $1,$2) }
1098 { Ast0.DesignatorIndex (P.clt2mcode "[" $1,$2,P.clt2mcode "]" $3) }
1099 | TOCro eexpr TEllipsis eexpr TCCro
1100 { Ast0.DesignatorRange (P.clt2mcode "[" $1,$2,P.clt2mcode "..." $3,
1101 $4,P.clt2mcode "]" $5) }
1104 initialize_list_start { Ast0.wrap(Ast0.DOTS($1)) }
1106 initialize_list_start:
1107 initialize2 TComma { [$1;Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))] }
1108 | initialize2 TComma initialize_list_start
1109 { $1::Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))::$3 }
1110 | d=edots_when(TEllipsis,initialize)
1111 r=comma_initializers(edots_when(TEllipsis,initialize))
1112 { (P.mkidots "..." d)::
1113 (List.concat(List.map (function x -> x (P.mkidots "...")) r)) }
1115 comma_initializers(dotter):
1117 | d=dotter r=comma_initializers2(dotter)
1118 { (function dot_builder -> [dot_builder d])::r }
1119 | i=initialize2 c=TComma r=comma_initializers(dotter)
1120 { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
1123 comma_initializers2(dotter):
1125 | i=initialize2 c=TComma r=comma_initializers(dotter)
1126 { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
1129 /* a statement that is part of a list */
1132 { let (nm,pure,clt) = $1 in
1133 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1138 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1140 | statement { [$1] }
1141 /* this doesn't allow expressions at top level, because the parser doesn't
1142 know whether there is one. If there is one, this is not sequencible.
1143 If there is not one, then it is. It seems complicated to get around
1144 this at the parser level. We would have to have a check afterwards to
1145 allow this. One case where this would be useful is for a when. Now
1146 we allow a sequence of whens, so one can be on only statements and
1147 one can be on only expressions. */
1148 | TOPar0 t=midzero_list(fun_start,fun_start) TCPar0
1149 { let (mids,code) = t in
1152 match Ast0.unwrap x with Ast0.DOTS([]) -> true | _ -> false)
1156 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, code, mids,
1157 P.clt2mcode ")" $3))] }
1159 /* a statement that is part of a list */
1160 decl_statement_expr:
1162 { let (nm,pure,clt) = $1 in
1163 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1168 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1170 | statement { [$1] }
1171 /* this doesn't allow expressions at top level, because the parser doesn't
1172 know whether there is one. If there is one, this is not sequencible.
1173 If there is not one, then it is. It seems complicated to get around
1174 this at the parser level. We would have to have a check afterwards to
1175 allow this. One case where this would be useful is for a when. Now
1176 we allow a sequence of whens, so one can be on only statements and
1177 one can be on only expressions. */
1178 | TOPar0 t=midzero_list(fun_after_stm,fun_after_dots_or) TCPar0
1179 { let (mids,code) = t in
1180 if List.for_all (function [] -> true | _ -> false) code
1184 List.map (function x -> Ast0.wrap(Ast0.DOTS x)) code in
1185 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, dot_code, mids,
1186 P.clt2mcode ")" $3))] }
1188 /*****************************************************************************/
1190 /* The following cannot contain <... ...> at the top level. This can only
1191 be allowed as an expression when the expression is delimited on both sides
1192 by expression-specific markers. In that case, the rule eexpr is used, which
1193 allows <... ...> anywhere. Hopefully, this will not be too much of a problem
1195 expr: basic_expr(expr,invalid) { $1 }
1196 /* allows ... and nests */
1197 eexpr: basic_expr(eexpr,dot_expressions) { $1 }
1198 /* allows nests but not .... */
1199 dexpr: basic_expr(eexpr,nest_expressions) { $1 }
1202 eexpr { Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))) }
1205 TInvalid { raise (Semantic_cocci.Semantic "not matchable") }
1208 TEllipsis { Ast0.wrap(Ast0.Edots(P.clt2mcode "..." $1,None)) }
1209 | nest_expressions { $1 }
1211 /* not clear what whencode would mean, so just drop it */
1213 TOEllipsis e=expr_dots(TEllipsis) c=TCEllipsis
1214 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<..." $1,
1215 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1216 P.clt2mcode "...>" c, None, false)) }
1217 | TPOEllipsis e=expr_dots(TEllipsis) c=TPCEllipsis
1218 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<+..." $1,
1219 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1220 P.clt2mcode "...+>" c, None, true)) }
1222 //whenexp: TWhen TNotEq w=eexpr TLineEnd { w }
1224 basic_expr(recurser,primary_extra):
1225 assign_expr(recurser,primary_extra) { $1 }
1228 cond_expr(r,pe) { $1 }
1229 | unary_expr(r,pe) TAssign assign_expr_bis
1230 { let (op,clt) = $2 in
1231 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1232 Ast0.set_arg_exp $3,false)) }
1233 | unary_expr(r,pe) TEq assign_expr_bis
1236 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1239 cond_expr(eexpr,dot_expressions) { $1 }
1240 | unary_expr(eexpr,dot_expressions) TAssign assign_expr_bis
1241 { let (op,clt) = $2 in
1242 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1243 Ast0.set_arg_exp $3,false)) }
1244 | unary_expr(eexpr,dot_expressions) TEq assign_expr_bis
1247 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1250 arith_expr(r,pe) { $1 }
1251 | l=arith_expr(r,pe) w=TWhy t=option(eexpr) dd=TDotDot r=cond_expr(r,pe)
1252 { Ast0.wrap(Ast0.CondExpr (l, P.clt2mcode "?" w, t,
1253 P.clt2mcode ":" dd, r)) }
1256 cast_expr(r,pe) { $1 }
1257 | arith_expr(r,pe) TMul arith_expr(r,pe)
1258 { P.arith_op Ast.Mul $1 $2 $3 }
1259 | arith_expr(r,pe) TDmOp arith_expr(r,pe)
1260 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1261 | arith_expr(r,pe) TPlus arith_expr(r,pe)
1262 { P.arith_op Ast.Plus $1 $2 $3 }
1263 | arith_expr(r,pe) TMinus arith_expr(r,pe)
1264 { P.arith_op Ast.Minus $1 $2 $3 }
1265 | arith_expr(r,pe) TShOp arith_expr(r,pe)
1266 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1267 | arith_expr(r,pe) TLogOp arith_expr(r,pe)
1268 { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
1269 | arith_expr(r,pe) TEqEq arith_expr(r,pe)
1270 { P.logic_op Ast.Eq $1 $2 $3 }
1271 | arith_expr(r,pe) TNotEq arith_expr(r,pe)
1272 { P.logic_op Ast.NotEq $1 $2 $3 }
1273 | arith_expr(r,pe) TAnd arith_expr(r,pe)
1274 { P.arith_op Ast.And $1 $2 $3 }
1275 | arith_expr(r,pe) TOr arith_expr(r,pe)
1276 { P.arith_op Ast.Or $1 $2 $3 }
1277 | arith_expr(r,pe) TXor arith_expr(r,pe)
1278 { P.arith_op Ast.Xor $1 $2 $3 }
1279 | arith_expr(r,pe) TAndLog arith_expr(r,pe)
1280 { P.logic_op Ast.AndLog $1 $2 $3 }
1281 | arith_expr(r,pe) TOrLog arith_expr(r,pe)
1282 { P.logic_op Ast.OrLog $1 $2 $3 }
1285 unary_expr(r,pe) { $1 }
1286 | lp=TOPar t=ctype rp=TCPar e=cast_expr(r,pe)
1287 { Ast0.wrap(Ast0.Cast (P.clt2mcode "(" lp, t,
1288 P.clt2mcode ")" rp, e)) }
1291 postfix_expr(r,pe) { $1 }
1292 | TInc unary_expr(r,pe)
1293 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
1294 | TDec unary_expr(r,pe)
1295 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
1296 | unary_op cast_expr(r,pe)
1297 { let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
1298 | TBang unary_expr(r,pe)
1299 { let mcode = P.clt2mcode Ast.Not $1 in
1300 Ast0.wrap(Ast0.Unary($2, mcode)) }
1301 | TSizeof unary_expr(r,pe)
1302 { Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
1303 | s=TSizeof lp=TOPar t=ctype rp=TCPar
1304 { Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
1305 P.clt2mcode "(" lp,t,
1306 P.clt2mcode ")" rp)) }
1308 unary_op: TAnd { P.clt2mcode Ast.GetRef $1 }
1309 | TMul { P.clt2mcode Ast.DeRef $1 }
1310 | TPlus { P.clt2mcode Ast.UnPlus $1 }
1311 | TMinus { P.clt2mcode Ast.UnMinus $1 }
1312 | TTilde { P.clt2mcode Ast.Tilde $1 }
1315 primary_expr(r,pe) { $1 }
1316 | postfix_expr(r,pe) TOCro eexpr TCCro
1317 { Ast0.wrap(Ast0.ArrayAccess ($1,P.clt2mcode "[" $2,$3,
1318 P.clt2mcode "]" $4)) }
1319 | postfix_expr(r,pe) TDot ident
1320 { Ast0.wrap(Ast0.RecordAccess($1, P.clt2mcode "." $2, $3)) }
1321 | postfix_expr(r,pe) TPtrOp ident
1322 { Ast0.wrap(Ast0.RecordPtAccess($1, P.clt2mcode "->" $2,
1324 | postfix_expr(r,pe) TInc
1325 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Inc $2)) }
1326 | postfix_expr(r,pe) TDec
1327 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Dec $2)) }
1328 | postfix_expr(r,pe) TOPar eexpr_list_option TCPar
1329 { Ast0.wrap(Ast0.FunCall($1,P.clt2mcode "(" $2,
1331 P.clt2mcode ")" $4)) }
1333 primary_expr(recurser,primary_extra):
1334 func_ident { Ast0.wrap(Ast0.Ident($1)) }
1336 { let (x,clt) = $1 in
1337 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1339 { let (x,clt) = $1 in
1340 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Float x) clt)) }
1342 { let (x,clt) = $1 in
1343 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.String x) clt)) }
1345 { let (x,clt) = $1 in
1346 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Char x) clt)) }
1348 { let (nm,constraints,pure,ty,clt) = $1 in
1350 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
1352 { let (nm,constraints,pure,clt) = $1 in
1353 Ast0.wrap(Ast0.MetaErr(P.clt2mcode nm clt,constraints,pure)) }
1355 { let (nm,constraints,pure,ty,clt) = $1 in
1357 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
1359 { let (nm,constraints,pure,ty,clt) = $1 in
1361 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
1363 { let (nm,constraints,pure,ty,clt) = $1 in
1365 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.LocalID,pure)) }
1367 { Ast0.wrap(Ast0.Paren(P.clt2mcode "(" $1,$2,
1368 P.clt2mcode ")" $3)) }
1369 | TOPar0 midzero_list(recurser,eexpr) TCPar0
1370 { let (mids,code) = $2 in
1371 Ast0.wrap(Ast0.DisjExpr(P.clt2mcode "(" $1,
1373 P.clt2mcode ")" $3)) }
1374 | primary_extra { $1 }
1377 r=no_dot_start_end(dexpr,edots_when(dotter,eexpr)) { r }
1380 no_dot_start_end(grammar,dotter):
1381 g=grammar dg=list(pair(dotter,grammar))
1382 { function dot_builder ->
1383 g :: (List.concat(List.map (function (d,g) -> [dot_builder d;g]) dg)) }
1385 /*****************************************************************************/
1391 TRuleName TDot pure_ident { (Some $1,P.id2name $3) }
1393 pure_ident_or_meta_ident:
1394 pure_ident { (None,P.id2name $1) }
1396 | TIdentifier { (None, "identifier") }
1397 | TExpression { (None, "expression") }
1398 | TStatement { (None, "statement") }
1399 | TFunction { (None, "function") }
1400 | TLocal { (None, "local") }
1401 | TType { (None, "type") }
1402 | TParameter { (None, "parameter") }
1403 | TIdExpression { (None, "idexpression") }
1404 | TInitialiser { (None, "initialiser") }
1405 | Tlist { (None, "list") }
1406 | TFresh { (None, "fresh") }
1407 | TConstant { (None, "constant") }
1408 | TError { (None, "error") }
1409 | TWords { (None, "words") }
1410 | TPure { (None, "pure") }
1411 | TContext { (None, "context") }
1412 | TGenerated { (None, "generated") }
1413 | TTypedef { (None, "typedef") }
1414 | TDeclarer { (None, "declarer") }
1415 | TIterator { (None, "iterator") }
1416 | TName { (None, "name") }
1417 | TPosition { (None, "position") }
1419 pure_ident_or_meta_ident_with_seed:
1420 pure_ident_or_meta_ident { ($1,Ast.NoVal) }
1421 | pure_ident_or_meta_ident TEq
1422 separated_nonempty_list(TCppConcatOp,seed_elem)
1424 [Ast.SeedString s] -> ($1,Ast.StringSeed s)
1425 | _ -> ($1,Ast.ListSeed $3) }
1428 TString { let (x,_) = $1 in Ast.SeedString x }
1429 | TMetaId { let (x,_,_,_) = $1 in Ast.SeedId x }
1430 | TRuleName TDot pure_ident
1431 { let nm = ($1,P.id2name $3) in
1432 P.check_meta(Ast.MetaIdDecl(Ast.NONE,nm));
1435 pure_ident_or_meta_ident_with_x_eq(x_eq):
1436 i=pure_ident_or_meta_ident l=loption(x_eq)
1441 pure_ident_or_meta_ident_with_econstraint(x_eq):
1442 i=pure_ident_or_meta_ident optc=option(x_eq)
1445 None -> (i, Ast0.NoConstraint)
1449 pure_ident_or_meta_ident_with_idconstraint(constraint_type):
1450 i=pure_ident_or_meta_ident c=option(constraint_type)
1453 None -> (i, Ast.IdNoConstraint)
1454 | Some constraint_ -> (i,constraint_)
1464 then failwith "constraints not allowed in iso file");
1465 (if !Data.in_generating
1466 then failwith "constraints not allowed in a generated rule file");
1467 let (s,_) = re in Ast.IdRegExp (s,Str.regexp s)
1469 | TTildeExclEq re=TString
1471 then failwith "constraints not allowed in iso file");
1472 (if !Data.in_generating
1473 then failwith "constraints not allowed in a generated rule file");
1474 let (s,_) = re in Ast.IdNotRegExp (s,Str.regexp s)
1480 then failwith "constraints not allowed in iso file");
1481 (if !Data.in_generating
1482 (* pb: constraints not stored with metavars; too lazy to search for
1483 them in the pattern *)
1484 then failwith "constraints not allowed in a generated rule file");
1485 Ast.IdNegIdSet([fst i]) }
1486 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1488 then failwith "constraints not allowed in iso file");
1489 (if !Data.in_generating
1490 then failwith "constraints not allowed in a generated rule file");
1491 Ast.IdNegIdSet(List.map fst l)
1495 re=regexp_eqid {Ast0.NotIdCstrt (re)}
1496 | ne=not_eqe {Ast0.NotExpCstrt (ne)}
1501 then failwith "constraints not allowed in iso file");
1502 (if !Data.in_generating
1503 then failwith "constraints not allowed in a generated rule file");
1504 [Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))]
1506 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1508 then failwith "constraints not allowed in iso file");
1509 (if !Data.in_generating
1510 then failwith "constraints not allowed in a generated rule file");
1513 Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))))
1518 TNotEq i=ident_or_const
1520 then failwith "constraints not allowed in iso file");
1521 (if !Data.in_generating
1522 then failwith "constraints not allowed in a generated rule file");
1524 | TNotEq TOBrace l=comma_list(ident_or_const) TCBrace
1526 then failwith "constraints not allowed in iso file");
1527 (if !Data.in_generating
1528 then failwith "constraints not allowed in a generated rule file");
1532 i=pure_ident { Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))) }
1534 { let (x,clt) = $1 in
1535 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1540 then failwith "constraints not allowed in iso file");
1541 (if !Data.in_generating
1542 then failwith "constraints not allowed in a generated rule file");
1544 (None,_) -> failwith "constraint must be an inherited variable"
1545 | (Some rule,name) ->
1546 let i = (rule,name) in
1547 P.check_meta(Ast.MetaPosDecl(Ast.NONE,i));
1549 | TNotEq TOBrace l=comma_list(meta_ident) TCBrace
1551 then failwith "constraints not allowed in iso file");
1552 (if !Data.in_generating
1553 then failwith "constraints not allowed in a generated rule file");
1557 failwith "constraint must be an inherited variable"
1558 | (Some rule,name) ->
1559 let i = (rule,name) in
1560 P.check_meta(Ast.MetaPosDecl(Ast.NONE,i));
1564 func_ident: pure_ident
1565 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1567 { let (nm,constraints,pure,clt) = $1 in
1568 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1570 { let (nm,constraints,pure,clt) = $1 in
1571 Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
1573 { let (nm,constraints,pure,clt) = $1 in
1575 (Ast0.MetaLocalFunc(P.clt2mcode nm clt,constraints,pure)) }
1578 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1580 { let (nm,constraints,pure,clt) = $1 in
1581 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1585 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1587 { let (nm,constraints,pure,clt) = $1 in
1588 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1592 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1594 { let (nm,constraints,pure,clt) = $1 in
1595 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1599 { Ast0.wrap(Ast0.TypeName(P.id2mcode $1)) }
1601 { let (nm,pure,clt) = $1 in
1602 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
1604 /*****************************************************************************/
1607 /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
1608 | decl_list_start(decl)
1610 match Ast0.unwrap x with Ast0.Pcircles(_) -> true | _ -> false in
1611 if List.exists circle $1
1612 then Ast0.wrap(Ast0.CIRCLES($1))
1613 else Ast0.wrap(Ast0.DOTS($1)) }
1615 decl_list_start(decl):
1616 one_dec(decl) { [$1] }
1617 | one_dec(decl) TComma decl_list_start(decl)
1618 { $1::Ast0.wrap(Ast0.PComma(P.clt2mcode "," $2))::$3 }
1619 | TEllipsis list(comma_decls(TEllipsis,decl))
1620 { Ast0.wrap(Ast0.Pdots(P.clt2mcode "..." $1))::
1621 (List.concat(List.map (function x -> x (P.mkpdots "...")) $2)) }
1626 { let (nm,lenname,pure,clt) = $1 in
1627 let nm = P.clt2mcode nm clt in
1630 Some nm -> Some(P.clt2mcode nm clt)
1632 Ast0.wrap(Ast0.MetaParamList(nm,lenname,pure)) }
1634 comma_decls(dotter,decl):
1636 { function dot_builder ->
1637 [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1));
1639 | TComma one_dec(decl)
1640 { function dot_builder ->
1641 [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1)); $2] }
1643 /* ---------------------------------------------------------------------- */
1645 /* error words make it complicated to be able to use error as a metavariable
1646 name or a type in a metavariable list; for that we would like to allow TError
1647 as an ident, but that makes conflicts with this rule. To add back error words,
1648 need to find some appropriate delimiter for it, but it has not been used much
1651 TError TWords TEq TOCro cl=comma_list(dexpr) TCCro
1652 { [Ast0.wrap(Ast0.ERRORWORDS(cl))] }
1655 /* ---------------------------------------------------------------------- */
1656 /* sequences of statements and expressions */
1658 /* There are number of cases that must be considered:
1661 Dots and nests allowed at the beginning or end
1662 Expressions allowed at the beginning or end
1663 One function allowed, by itself
1665 Dots and nests allowed at the beginning or end
1666 Expressions not allowed at the beginning or end
1667 Functions not allowed
1668 3. The body of a nest:
1669 Dots and nests not allowed at the beginning or end
1670 Expressions allowed at the beginning or end
1671 Functions not allowed
1673 Dots and nests not allowed at the beginning but allowed at the end
1674 Expressions allowed at the beginning or end
1675 Functions not allowed
1677 These are implemented by the rules minus_toplevel_sequence,
1678 plus_toplevel_sequence, function_body_sequence, nest_body_sequence, and
1681 /* ------------------------------------------------------------------------ */
1682 /* Minus top level */
1684 /* doesn't allow only ... */
1686 fundecl { [Ast0.wrap(Ast0.DECL($1))] }
1687 | ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1688 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1689 | toplevel_seq_startne(toplevel_after_dots_init)
1690 { List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1 }
1692 toplevel_seq_startne(after_dots_init):
1693 a=stm_dots_ell b=after_dots_init { a::b }
1694 | a=stm_dots_nest b=after_dots_init { a::b }
1695 | a=stm_dots_nest { [a] }
1696 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1697 | decl_statement_expr toplevel_after_stm { $1@$2 }
1699 toplevel_seq_start(after_dots_init):
1700 stm_dots after_dots_init { $1::$2 }
1701 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1702 | decl_statement_expr toplevel_after_stm { $1@$2 }
1704 toplevel_after_dots_init:
1705 TNothing toplevel_after_exp {$2}
1706 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1707 | decl_statement_expr toplevel_after_stm {$1@$2}
1711 | stm_dots toplevel_after_dots {$1::$2}
1713 toplevel_after_dots:
1715 | TNothing toplevel_after_exp {$2}
1716 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1717 | decl_statement_expr toplevel_after_stm {$1@$2}
1721 | stm_dots toplevel_after_dots {$1::$2}
1722 | decl_statement toplevel_after_stm {$1@$2}
1725 TOInit initialize_list TCBrace
1726 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1728 /* ------------------------------------------------------------------------ */
1729 /* Plus top level */
1731 /* does allow only ... also allows multiple top-level functions */
1733 ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1734 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1735 | stm_dots plus_after_dots
1736 { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1737 | expr plus_after_exp
1738 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1739 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1740 | decl_statement_expr plus_after_stm
1741 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1745 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1749 | TNothing plus_after_exp {$2}
1750 | expr plus_after_exp
1751 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1752 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1753 | decl_statement_expr plus_after_stm
1754 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1758 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1759 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1760 | decl_statement plus_after_stm
1761 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1763 /* ------------------------------------------------------------------------ */
1767 fun_after_stm { Ast0.wrap(Ast0.DOTS($1)) }
1771 | stm_dots fun_after_dots {$1::$2}
1772 | decl_statement fun_after_stm {$1@$2}
1776 | TNothing fun_after_exp {$2}
1777 | expr fun_after_exp {Ast0.wrap(Ast0.Exp($1))::$2}
1778 | decl_statement_expr fun_after_stm {$1@$2}
1781 stm_dots fun_after_dots {$1::$2}
1783 /* hack to allow mixing statements and expressions in an or */
1786 | TNothing fun_after_exp_or {$2}
1787 | expr fun_after_exp_or {Ast0.wrap(Ast0.Exp($1))::$2}
1788 | decl_statement_expr fun_after_stm {$1@$2}
1792 | stm_dots fun_after_dots {$1::$2}
1794 /* ------------------------------------------------------------------------ */
1798 nest_after_dots { Ast0.wrap(Ast0.DOTS($1)) }
1801 decl_statement_expr nest_after_stm {$1@$2}
1802 | TNothing nest_after_exp {$2}
1803 | expr nest_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1807 | stm_dots nest_after_dots {$1::$2}
1808 | decl_statement nest_after_stm {$1@$2}
1812 | stm_dots nest_after_dots {$1::$2}
1814 /* ------------------------------------------------------------------------ */
1818 expr toplevel_after_exp
1819 { Ast0.wrap(Ast0.DOTS((Ast0.wrap(Ast0.Exp($1)))::$2)) }
1820 | decl_statement toplevel_after_stm
1821 { Ast0.wrap(Ast0.DOTS($1@$2)) }
1823 /* ---------------------------------------------------------------------- */
1828 match Ast0.unwrap x with Ast0.Ecircles(_) -> true | _ -> false in
1830 match Ast0.unwrap x with Ast0.Estars(_) -> true | _ -> false in
1831 if List.exists circle $1
1832 then Ast0.wrap(Ast0.CIRCLES($1))
1834 if List.exists star $1
1835 then Ast0.wrap(Ast0.STARS($1))
1836 else Ast0.wrap(Ast0.DOTS($1)) }
1838 /* arg expr. may contain a type or a explist metavariable */
1841 { Ast0.set_arg_exp $1 }
1843 { let (nm,lenname,pure,clt) = $1 in
1844 let nm = P.clt2mcode nm clt in
1847 Some nm -> Some(P.clt2mcode nm clt)
1849 Ast0.wrap(Ast0.MetaExprList(nm,lenname,pure)) }
1851 { Ast0.set_arg_exp(Ast0.wrap(Ast0.TypeExp($1))) }
1855 | aexpr TComma eexpr_list_start
1856 { $1::Ast0.wrap(Ast0.EComma(P.clt2mcode "," $2))::$3 }
1860 { function dot_builder ->
1861 [Ast0.wrap(Ast0.EComma(P.clt2mcode "," c)); dot_builder d] }
1863 { function dot_builder ->
1864 [Ast0.wrap(Ast0.EComma(P.clt2mcode "," $1)); $2] }
1866 eexpr_list_option: eexpr_list { $1 }
1867 | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
1869 /****************************************************************************/
1871 // non-empty lists - drop separator
1873 separated_nonempty_list(TComma,elem) { $1 }
1875 midzero_list(elem,aft):
1876 a=elem b=list(mzl(aft))
1877 { let (mids,code) = List.split b in (mids,(a::code)) }
1880 a=TMid0 b=elem { (P.clt2mcode "|" a, b) }
1882 edots_when(dotter,when_grammar):
1883 d=dotter { (d,None) }
1884 | d=dotter TWhen TNotEq w=when_grammar TLineEnd { (d,Some w) }
1886 whens(when_grammar,simple_when_grammar,any_strict):
1887 TWhen TNotEq w=when_grammar TLineEnd { [Ast0.WhenNot w] }
1888 | TWhen TEq w=simple_when_grammar TLineEnd { [Ast0.WhenAlways w] }
1889 | TWhen comma_list(any_strict) TLineEnd
1890 { List.map (function x -> Ast0.WhenModifier(x)) $2 }
1891 | TWhenTrue TNotEq e = eexpr TLineEnd { [Ast0.WhenNotTrue e] }
1892 | TWhenFalse TNotEq e = eexpr TLineEnd { [Ast0.WhenNotFalse e] }
1895 TAny { Ast.WhenAny }
1896 | TStrict { Ast.WhenStrict }
1897 | TForall { Ast.WhenForall }
1898 | TExists { Ast.WhenExists }
1900 /*****************************************************************************
1903 *****************************************************************************/
1906 TIsoExpression e1=dexpr el=list(iso(dexpr)) EOF
1907 { P.iso_adjust (function x -> Ast0.ExprTag x) e1 el }
1908 | TIsoArgExpression e1=dexpr el=list(iso(dexpr)) EOF
1909 { P.iso_adjust (function x -> Ast0.ArgExprTag x) e1 el }
1910 | TIsoTestExpression e1=dexpr el=list(iso(dexpr)) EOF
1911 { P.iso_adjust (function x -> Ast0.TestExprTag x) e1 el }
1912 | TIsoStatement s1=single_statement sl=list(iso(single_statement)) EOF
1913 { P.iso_adjust (function x -> Ast0.StmtTag x) s1 sl }
1914 | TIsoType t1=ctype tl=list(iso(ctype)) EOF
1915 { P.iso_adjust (function x -> Ast0.TypeCTag x) t1 tl }
1916 | TIsoTopLevel e1=nest_start el=list(iso(nest_start)) EOF
1917 { P.iso_adjust (function x -> Ast0.DotsStmtTag x) e1 el }
1918 | TIsoDeclaration d1=decl_var dl=list(iso(decl_var)) EOF
1919 { let check_one = function
1923 (Semantic_cocci.Semantic
1924 "only one variable per declaration in an isomorphism rule") in
1925 let d1 = check_one d1 in
1929 Common.Left x -> Common.Left(check_one x)
1930 | Common.Right x -> Common.Right(check_one x))
1932 P.iso_adjust (function x -> Ast0.DeclTag x) d1 dl }
1935 TIso t=term { Common.Left t }
1936 | TRightIso t=term { Common.Right t }
1938 /*****************************************************************************
1941 *****************************************************************************/
1943 never_used: TPragma { () }
1944 | TPArob TMetaPos { () }
1945 | TScriptData { () }
1947 script_meta_main: py=pure_ident TShOp TRuleName TDot cocci=pure_ident TMPtVirg
1948 { (P.id2name py, ($3, P.id2name cocci)) }