3 (* Not clear how to allow function declarations to specify a return type
4 and how to allow both to be specified as static, because they are in
5 different rules. The rules seem to have to be combined, which would allow
6 functions to be declared as local variables *)
8 (* Not clear how to let a function have a parameter of type void. At the
9 moment, void is allowed to be the type of a variable, which is wrong, and a
10 parameter needs both a type and an identifier *)
11 module Ast0 = Ast0_cocci
12 module Ast = Ast_cocci
18 %token TIdentifier TExpression TStatement TFunction TLocal TType TParameter
19 %token TIdExpression TInitialiser
20 %token Tlist TFresh TConstant TError TWords TWhy0 TPlus0 TBang0
21 %token TPure TContext TGenerated
22 %token TTypedef TDeclarer TIterator TName TPosition TPosAny
23 %token TUsing TDisable TExtends TDepends TOn TEver TNever TExists TForall
24 %token TScript TInitialize TFinalize TNothing TVirtual
25 %token<string> TRuleName
27 %token<Data.clt> Tchar Tshort Tint Tdouble Tfloat Tlong
28 %token<Data.clt> Tvoid Tstruct Tunion Tenum
29 %token<Data.clt> Tunsigned Tsigned
31 %token<Data.clt> Tstatic Tauto Tregister Textern Tinline Ttypedef
32 %token<Data.clt> Tconst Tvolatile
33 %token<string * Data.clt> Tattr
35 %token <Data.clt> TIf TElse TWhile TFor TDo TSwitch TCase TDefault TReturn
36 %token <Data.clt> TBreak TContinue TGoto TSizeof TFunDecl
37 %token <string * Data.clt> TIdent TTypeId TDeclarerId TIteratorId TPragma
39 %token <Parse_aux.idinfo> TMetaId TMetaFunc TMetaLocalFunc
40 %token <Parse_aux.idinfo> TMetaIterator TMetaDeclarer
41 %token <Parse_aux.expinfo> TMetaErr
42 %token <Parse_aux.info> TMetaParam TMetaStm TMetaStmList TMetaType
43 %token <Parse_aux.info> TMetaInit
44 %token <Parse_aux.list_info> TMetaParamList TMetaExpList
45 %token <Parse_aux.typed_expinfo> TMetaExp TMetaIdExp TMetaLocalIdExp TMetaConst
46 %token <Parse_aux.pos_info> TMetaPos
48 %token TArob TArobArob TPArob
49 %token <string> TScriptData
51 %token <Data.clt> TEllipsis TOEllipsis TCEllipsis TPOEllipsis TPCEllipsis
52 %token <Data.clt> TWhen TWhenTrue TWhenFalse TAny TStrict TLineEnd
54 %token <Data.clt> TWhy TDotDot TBang TOPar TOPar0
55 %token <Data.clt> TMid0 TCPar TCPar0
57 %token <string> TPathIsoFile
58 %token <string * Data.clt> TIncludeL TIncludeNL
59 %token <Data.clt * token> TDefine
60 %token <Data.clt * token * int * int> TDefineParam
61 %token <string * Data.clt> TMinusFile TPlusFile
63 %token <Data.clt> TInc TDec
65 %token <string * Data.clt> TString TChar TFloat TInt
67 %token <Data.clt> TOrLog
68 %token <Data.clt> TAndLog
70 %token <Data.clt> TXor
71 %token <Data.clt> TAnd
72 %token <Data.clt> TEqEq TNotEq TTildeEq TTildeExclEq
73 %token <Ast_cocci.logicalOp * Data.clt> TLogOp /* TInf TSup TInfEq TSupEq */
74 %token <Ast_cocci.arithOp * Data.clt> TShOp /* TShl TShr */
75 %token <Ast_cocci.arithOp * Data.clt> TDmOp /* TDiv TMod */
76 %token <Data.clt> TPlus TMinus
77 %token <Data.clt> TMul TTilde
79 %token <Data.clt> TOBrace TCBrace TOInit
80 %token <Data.clt> TOCro TCCro
82 %token <Data.clt> TPtrOp
84 %token TMPtVirg TCppConcatOp
85 %token <Data.clt> TEq TDot TComma TPtVirg
86 %token <Ast_cocci.assignOp * Data.clt> TAssign
88 %token TIso TRightIso TIsoExpression TIsoStatement TIsoDeclaration TIsoType
89 %token TIsoTopLevel TIsoArgExpression TIsoTestExpression
93 /* operator precedence */
103 %left TLogOp /* TInf TSup TInfEq TSupEq */
104 %left TShOp /* TShl TShr */
106 %left TMul TDmOp /* TDiv TMod */
112 %type <Ast0_cocci.rule> minus_main
114 %start minus_exp_main
115 %type <Ast0_cocci.rule> minus_exp_main
118 %type <Ast0_cocci.rule> plus_main
121 %type <Ast0_cocci.rule> plus_exp_main
124 %type <Data.incl_iso list> include_main
127 %type <Ast_cocci.rulename>
131 %type <Ast_cocci.rulename>
135 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> meta_main
137 %start <string * (string * string)> script_meta_main
140 %type <Ast0_cocci.anything list list> iso_main
143 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> iso_meta_main
146 %type <unit> never_used
151 minus_main: minus_body EOF { $1 } | m=minus_body TArobArob { m }
152 | m=minus_body TArob { m }
153 plus_main: plus_body EOF { $1 } | p=plus_body TArobArob { p }
154 | p=plus_body TArob { p }
155 minus_exp_main: minus_exp_body EOF { $1 } | m=minus_exp_body TArobArob { m }
156 | m=minus_exp_body TArob { m }
157 plus_exp_main: plus_exp_body EOF { $1 } | p=plus_exp_body TArobArob { p }
158 | p=plus_exp_body TArob { p }
159 meta_main: m=metadec { m (!Ast0.rule_name) }
160 iso_meta_main: m=metadec { m "" }
162 /*****************************************************************************
165 *****************************************************************************/
169 | TContext { Ast0.Context }
170 | TPure TContext { Ast0.PureContext }
171 | TContext TPure { Ast0.PureContext }
172 | /* empty */ { Ast0.Impure }
175 nm=pure_ident TArob { P.make_iso_rule_name_result (P.id2name nm) }
178 nm=ioption(pure_ident) extends d=depends i=loption(choose_iso)
179 a=loption(disable) e=exists ee=is_expression TArob
180 { P.make_cocci_rule_name_result nm d i a e ee }
181 | TGenerated extends d=depends i=loption(choose_iso)
182 a=loption(disable) e=exists ee=is_expression TArob
183 /* these rules have no name as a cheap way to ensure that no normal
184 rule inherits their metavariables or depends on them */
185 { P.make_generated_rule_name_result None d i a e ee }
186 | TScript TDotDot lang=pure_ident d=depends TArob
187 { P.make_script_rule_name_result lang d }
188 | TInitialize TDotDot lang=pure_ident TArob
189 { P.make_initial_script_rule_name_result lang }
190 | TFinalize TDotDot lang=pure_ident TArob
191 { P.make_final_script_rule_name_result lang }
195 | TExtends parent=TRuleName
196 { !Data.install_bindings (parent) }
199 /* empty */ { Ast.NoDep }
200 | TDepends TOn parents=dep { parents }
204 | dep TAndLog dep { Ast.AndDep($1, $3) }
205 | dep TOrLog dep { Ast.OrDep ($1, $3) }
208 TRuleName { Ast.Dep $1 }
209 | TBang TRuleName { Ast.AntiDep $2 }
210 | TEver TRuleName { Ast.EverDep $2 }
211 | TNever TRuleName { Ast.NeverDep $2 }
212 | TOPar dep TCPar { $2 }
215 TUsing separated_nonempty_list(TComma,TString) { List.map P.id2name $2 }
218 TDisable separated_nonempty_list(TComma,pure_ident) { List.map P.id2name $2 }
221 TExists { Ast.Exists }
222 | TForall { Ast.Forall }
223 | { Ast.Undetermined }
225 is_expression: // for more flexible parsing of top level expressions
227 | TExpression { true }
230 list(incl) TArob { $1 }
231 | list(incl) TArobArob { $1 }
234 TIncludeL { let (x,_) = $1 in Data.Include(x) }
235 | TUsing TString { Data.Iso(Common.Left(P.id2name $2)) }
236 | TUsing TPathIsoFile { Data.Iso(Common.Right $2) }
237 | TVirtual comma_list(pure_ident)
238 { let names = List.map P.id2name $2 in
239 (* ensure that the names of virtual and real rules don't overlap *)
241 (function name -> Hashtbl.add Data.all_metadecls name [])
247 kindfn=metakind ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
248 { P.create_metadec ar ispure kindfn ids }
249 | kindfn=metakind_fresh ids=comma_list(pure_ident_or_meta_ident_with_seed)
251 { P.create_fresh_metadec kindfn ids }
252 | ar=arity ispure=pure
253 kindfn=metakind_atomic
254 ids=comma_list(pure_ident_or_meta_ident_with_idconstraint(re_or_not_eqid))
256 { P.create_metadec_with_constraints ar ispure kindfn ids }
257 | ar=arity ispure=pure
258 kindfn=metakind_atomic_expi
259 ids=comma_list(pure_ident_or_meta_ident_with_econstraint(re_or_not_eqe))
261 { P.create_metadec_with_constraints ar ispure kindfn ids }
262 | ar=arity ispure=pure
263 kindfn=metakind_atomic_expe
264 ids=comma_list(pure_ident_or_meta_ident_with_x_eq(not_ceq)) TMPtVirg
265 { P.create_metadec_with_constraints ar ispure kindfn ids }
266 | ar=arity TPosition a=option(TPosAny)
267 ids=comma_list(pure_ident_or_meta_ident_with_x_eq(not_pos)) TMPtVirg
268 (* pb: position variables can't be inherited from normal rules, and then
269 there is no way to inherit from a generated rule, so there is no point
270 to have a position variable *)
271 { (if !Data.in_generating
272 then failwith "position variables not allowed in a generated rule file");
273 let kindfn arity name pure check_meta constraints =
274 let tok = check_meta(Ast.MetaPosDecl(arity,name)) in
275 let any = match a with None -> Ast.PER | Some _ -> Ast.ALL in
276 !Data.add_pos_meta name constraints any; tok in
277 P.create_metadec_with_constraints ar false kindfn ids }
278 | ar=arity ispure=pure
279 TParameter Tlist TOCro id=pure_ident_or_meta_ident TCCro
280 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
281 { P.create_len_metadec ar ispure
282 (fun lenname arity name pure check_meta ->
284 check_meta(Ast.MetaParamListDecl(arity,name,Some lenname)) in
285 !Data.add_paramlist_meta name (Some lenname) pure; tok)
287 | ar=arity ispure=pure
288 TExpression Tlist TOCro id=pure_ident_or_meta_ident TCCro
289 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
290 { P.create_len_metadec ar ispure
291 (fun lenname arity name pure check_meta ->
293 check_meta(Ast.MetaExpListDecl(arity,name,Some lenname)) in
294 !Data.add_explist_meta name (Some lenname) pure; tok)
297 %inline metakind_fresh:
299 { (fun name check_meta seed ->
300 let tok = check_meta(Ast.MetaFreshIdDecl(name,seed)) in
301 !Data.add_fresh_id_meta name; tok) }
305 { (fun arity name pure check_meta ->
306 let tok = check_meta(Ast.MetaParamDecl(arity,name)) in
307 !Data.add_param_meta name pure; tok) }
309 { (fun arity name pure check_meta ->
310 let tok = check_meta(Ast.MetaParamListDecl(arity,name,None)) in
311 !Data.add_paramlist_meta name None pure; tok) }
313 { (fun arity name pure check_meta ->
314 let tok = check_meta(Ast.MetaExpListDecl(arity,name,None)) in
315 !Data.add_explist_meta name None pure; tok) }
317 { (fun arity name pure check_meta ->
318 let tok = check_meta(Ast.MetaTypeDecl(arity,name)) in
319 !Data.add_type_meta name pure; tok) }
321 { (fun arity name pure check_meta ->
322 let tok = check_meta(Ast.MetaInitDecl(arity,name)) in
323 !Data.add_init_meta name pure; tok) }
325 { (fun arity name pure check_meta ->
326 let tok = check_meta(Ast.MetaStmDecl(arity,name)) in
327 !Data.add_stm_meta name pure; tok) }
329 { (fun arity name pure check_meta ->
330 let tok = check_meta(Ast.MetaStmListDecl(arity,name)) in
331 !Data.add_stmlist_meta name pure; tok) }
333 { (fun arity (_,name) pure check_meta ->
334 if arity = Ast.NONE && pure = Ast0.Impure
335 then (!Data.add_type_name name; [])
336 else raise (Semantic_cocci.Semantic "bad typedef")) }
338 { (fun arity (_,name) pure check_meta ->
339 if arity = Ast.NONE && pure = Ast0.Impure
340 then (!Data.add_declarer_name name; [])
341 else raise (Semantic_cocci.Semantic "bad declarer")) }
343 { (fun arity (_,name) pure check_meta ->
344 if arity = Ast.NONE && pure = Ast0.Impure
345 then (!Data.add_iterator_name name; [])
346 else raise (Semantic_cocci.Semantic "bad iterator")) }
348 %inline metakind_atomic:
350 { (fun arity name pure check_meta constraints ->
351 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
352 !Data.add_id_meta name constraints pure; tok) }
354 { (fun arity name pure check_meta constraints ->
355 let tok = check_meta(Ast.MetaFuncDecl(arity,name)) in
356 !Data.add_func_meta name constraints pure; tok) }
358 { (fun arity name pure check_meta constraints ->
359 let tok = check_meta(Ast.MetaLocalFuncDecl(arity,name)) in
360 !Data.add_local_func_meta name constraints pure;
363 { (fun arity name pure check_meta constraints ->
364 let tok = check_meta(Ast.MetaDeclarerDecl(arity,name)) in
365 !Data.add_declarer_meta name constraints pure; tok) }
367 { (fun arity name pure check_meta constraints ->
368 let tok = check_meta(Ast.MetaIteratorDecl(arity,name)) in
369 !Data.add_iterator_meta name constraints pure; tok) }
371 %inline metakind_atomic_expi:
373 { (fun arity name pure check_meta constraints ->
374 let tok = check_meta(Ast.MetaErrDecl(arity,name)) in
375 !Data.add_err_meta name constraints pure; tok) }
376 | l=option(TLocal) TIdExpression ty=ioption(meta_exp_type)
377 { (fun arity name pure check_meta constraints ->
380 !Data.add_idexp_meta ty name constraints pure;
381 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
383 !Data.add_local_idexp_meta ty name constraints pure;
384 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
385 | l=option(TLocal) TIdExpression m=nonempty_list(TMul)
386 { (fun arity name pure check_meta constraints ->
387 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
390 !Data.add_idexp_meta ty name constraints pure;
391 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
393 !Data.add_local_idexp_meta ty name constraints pure;
394 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
395 | TExpression m=nonempty_list(TMul)
396 { (fun arity name pure check_meta constraints ->
397 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
398 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
399 !Data.add_exp_meta ty name constraints pure; tok) }
400 | vl=meta_exp_type TOCro TCCro
401 { (fun arity name pure check_meta constraints ->
402 let ty = Some (List.map (function x -> Type_cocci.Array x) vl) in
403 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
404 !Data.add_exp_meta ty name constraints pure; tok) }
405 | TConstant ty=ioption(meta_exp_type)
406 { (fun arity name pure check_meta constraints ->
407 let tok = check_meta(Ast.MetaConstDecl(arity,name,ty)) in
408 !Data.add_const_meta ty name constraints pure; tok) }
410 %inline metakind_atomic_expe:
412 { (fun arity name pure check_meta constraints ->
413 let tok = check_meta(Ast.MetaExpDecl(arity,name,None)) in
414 !Data.add_exp_meta None name (Ast0.NotExpCstrt constraints) pure; tok) }
415 | vl=meta_exp_type // no error if use $1 but doesn't type check
416 { (fun arity name pure check_meta constraints ->
420 match Ast0.unwrap c with
425 Type_cocci.BaseType(Type_cocci.IntType) -> true
426 | Type_cocci.BaseType(Type_cocci.ShortType) -> true
427 | Type_cocci.BaseType(Type_cocci.LongType) -> true
430 then failwith "metavariable with int constraint must be an int"
433 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
434 !Data.add_exp_meta ty name (Ast0.NotExpCstrt constraints) pure; tok)
440 { [Ast0_cocci.ast0_type_to_type t] }
441 | TOBrace t=comma_list(ctype) TCBrace m=list(TMul)
443 (function x -> P.ty_pointerify (Ast0_cocci.ast0_type_to_type x) m)
446 arity: TBang0 { Ast.UNIQUE }
448 | TPlus0 { Ast.MULTI }
449 | /* empty */ { Ast.NONE }
451 /* ---------------------------------------------------------------------- */
456 { Ast0.wrap(Ast0.BaseType(Ast.CharType,[P.clt2mcode "char" ty])) }
458 { Ast0.wrap(Ast0.BaseType(Ast.ShortType,[P.clt2mcode "short" ty])) }
460 { Ast0.wrap(Ast0.BaseType(Ast.IntType,[P.clt2mcode "int" ty])) }
462 { let (nm,pure,clt) = p in
463 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
464 | r=TRuleName TDot p=TIdent
465 { let nm = (r,P.id2name p) in
466 (* this is only possible when we are in a metavar decl. Otherwise,
467 it will be represented already as a MetaType *)
468 let _ = P.check_meta(Ast.MetaTypeDecl(Ast.NONE,nm)) in
469 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm (P.id2clt p),
470 Ast0.Impure (*will be ignored*))) }
472 { Ast0.wrap(Ast0.BaseType(Ast.LongType,[P.clt2mcode "long" ty])) }
473 | ty1=Tlong ty2=Tlong
477 [P.clt2mcode "long" ty1;P.clt2mcode "long" ty2])) }
482 { Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" ty])) }
484 { Ast0.wrap(Ast0.BaseType(Ast.DoubleType,[P.clt2mcode "double" ty])) }
486 { Ast0.wrap(Ast0.BaseType(Ast.FloatType,[P.clt2mcode "float" ty])) }
488 { Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, i)) }
489 | s=struct_or_union i=ident
490 { Ast0.wrap(Ast0.StructUnionName(s, Some i)) }
491 | s=struct_or_union i=ioption(ident)
492 l=TOBrace d=struct_decl_list r=TCBrace
493 { (if i = None && !Data.in_iso
494 then failwith "structures must be named in the iso file");
495 Ast0.wrap(Ast0.StructUnionDef(Ast0.wrap(Ast0.StructUnionName(s, i)),
497 d, P.clt2mcode "}" r)) }
498 | s=TMetaType l=TOBrace d=struct_decl_list r=TCBrace
499 { let (nm,pure,clt) = s in
500 let ty = Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) in
501 Ast0.wrap(Ast0.StructUnionDef(ty,P.clt2mcode "{" l,d,P.clt2mcode "}" r)) }
503 { Ast0.wrap(Ast0.TypeName(P.id2mcode p)) }
507 r=Tsigned ty=signable_types
508 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,Some ty)) }
509 | r=Tunsigned ty=signable_types
510 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,Some ty)) }
511 | ty=signable_types { ty }
512 | ty=non_signable_types { ty }
515 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
516 { P.pointerify (P.make_cv cv ty) m }
518 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,None)) }
520 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,None)) }
521 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
522 { let (mids,code) = t in
524 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
526 /* signed, unsigned alone not allowed */
528 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
529 { P.pointerify (P.make_cv cv ty) m }
530 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
531 { let (mids,code) = t in
533 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
535 /* ---------------------------------------------------------------------- */
538 s=Tstruct { P.clt2mcode Ast.Struct s }
539 | u=Tunion { P.clt2mcode Ast.Union u }
543 | t=ctype d=d_ident pv=TPtVirg
545 [Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] }
546 | t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
547 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar pv=TPtVirg
551 (Ast0.FunctionPointer
552 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
553 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
554 [Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] }
555 | cv=ioption(const_vol) i=pure_ident d=d_ident pv=TPtVirg
557 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
558 [Ast0.wrap(Ast0.UnInit(None,fn idtype,id,P.clt2mcode ";" pv))] }
561 struct_decl_list_start { Ast0.wrap(Ast0.DOTS($1)) }
563 struct_decl_list_start:
565 | struct_decl struct_decl_list_start { $1@$2 }
566 | d=edots_when(TEllipsis,struct_decl) r=continue_struct_decl_list
567 { (P.mkddots "..." d)::r }
569 continue_struct_decl_list:
571 | struct_decl struct_decl_list_start { $1@$2 }
575 /*****************************************************************************/
577 /* have to inline everything to avoid conflicts? switch to proper
578 declarations, statements, and expressions for the subterms */
582 b=loption(minus_start)
583 /*ew=loption(error_words)*/
584 { match f@b(*@ew*) with
585 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
586 | code -> Top_level.top_level code }
590 b=loption(plus_start)
591 /*ew=loption(error_words)*/
592 { Top_level.top_level (f@b(*@ew*)) }
597 /*ew=loption(error_words)*/
598 { match f@[b](*@ew*) with
599 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
600 | code -> Top_level.top_level code }
605 /*ew=loption(error_words)*/
606 { Top_level.top_level (f@[b](*@ew*)) }
611 (Ast0.FILEINFO(P.id2mcode $1,
617 (Ast0.Include(P.clt2mcode "#include"
618 (P.drop_pos (P.drop_aft (P.id2clt $1))),
619 let (arity,ln,lln,offset,col,strbef,straft,pos) =
622 (arity,ln,lln,offset,0,strbef,straft,pos) in
624 (Ast.Local (Parse_aux.str2inc (P.id2name $1)))
628 (Ast0.Include(P.clt2mcode "#include"
629 (P.drop_pos (P.drop_aft (P.id2clt $1))),
630 let (arity,ln,lln,offset,col,strbef,straft,pos) =
633 (arity,ln,lln,offset,0,strbef,straft,pos) in
635 (Ast.NonLocal (Parse_aux.str2inc (P.id2name $1)))
637 | d=defineop t=ctype TLineEnd
638 { let ty = Ast0.wrap(Ast0.TopExp(Ast0.wrap(Ast0.TypeExp(t)))) in
639 d (Ast0.wrap(Ast0.DOTS([ty]))) }
640 | defineop b=toplevel_seq_start(toplevel_after_dots) TLineEnd
644 (match Ast0.unwrap e with
646 [Ast0.rewrap e (Ast0.TopExp(Ast0.set_arg_exp (e1)))]
649 $1 (Ast0.wrap(Ast0.DOTS(body))) }
653 { let (clt,ident) = $1 in
657 (P.clt2mcode "#define" clt,
659 TMetaId((nm,constraints,pure,clt)) ->
660 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
662 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
665 (Semantic_cocci.Semantic
666 "unexpected name for a #define")),
667 Ast0.wrap Ast0.NoParams,
669 | TDefineParam define_param_list_option TCPar
670 { let (clt,ident,parenoff,parencol) = $1 in
671 (* clt is the start of the #define itself *)
672 let (arity,line,lline,offset,col,strbef,straft,pos) = clt in
675 (arity,line,lline,parenoff,parencol,[],[],Ast0.NoMetaPos) in
679 (P.clt2mcode "#define" clt,
681 TMetaId((nm,constraints,pure,clt)) ->
682 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
684 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
687 (Semantic_cocci.Semantic
688 "unexpected name for a #define")),
689 Ast0.wrap (Ast0.DParams (lp,$2,P.clt2mcode ")" $3)),body)) }
691 /* ---------------------------------------------------------------------- */
693 define_param_list: define_param_list_start
695 match Ast0.unwrap x with Ast0.DPcircles(_) -> true | _ -> false in
696 if List.exists circle $1
697 then Ast0.wrap(Ast0.CIRCLES($1))
698 else Ast0.wrap(Ast0.DOTS($1)) }
700 define_param_list_start:
701 ident { [Ast0.wrap(Ast0.DParam $1)] }
702 | ident TComma define_param_list_start
703 { Ast0.wrap(Ast0.DParam $1)::
704 Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $2))::$3 }
705 | d=TEllipsis r=list(dp_comma_args(TEllipsis))
706 { (P.mkdpdots "..." d)::
707 (List.concat (List.map (function x -> x (P.mkdpdots "...")) r)) }
709 dp_comma_args(dotter):
711 { function dot_builder ->
712 [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," c)); dot_builder d] }
714 { function dot_builder ->
715 [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $1));
716 Ast0.wrap(Ast0.DParam $2)] }
718 define_param_list_option: define_param_list { $1 }
719 | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
721 /*****************************************************************************/
724 s=ioption(storage) t=ctype
725 id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
730 (Ast0.FunctionType(Some t,
731 P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
732 id, P.clt2mcode ";" pt)) }
736 TFunDecl i=func_ident lp=TOPar d=decl_list(decl) rp=TCPar
737 lb=TOBrace b=fun_start rb=TCBrace
738 { P.verify_parameter_declarations (Ast0.undots d);
739 Ast0.wrap(Ast0.FunDecl((Ast0.default_info(),Ast0.context_befaft()),
741 P.clt2mcode "(" lp, d,
743 P.clt2mcode "{" lb, b,
744 P.clt2mcode "}" rb)) }
751 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
752 raise (Semantic_cocci.Semantic "duplicate storage")
753 with Not_found -> (Ast0.FStorage($1))::$2 }
754 | t=ctype r=fninfo_nt { (Ast0.FType(t))::r }
757 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
758 raise (Semantic_cocci.Semantic "duplicate inline")
759 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
762 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
763 raise (Semantic_cocci.Semantic "multiple attributes")
764 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
771 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
772 raise (Semantic_cocci.Semantic "duplicate storage")
773 with Not_found -> (Ast0.FStorage($1))::$2 }
776 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
777 raise (Semantic_cocci.Semantic "duplicate inline")
778 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
781 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
782 raise (Semantic_cocci.Semantic "duplicate init")
783 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
786 s=Tstatic { P.clt2mcode Ast.Static s }
787 | s=Tauto { P.clt2mcode Ast.Auto s }
788 | s=Tregister { P.clt2mcode Ast.Register s }
789 | s=Textern { P.clt2mcode Ast.Extern s }
791 decl: t=ctype i=ident
792 { Ast0.wrap(Ast0.Param(t, Some i)) }
793 | t=ctype { (*verify in FunDecl*) Ast0.wrap(Ast0.Param(t, None)) }
794 | t=ctype lp=TOPar s=TMul i=ident rp=TCPar
795 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
798 (Ast0.FunctionPointer
799 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
800 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
801 Ast0.wrap(Ast0.Param(fnptr, Some i)) }
803 { let (nm,pure,clt) = $1 in
804 Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) }
808 | t=ctype lp=TOPar s=TMul rp=TCPar
809 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
812 (Ast0.FunctionPointer
813 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
814 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
815 Ast0.wrap(Ast0.Param(fnptr, None)) }
818 Tconst { P.clt2mcode Ast.Const $1 }
819 | Tvolatile { P.clt2mcode Ast.Volatile $1 }
821 /*****************************************************************************/
824 includes { $1 } /* shouldn't be allowed to be a single_statement... */
829 | TIf TOPar eexpr TCPar single_statement %prec TIf
830 { P.ifthen $1 $2 $3 $4 $5 }
831 | TIf TOPar eexpr TCPar single_statement TElse single_statement
832 { P.ifthenelse $1 $2 $3 $4 $5 $6 $7 }
833 | TFor TOPar option(eexpr) TPtVirg option(eexpr) TPtVirg
834 option(eexpr) TCPar single_statement
835 { P.forloop $1 $2 $3 $4 $5 $6 $7 $8 $9 }
836 | TWhile TOPar eexpr TCPar single_statement
837 { P.whileloop $1 $2 $3 $4 $5 }
838 | TDo single_statement TWhile TOPar eexpr TCPar TPtVirg
839 { P.doloop $1 $2 $3 $4 $5 $6 $7 }
840 | iter_ident TOPar eexpr_list_option TCPar single_statement
841 { P.iterator $1 $2 $3 $4 $5 }
842 | TSwitch TOPar eexpr TCPar TOBrace list(decl_var) list(case_line) TCBrace
843 { P.switch $1 $2 $3 $4 $5 (List.concat $6) $7 $8 }
844 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
845 | TReturn TPtVirg { P.ret $1 $2 }
846 | TBreak TPtVirg { P.break $1 $2 }
847 | TContinue TPtVirg { P.cont $1 $2 }
848 | ident TDotDot { P.label $1 $2 }
849 | TGoto ident TPtVirg { P.goto $1 $2 $3 }
850 | TOBrace fun_start TCBrace
854 TEllipsis w=list(whenppdecs)
855 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." $1, List.concat w)) }
856 | TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
857 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." $1, b,
858 P.clt2mcode "...>" c, List.concat w, false)) }
859 | TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
860 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." $1, b,
861 P.clt2mcode "...+>" c, List.concat w, true)) }
863 %inline stm_dots_ell:
864 a=TEllipsis w=list(whenppdecs)
865 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." a, List.concat w)) }
867 %inline stm_dots_nest:
868 a=TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
869 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." a, b,
870 P.clt2mcode "...>" c, List.concat w, false)) }
871 | a=TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
872 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." a, b,
873 P.clt2mcode "...+>" c, List.concat w, true)) }
875 whenppdecs: w=whens(when_start,rule_elem_statement,any_strict)
878 /* a statement that fits into a single rule_elem. should nests be included?
879 what about statement metavariables? */
882 { Ast0.wrap(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),$1)) }
883 | expr TPtVirg { P.exp_stm $1 $2 }
884 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
885 | TReturn TPtVirg { P.ret $1 $2 }
886 | TBreak TPtVirg { P.break $1 $2 }
887 | TContinue TPtVirg { P.cont $1 $2 }
888 | TOPar0 midzero_list(rule_elem_statement,rule_elem_statement) TCPar0
889 { let (mids,code) = $2 in
891 (Ast0.Disj(P.clt2mcode "(" $1,
892 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
893 mids, P.clt2mcode ")" $3)) }
895 /* a statement on its own */
898 | TOPar0 midzero_list(statement,statement) TCPar0
899 /* degenerate case, elements are single statements and thus don't
901 { let (mids,code) = $2 in
903 (Ast0.Disj(P.clt2mcode "(" $1,
904 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
905 mids, P.clt2mcode ")" $3)) }
908 TDefault TDotDot fun_start
910 (Ast0.Default(P.clt2mcode "default" $1,P.clt2mcode ":" $2,$3)) }
911 | TCase eexpr TDotDot fun_start
912 { Ast0.wrap(Ast0.Case(P.clt2mcode "case" $1,$2,P.clt2mcode ":" $3,$4)) }
913 /* | lp=TOPar0 t=midzero_list(case_line,case_line) rp=TCPar0
914 { let (mids,code) = ([],[t]) in
916 (Ast0.DisjCase(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) } */
918 /* In the following, an identifier as a type is not fully supported. Indeed,
919 the language is ambiguous: what is foo * bar; */
920 /* The AST DisjDecl cannot be generated because it would be ambiguous with
921 a disjunction on a statement with a declaration in each branch */
924 { [Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv))] }
925 | s=ioption(storage) t=ctype d=comma_list(d_ident) pv=TPtVirg
928 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)))
931 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
933 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
934 /* type is a typedef name */
935 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
936 d=comma_list(d_ident) pv=TPtVirg
940 P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
941 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)))
943 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
944 e=initialize pv=TPtVirg
946 !Data.add_type_name (P.id2name i);
947 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
948 [Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
949 P.clt2mcode ";" pv))] }
950 /* function pointer type */
952 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
953 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
958 (Ast0.FunctionPointer
959 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
960 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
961 [Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv))] }
962 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
963 { [Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
964 P.clt2mcode ")" $4,P.clt2mcode ";" $5))] }
966 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
967 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
968 q=TEq e=initialize pv=TPtVirg
972 (Ast0.FunctionPointer
973 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
974 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
975 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
976 | s=Ttypedef t=typedef_ctype id=comma_list(typedef_ident) pv=TPtVirg
977 { let s = P.clt2mcode "typedef" s in
980 Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv)))
985 { Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv)) }
986 | s=ioption(storage) t=ctype d=d_ident pv=TPtVirg
988 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
990 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
992 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv)) }
993 /* type is a typedef name */
994 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
997 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
998 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)) }
999 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
1000 e=initialize pv=TPtVirg
1001 { let (id,fn) = d in
1002 !Data.add_type_name (P.id2name i);
1003 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1004 Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
1005 P.clt2mcode ";" pv)) }
1006 /* function pointer type */
1007 | s=ioption(storage)
1008 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1009 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1011 { let (id,fn) = d in
1014 (Ast0.FunctionPointer
1015 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1016 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1017 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1018 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
1019 { Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
1020 P.clt2mcode ")" $4,P.clt2mcode ";" $5)) }
1021 | s=ioption(storage)
1022 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1023 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1024 q=TEq e=initialize pv=TPtVirg
1025 { let (id,fn) = d in
1028 (Ast0.FunctionPointer
1029 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1030 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1031 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))}
1035 ident list(array_dec)
1039 (function (l,i,r) ->
1042 (Ast0.Array(rest,P.clt2mcode "[" l,i,P.clt2mcode "]" r)))
1045 array_dec: l=TOCro i=option(eexpr) r=TCCro { (l,i,r) }
1049 { Ast0.wrap(Ast0.InitExpr($1)) }
1050 | TOBrace initialize_list TCBrace
1051 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1054 (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []),
1055 P.clt2mcode "}" $2)) }
1057 {let (nm,pure,clt) = $1 in
1058 Ast0.wrap(Ast0.MetaInit(P.clt2mcode nm clt,pure)) }
1061 /*arithexpr and not eexpr because can have ambiguity with comma*/
1062 /*dots and nests probably not allowed at top level, haven't looked into why*/
1063 arith_expr(eexpr,invalid) { Ast0.wrap(Ast0.InitExpr($1)) }
1064 | TOBrace initialize_list TCBrace
1065 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1068 (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []),
1069 P.clt2mcode "}" $2)) }
1070 /* gccext:, labeled elements */
1071 | list(designator) TEq initialize2
1072 { Ast0.wrap(Ast0.InitGccExt($1,P.clt2mcode "=" $2,$3)) }
1073 | ident TDotDot initialize2
1074 { Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */
1078 { Ast0.DesignatorField (P.clt2mcode "." $1,$2) }
1080 { Ast0.DesignatorIndex (P.clt2mcode "[" $1,$2,P.clt2mcode "]" $3) }
1081 | TOCro eexpr TEllipsis eexpr TCCro
1082 { Ast0.DesignatorRange (P.clt2mcode "[" $1,$2,P.clt2mcode "..." $3,
1083 $4,P.clt2mcode "]" $5) }
1086 initialize_list_start { Ast0.wrap(Ast0.DOTS($1)) }
1088 initialize_list_start:
1089 initialize2 TComma { [$1;Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))] }
1090 | initialize2 TComma initialize_list_start
1091 { $1::Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))::$3 }
1092 | d=edots_when(TEllipsis,initialize)
1093 r=comma_initializers(edots_when(TEllipsis,initialize))
1094 { (P.mkidots "..." d)::
1095 (List.concat(List.map (function x -> x (P.mkidots "...")) r)) }
1097 comma_initializers(dotter):
1099 | d=dotter r=comma_initializers2(dotter)
1100 { (function dot_builder -> [dot_builder d])::r }
1101 | i=initialize2 c=TComma r=comma_initializers(dotter)
1102 { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
1105 comma_initializers2(dotter):
1107 | i=initialize2 c=TComma r=comma_initializers(dotter)
1108 { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
1111 /* a statement that is part of a list */
1114 { let (nm,pure,clt) = $1 in
1115 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1120 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1122 | statement { [$1] }
1123 /* this doesn't allow expressions at top level, because the parser doesn't
1124 know whether there is one. If there is one, this is not sequencible.
1125 If there is not one, then it is. It seems complicated to get around
1126 this at the parser level. We would have to have a check afterwards to
1127 allow this. One case where this would be useful is for a when. Now
1128 we allow a sequence of whens, so one can be on only statements and
1129 one can be on only expressions. */
1130 | TOPar0 t=midzero_list(fun_start,fun_start) TCPar0
1131 { let (mids,code) = t in
1134 match Ast0.unwrap x with Ast0.DOTS([]) -> true | _ -> false)
1138 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, code, mids,
1139 P.clt2mcode ")" $3))] }
1141 /* a statement that is part of a list */
1142 decl_statement_expr:
1144 { let (nm,pure,clt) = $1 in
1145 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1150 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1152 | statement { [$1] }
1153 /* this doesn't allow expressions at top level, because the parser doesn't
1154 know whether there is one. If there is one, this is not sequencible.
1155 If there is not one, then it is. It seems complicated to get around
1156 this at the parser level. We would have to have a check afterwards to
1157 allow this. One case where this would be useful is for a when. Now
1158 we allow a sequence of whens, so one can be on only statements and
1159 one can be on only expressions. */
1160 | TOPar0 t=midzero_list(fun_after_stm,fun_after_dots_or) TCPar0
1161 { let (mids,code) = t in
1162 if List.for_all (function [] -> true | _ -> false) code
1166 List.map (function x -> Ast0.wrap(Ast0.DOTS x)) code in
1167 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, dot_code, mids,
1168 P.clt2mcode ")" $3))] }
1170 /*****************************************************************************/
1172 /* The following cannot contain <... ...> at the top level. This can only
1173 be allowed as an expression when the expression is delimited on both sides
1174 by expression-specific markers. In that case, the rule eexpr is used, which
1175 allows <... ...> anywhere. Hopefully, this will not be too much of a problem
1177 expr: basic_expr(expr,invalid) { $1 }
1178 /* allows ... and nests */
1179 eexpr: basic_expr(eexpr,dot_expressions) { $1 }
1180 /* allows nests but not .... */
1181 dexpr: basic_expr(eexpr,nest_expressions) { $1 }
1184 eexpr { Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))) }
1187 TInvalid { raise (Semantic_cocci.Semantic "not matchable") }
1190 TEllipsis { Ast0.wrap(Ast0.Edots(P.clt2mcode "..." $1,None)) }
1191 | nest_expressions { $1 }
1193 /* not clear what whencode would mean, so just drop it */
1195 TOEllipsis e=expr_dots(TEllipsis) c=TCEllipsis
1196 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<..." $1,
1197 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1198 P.clt2mcode "...>" c, None, false)) }
1199 | TPOEllipsis e=expr_dots(TEllipsis) c=TPCEllipsis
1200 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<+..." $1,
1201 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1202 P.clt2mcode "...+>" c, None, true)) }
1204 //whenexp: TWhen TNotEq w=eexpr TLineEnd { w }
1206 basic_expr(recurser,primary_extra):
1207 assign_expr(recurser,primary_extra) { $1 }
1210 cond_expr(r,pe) { $1 }
1211 | unary_expr(r,pe) TAssign assign_expr_bis
1212 { let (op,clt) = $2 in
1213 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1214 Ast0.set_arg_exp $3,false)) }
1215 | unary_expr(r,pe) TEq assign_expr_bis
1218 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1221 cond_expr(eexpr,dot_expressions) { $1 }
1222 | unary_expr(eexpr,dot_expressions) TAssign assign_expr_bis
1223 { let (op,clt) = $2 in
1224 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1225 Ast0.set_arg_exp $3,false)) }
1226 | unary_expr(eexpr,dot_expressions) TEq assign_expr_bis
1229 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1232 arith_expr(r,pe) { $1 }
1233 | l=arith_expr(r,pe) w=TWhy t=option(eexpr) dd=TDotDot r=cond_expr(r,pe)
1234 { Ast0.wrap(Ast0.CondExpr (l, P.clt2mcode "?" w, t,
1235 P.clt2mcode ":" dd, r)) }
1238 cast_expr(r,pe) { $1 }
1239 | arith_expr(r,pe) TMul arith_expr(r,pe)
1240 { P.arith_op Ast.Mul $1 $2 $3 }
1241 | arith_expr(r,pe) TDmOp arith_expr(r,pe)
1242 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1243 | arith_expr(r,pe) TPlus arith_expr(r,pe)
1244 { P.arith_op Ast.Plus $1 $2 $3 }
1245 | arith_expr(r,pe) TMinus arith_expr(r,pe)
1246 { P.arith_op Ast.Minus $1 $2 $3 }
1247 | arith_expr(r,pe) TShOp arith_expr(r,pe)
1248 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1249 | arith_expr(r,pe) TLogOp arith_expr(r,pe)
1250 { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
1251 | arith_expr(r,pe) TEqEq arith_expr(r,pe)
1252 { P.logic_op Ast.Eq $1 $2 $3 }
1253 | arith_expr(r,pe) TNotEq arith_expr(r,pe)
1254 { P.logic_op Ast.NotEq $1 $2 $3 }
1255 | arith_expr(r,pe) TAnd arith_expr(r,pe)
1256 { P.arith_op Ast.And $1 $2 $3 }
1257 | arith_expr(r,pe) TOr arith_expr(r,pe)
1258 { P.arith_op Ast.Or $1 $2 $3 }
1259 | arith_expr(r,pe) TXor arith_expr(r,pe)
1260 { P.arith_op Ast.Xor $1 $2 $3 }
1261 | arith_expr(r,pe) TAndLog arith_expr(r,pe)
1262 { P.logic_op Ast.AndLog $1 $2 $3 }
1263 | arith_expr(r,pe) TOrLog arith_expr(r,pe)
1264 { P.logic_op Ast.OrLog $1 $2 $3 }
1267 unary_expr(r,pe) { $1 }
1268 | lp=TOPar t=ctype rp=TCPar e=cast_expr(r,pe)
1269 { Ast0.wrap(Ast0.Cast (P.clt2mcode "(" lp, t,
1270 P.clt2mcode ")" rp, e)) }
1273 postfix_expr(r,pe) { $1 }
1274 | TInc unary_expr(r,pe)
1275 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
1276 | TDec unary_expr(r,pe)
1277 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
1278 | unary_op cast_expr(r,pe)
1279 { let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
1280 | TBang unary_expr(r,pe)
1281 { let mcode = P.clt2mcode Ast.Not $1 in
1282 Ast0.wrap(Ast0.Unary($2, mcode)) }
1283 | TSizeof unary_expr(r,pe)
1284 { Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
1285 | s=TSizeof lp=TOPar t=ctype rp=TCPar
1286 { Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
1287 P.clt2mcode "(" lp,t,
1288 P.clt2mcode ")" rp)) }
1290 unary_op: TAnd { P.clt2mcode Ast.GetRef $1 }
1291 | TMul { P.clt2mcode Ast.DeRef $1 }
1292 | TPlus { P.clt2mcode Ast.UnPlus $1 }
1293 | TMinus { P.clt2mcode Ast.UnMinus $1 }
1294 | TTilde { P.clt2mcode Ast.Tilde $1 }
1297 primary_expr(r,pe) { $1 }
1298 | postfix_expr(r,pe) TOCro eexpr TCCro
1299 { Ast0.wrap(Ast0.ArrayAccess ($1,P.clt2mcode "[" $2,$3,
1300 P.clt2mcode "]" $4)) }
1301 | postfix_expr(r,pe) TDot ident
1302 { Ast0.wrap(Ast0.RecordAccess($1, P.clt2mcode "." $2, $3)) }
1303 | postfix_expr(r,pe) TPtrOp ident
1304 { Ast0.wrap(Ast0.RecordPtAccess($1, P.clt2mcode "->" $2,
1306 | postfix_expr(r,pe) TInc
1307 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Inc $2)) }
1308 | postfix_expr(r,pe) TDec
1309 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Dec $2)) }
1310 | postfix_expr(r,pe) TOPar eexpr_list_option TCPar
1311 { Ast0.wrap(Ast0.FunCall($1,P.clt2mcode "(" $2,
1313 P.clt2mcode ")" $4)) }
1315 primary_expr(recurser,primary_extra):
1316 func_ident { Ast0.wrap(Ast0.Ident($1)) }
1318 { let (x,clt) = $1 in
1319 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1321 { let (x,clt) = $1 in
1322 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Float x) clt)) }
1324 { let (x,clt) = $1 in
1325 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.String x) clt)) }
1327 { let (x,clt) = $1 in
1328 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Char x) clt)) }
1330 { let (nm,constraints,pure,ty,clt) = $1 in
1332 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
1334 { let (nm,constraints,pure,clt) = $1 in
1335 Ast0.wrap(Ast0.MetaErr(P.clt2mcode nm clt,constraints,pure)) }
1337 { let (nm,constraints,pure,ty,clt) = $1 in
1339 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
1341 { let (nm,constraints,pure,ty,clt) = $1 in
1343 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
1345 { let (nm,constraints,pure,ty,clt) = $1 in
1347 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.LocalID,pure)) }
1349 { Ast0.wrap(Ast0.Paren(P.clt2mcode "(" $1,$2,
1350 P.clt2mcode ")" $3)) }
1351 | TOPar0 midzero_list(recurser,eexpr) TCPar0
1352 { let (mids,code) = $2 in
1353 Ast0.wrap(Ast0.DisjExpr(P.clt2mcode "(" $1,
1355 P.clt2mcode ")" $3)) }
1356 | primary_extra { $1 }
1359 r=no_dot_start_end(dexpr,edots_when(dotter,eexpr)) { r }
1362 no_dot_start_end(grammar,dotter):
1363 g=grammar dg=list(pair(dotter,grammar))
1364 { function dot_builder ->
1365 g :: (List.concat(List.map (function (d,g) -> [dot_builder d;g]) dg)) }
1367 /*****************************************************************************/
1373 TRuleName TDot pure_ident { (Some $1,P.id2name $3) }
1375 pure_ident_or_meta_ident:
1376 pure_ident { (None,P.id2name $1) }
1378 | TIdentifier { (None, "identifier") }
1379 | TExpression { (None, "expression") }
1380 | TStatement { (None, "statement") }
1381 | TFunction { (None, "function") }
1382 | TLocal { (None, "local") }
1383 | TType { (None, "type") }
1384 | TParameter { (None, "parameter") }
1385 | TIdExpression { (None, "idexpression") }
1386 | TInitialiser { (None, "initialiser") }
1387 | Tlist { (None, "list") }
1388 | TFresh { (None, "fresh") }
1389 | TConstant { (None, "constant") }
1390 | TError { (None, "error") }
1391 | TWords { (None, "words") }
1392 | TPure { (None, "pure") }
1393 | TContext { (None, "context") }
1394 | TGenerated { (None, "generated") }
1395 | TTypedef { (None, "typedef") }
1396 | TDeclarer { (None, "declarer") }
1397 | TIterator { (None, "iterator") }
1398 | TName { (None, "name") }
1399 | TPosition { (None, "position") }
1401 pure_ident_or_meta_ident_with_seed:
1402 pure_ident_or_meta_ident { ($1,Ast.NoVal) }
1403 | pure_ident_or_meta_ident TEq
1404 separated_nonempty_list(TCppConcatOp,seed_elem)
1406 [Ast.SeedString s] -> ($1,Ast.StringSeed s)
1407 | _ -> ($1,Ast.ListSeed $3) }
1410 TString { let (x,_) = $1 in Ast.SeedString x }
1411 | TMetaId { let (x,_,_,_) = $1 in Ast.SeedId x }
1412 | TRuleName TDot pure_ident
1413 { let nm = ($1,P.id2name $3) in
1414 P.check_meta(Ast.MetaIdDecl(Ast.NONE,nm));
1417 pure_ident_or_meta_ident_with_x_eq(x_eq):
1418 i=pure_ident_or_meta_ident l=loption(x_eq)
1423 pure_ident_or_meta_ident_with_econstraint(x_eq):
1424 i=pure_ident_or_meta_ident optc=option(x_eq)
1427 None -> (i, Ast0.NoConstraint)
1431 pure_ident_or_meta_ident_with_idconstraint(constraint_type):
1432 i=pure_ident_or_meta_ident c=option(constraint_type)
1435 None -> (i, Ast.IdNoConstraint)
1436 | Some constraint_ -> (i,constraint_)
1446 then failwith "constraints not allowed in iso file");
1447 (if !Data.in_generating
1448 then failwith "constraints not allowed in a generated rule file");
1449 let (s,_) = re in Ast.IdRegExp (s,Str.regexp s)
1451 | TTildeExclEq re=TString
1453 then failwith "constraints not allowed in iso file");
1454 (if !Data.in_generating
1455 then failwith "constraints not allowed in a generated rule file");
1456 let (s,_) = re in Ast.IdNotRegExp (s,Str.regexp s)
1462 then failwith "constraints not allowed in iso file");
1463 (if !Data.in_generating
1464 (* pb: constraints not stored with metavars; too lazy to search for
1465 them in the pattern *)
1466 then failwith "constraints not allowed in a generated rule file");
1467 Ast.IdNegIdSet([fst i]) }
1468 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1470 then failwith "constraints not allowed in iso file");
1471 (if !Data.in_generating
1472 then failwith "constraints not allowed in a generated rule file");
1473 Ast.IdNegIdSet(List.map fst l)
1477 re=regexp_eqid {Ast0.NotIdCstrt (re)}
1478 | ne=not_eqe {Ast0.NotExpCstrt (ne)}
1483 then failwith "constraints not allowed in iso file");
1484 (if !Data.in_generating
1485 then failwith "constraints not allowed in a generated rule file");
1486 [Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))]
1488 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1490 then failwith "constraints not allowed in iso file");
1491 (if !Data.in_generating
1492 then failwith "constraints not allowed in a generated rule file");
1495 Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))))
1500 TNotEq i=ident_or_const
1502 then failwith "constraints not allowed in iso file");
1503 (if !Data.in_generating
1504 then failwith "constraints not allowed in a generated rule file");
1506 | TNotEq TOBrace l=comma_list(ident_or_const) 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");
1514 i=pure_ident { Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))) }
1516 { let (x,clt) = $1 in
1517 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1522 then failwith "constraints not allowed in iso file");
1523 (if !Data.in_generating
1524 then failwith "constraints not allowed in a generated rule file");
1526 (None,_) -> failwith "constraint must be an inherited variable"
1527 | (Some rule,name) ->
1528 let i = (rule,name) in
1529 P.check_meta(Ast.MetaPosDecl(Ast.NONE,i));
1531 | TNotEq TOBrace l=comma_list(meta_ident) TCBrace
1533 then failwith "constraints not allowed in iso file");
1534 (if !Data.in_generating
1535 then failwith "constraints not allowed in a generated rule file");
1539 failwith "constraint must be an inherited variable"
1540 | (Some rule,name) ->
1541 let i = (rule,name) in
1542 P.check_meta(Ast.MetaPosDecl(Ast.NONE,i));
1546 func_ident: pure_ident
1547 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1549 { let (nm,constraints,pure,clt) = $1 in
1550 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1552 { let (nm,constraints,pure,clt) = $1 in
1553 Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
1555 { let (nm,constraints,pure,clt) = $1 in
1557 (Ast0.MetaLocalFunc(P.clt2mcode nm clt,constraints,pure)) }
1560 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1562 { let (nm,constraints,pure,clt) = $1 in
1563 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1567 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1569 { let (nm,constraints,pure,clt) = $1 in
1570 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1574 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1576 { let (nm,constraints,pure,clt) = $1 in
1577 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1581 { Ast0.wrap(Ast0.TypeName(P.id2mcode $1)) }
1583 { let (nm,pure,clt) = $1 in
1584 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
1586 /*****************************************************************************/
1589 /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
1590 | decl_list_start(decl)
1592 match Ast0.unwrap x with Ast0.Pcircles(_) -> true | _ -> false in
1593 if List.exists circle $1
1594 then Ast0.wrap(Ast0.CIRCLES($1))
1595 else Ast0.wrap(Ast0.DOTS($1)) }
1597 decl_list_start(decl):
1598 one_dec(decl) { [$1] }
1599 | one_dec(decl) TComma decl_list_start(decl)
1600 { $1::Ast0.wrap(Ast0.PComma(P.clt2mcode "," $2))::$3 }
1601 | TEllipsis list(comma_decls(TEllipsis,decl))
1602 { Ast0.wrap(Ast0.Pdots(P.clt2mcode "..." $1))::
1603 (List.concat(List.map (function x -> x (P.mkpdots "...")) $2)) }
1608 { let (nm,lenname,pure,clt) = $1 in
1609 let nm = P.clt2mcode nm clt in
1612 Some nm -> Some(P.clt2mcode nm clt)
1614 Ast0.wrap(Ast0.MetaParamList(nm,lenname,pure)) }
1616 comma_decls(dotter,decl):
1618 { function dot_builder ->
1619 [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1));
1621 | TComma one_dec(decl)
1622 { function dot_builder ->
1623 [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1)); $2] }
1625 /* ---------------------------------------------------------------------- */
1627 /* error words make it complicated to be able to use error as a metavariable
1628 name or a type in a metavariable list; for that we would like to allow TError
1629 as an ident, but that makes conflicts with this rule. To add back error words,
1630 need to find some appropriate delimiter for it, but it has not been used much
1633 TError TWords TEq TOCro cl=comma_list(dexpr) TCCro
1634 { [Ast0.wrap(Ast0.ERRORWORDS(cl))] }
1637 /* ---------------------------------------------------------------------- */
1638 /* sequences of statements and expressions */
1640 /* There are number of cases that must be considered:
1643 Dots and nests allowed at the beginning or end
1644 Expressions allowed at the beginning or end
1645 One function allowed, by itself
1647 Dots and nests allowed at the beginning or end
1648 Expressions not allowed at the beginning or end
1649 Functions not allowed
1650 3. The body of a nest:
1651 Dots and nests not allowed at the beginning or end
1652 Expressions allowed at the beginning or end
1653 Functions not allowed
1655 Dots and nests not allowed at the beginning but allowed at the end
1656 Expressions allowed at the beginning or end
1657 Functions not allowed
1659 These are implemented by the rules minus_toplevel_sequence,
1660 plus_toplevel_sequence, function_body_sequence, nest_body_sequence, and
1663 /* ------------------------------------------------------------------------ */
1664 /* Minus top level */
1666 /* doesn't allow only ... */
1668 fundecl { [Ast0.wrap(Ast0.DECL($1))] }
1669 | ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1670 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1671 | toplevel_seq_startne(toplevel_after_dots_init)
1672 { List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1 }
1674 toplevel_seq_startne(after_dots_init):
1675 a=stm_dots_ell b=after_dots_init { a::b }
1676 | a=stm_dots_nest b=after_dots_init { a::b }
1677 | a=stm_dots_nest { [a] }
1678 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1679 | decl_statement_expr toplevel_after_stm { $1@$2 }
1681 toplevel_seq_start(after_dots_init):
1682 stm_dots after_dots_init { $1::$2 }
1683 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1684 | decl_statement_expr toplevel_after_stm { $1@$2 }
1686 toplevel_after_dots_init:
1687 TNothing toplevel_after_exp {$2}
1688 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1689 | decl_statement_expr toplevel_after_stm {$1@$2}
1693 | stm_dots toplevel_after_dots {$1::$2}
1695 toplevel_after_dots:
1697 | TNothing toplevel_after_exp {$2}
1698 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1699 | decl_statement_expr toplevel_after_stm {$1@$2}
1703 | stm_dots toplevel_after_dots {$1::$2}
1704 | decl_statement toplevel_after_stm {$1@$2}
1707 TOInit initialize_list TCBrace
1708 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1710 /* ------------------------------------------------------------------------ */
1711 /* Plus top level */
1713 /* does allow only ... also allows multiple top-level functions */
1715 ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1716 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1717 | stm_dots plus_after_dots
1718 { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1719 | expr plus_after_exp
1720 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1721 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1722 | decl_statement_expr plus_after_stm
1723 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1727 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1731 | TNothing plus_after_exp {$2}
1732 | expr plus_after_exp
1733 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1734 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1735 | decl_statement_expr plus_after_stm
1736 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1740 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1741 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1742 | decl_statement plus_after_stm
1743 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1745 /* ------------------------------------------------------------------------ */
1749 fun_after_stm { Ast0.wrap(Ast0.DOTS($1)) }
1753 | stm_dots fun_after_dots {$1::$2}
1754 | decl_statement fun_after_stm {$1@$2}
1758 | TNothing fun_after_exp {$2}
1759 | expr fun_after_exp {Ast0.wrap(Ast0.Exp($1))::$2}
1760 | decl_statement_expr fun_after_stm {$1@$2}
1763 stm_dots fun_after_dots {$1::$2}
1765 /* hack to allow mixing statements and expressions in an or */
1768 | TNothing fun_after_exp_or {$2}
1769 | expr fun_after_exp_or {Ast0.wrap(Ast0.Exp($1))::$2}
1770 | decl_statement_expr fun_after_stm {$1@$2}
1774 | stm_dots fun_after_dots {$1::$2}
1776 /* ------------------------------------------------------------------------ */
1780 nest_after_dots { Ast0.wrap(Ast0.DOTS($1)) }
1783 decl_statement_expr nest_after_stm {$1@$2}
1784 | TNothing nest_after_exp {$2}
1785 | expr nest_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1789 | stm_dots nest_after_dots {$1::$2}
1790 | decl_statement nest_after_stm {$1@$2}
1794 | stm_dots nest_after_dots {$1::$2}
1796 /* ------------------------------------------------------------------------ */
1800 expr toplevel_after_exp
1801 { Ast0.wrap(Ast0.DOTS((Ast0.wrap(Ast0.Exp($1)))::$2)) }
1802 | decl_statement toplevel_after_stm
1803 { Ast0.wrap(Ast0.DOTS($1@$2)) }
1805 /* ---------------------------------------------------------------------- */
1810 match Ast0.unwrap x with Ast0.Ecircles(_) -> true | _ -> false in
1812 match Ast0.unwrap x with Ast0.Estars(_) -> true | _ -> false in
1813 if List.exists circle $1
1814 then Ast0.wrap(Ast0.CIRCLES($1))
1816 if List.exists star $1
1817 then Ast0.wrap(Ast0.STARS($1))
1818 else Ast0.wrap(Ast0.DOTS($1)) }
1820 /* arg expr. may contain a type or a explist metavariable */
1823 { Ast0.set_arg_exp $1 }
1825 { let (nm,lenname,pure,clt) = $1 in
1826 let nm = P.clt2mcode nm clt in
1829 Some nm -> Some(P.clt2mcode nm clt)
1831 Ast0.wrap(Ast0.MetaExprList(nm,lenname,pure)) }
1833 { Ast0.set_arg_exp(Ast0.wrap(Ast0.TypeExp($1))) }
1837 | aexpr TComma eexpr_list_start
1838 { $1::Ast0.wrap(Ast0.EComma(P.clt2mcode "," $2))::$3 }
1842 { function dot_builder ->
1843 [Ast0.wrap(Ast0.EComma(P.clt2mcode "," c)); dot_builder d] }
1845 { function dot_builder ->
1846 [Ast0.wrap(Ast0.EComma(P.clt2mcode "," $1)); $2] }
1848 eexpr_list_option: eexpr_list { $1 }
1849 | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
1851 /****************************************************************************/
1853 // non-empty lists - drop separator
1855 separated_nonempty_list(TComma,elem) { $1 }
1857 midzero_list(elem,aft):
1858 a=elem b=list(mzl(aft))
1859 { let (mids,code) = List.split b in (mids,(a::code)) }
1862 a=TMid0 b=elem { (P.clt2mcode "|" a, b) }
1864 edots_when(dotter,when_grammar):
1865 d=dotter { (d,None) }
1866 | d=dotter TWhen TNotEq w=when_grammar TLineEnd { (d,Some w) }
1868 whens(when_grammar,simple_when_grammar,any_strict):
1869 TWhen TNotEq w=when_grammar TLineEnd { [Ast0.WhenNot w] }
1870 | TWhen TEq w=simple_when_grammar TLineEnd { [Ast0.WhenAlways w] }
1871 | TWhen comma_list(any_strict) TLineEnd
1872 { List.map (function x -> Ast0.WhenModifier(x)) $2 }
1873 | TWhenTrue TNotEq e = eexpr TLineEnd { [Ast0.WhenNotTrue e] }
1874 | TWhenFalse TNotEq e = eexpr TLineEnd { [Ast0.WhenNotFalse e] }
1877 TAny { Ast.WhenAny }
1878 | TStrict { Ast.WhenStrict }
1879 | TForall { Ast.WhenForall }
1880 | TExists { Ast.WhenExists }
1882 /*****************************************************************************
1885 *****************************************************************************/
1888 TIsoExpression e1=dexpr el=list(iso(dexpr)) EOF
1889 { P.iso_adjust (function x -> Ast0.ExprTag x) e1 el }
1890 | TIsoArgExpression e1=dexpr el=list(iso(dexpr)) EOF
1891 { P.iso_adjust (function x -> Ast0.ArgExprTag x) e1 el }
1892 | TIsoTestExpression e1=dexpr el=list(iso(dexpr)) EOF
1893 { P.iso_adjust (function x -> Ast0.TestExprTag x) e1 el }
1894 | TIsoStatement s1=single_statement sl=list(iso(single_statement)) EOF
1895 { P.iso_adjust (function x -> Ast0.StmtTag x) s1 sl }
1896 | TIsoType t1=ctype tl=list(iso(ctype)) EOF
1897 { P.iso_adjust (function x -> Ast0.TypeCTag x) t1 tl }
1898 | TIsoTopLevel e1=nest_start el=list(iso(nest_start)) EOF
1899 { P.iso_adjust (function x -> Ast0.DotsStmtTag x) e1 el }
1900 | TIsoDeclaration d1=decl_var dl=list(iso(decl_var)) EOF
1901 { let check_one = function
1905 (Semantic_cocci.Semantic
1906 "only one variable per declaration in an isomorphism rule") in
1907 let d1 = check_one d1 in
1911 Common.Left x -> Common.Left(check_one x)
1912 | Common.Right x -> Common.Right(check_one x))
1914 P.iso_adjust (function x -> Ast0.DeclTag x) d1 dl }
1917 TIso t=term { Common.Left t }
1918 | TRightIso t=term { Common.Right t }
1920 /*****************************************************************************
1923 *****************************************************************************/
1925 never_used: TPragma { () }
1926 | TPArob TMetaPos { () }
1927 | TScriptData { () }
1929 script_meta_main: py=pure_ident TShOp TRuleName TDot cocci=pure_ident TMPtVirg
1930 { (P.id2name py, ($3, P.id2name cocci)) }