2 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
3 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
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 TReverse TNothing
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_info> 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> 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
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
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 <(string,string) Common.either 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 }
213 | TExtends parent=TRuleName
214 { !Data.install_bindings (parent) }
217 /* empty */ { Ast.NoDep }
218 | TDepends TOn parents=dep { parents }
222 | dep TAndLog dep { Ast.AndDep($1, $3) }
223 | dep TOrLog dep { Ast.OrDep ($1, $3) }
226 TRuleName { Ast.Dep $1 }
227 | TBang TRuleName { Ast.AntiDep $2 }
228 | TEver TRuleName { Ast.EverDep $2 }
229 | TNever TRuleName { Ast.NeverDep $2 }
230 | TOPar dep TCPar { $2 }
233 TUsing separated_nonempty_list(TComma,TString) { List.map P.id2name $2 }
236 TDisable separated_nonempty_list(TComma,pure_ident) { List.map P.id2name $2 }
239 TExists { Ast.Exists }
240 | TForall { Ast.Forall }
241 | TReverse TForall { Ast.ReverseForall }
242 | { Ast.Undetermined }
244 is_expression: // for more flexible parsing of top level expressions
246 | TExpression { true }
249 list(incl) TArob { $1 }
250 | list(incl) TArobArob { $1 }
253 TUsing TString { Common.Left(P.id2name $2) }
254 | TUsing TPathIsoFile { Common.Right $2 }
258 kindfn=metakind ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
259 { P.create_metadec ar ispure kindfn ids }
260 | ar=arity ispure=pure
261 kindfn=metakind_atomic
262 ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_eq)) TMPtVirg
263 { P.create_metadec_ne ar ispure kindfn ids }
264 | ar=arity ispure=pure
265 kindfn=metakind_atomic_expi
266 ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_eqe)) TMPtVirg
267 { P.create_metadec_ne ar ispure kindfn ids }
268 | ar=arity ispure=pure
269 kindfn=metakind_atomic_expe
270 ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_ceq)) TMPtVirg
271 { P.create_metadec_ne ar ispure kindfn ids }
272 | ar=arity TPosition a=option(TPosAny)
273 ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_pos)) TMPtVirg
274 (* pb: position variables can't be inherited from normal rules, and then
275 there is no way to inherit from a generated rule, so there is no point
276 to have a position variable *)
277 { (if !Data.in_generating
278 then failwith "position variables not allowed in a generated rule file");
279 let kindfn arity name pure check_meta constraints =
280 let tok = check_meta(Ast.MetaPosDecl(arity,name)) in
281 let any = match a with None -> Ast.PER | Some _ -> Ast.ALL in
282 !Data.add_pos_meta name constraints any; tok in
283 P.create_metadec_ne ar false kindfn ids }
284 | ar=arity ispure=pure
285 TParameter Tlist TOCro id=pure_ident_or_meta_ident TCCro
286 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
287 { P.create_len_metadec ar ispure
288 (fun lenname arity name pure check_meta ->
290 check_meta(Ast.MetaParamListDecl(arity,name,Some lenname)) in
291 !Data.add_paramlist_meta name (Some lenname) pure; tok)
293 | ar=arity ispure=pure
294 TExpression Tlist TOCro id=pure_ident_or_meta_ident TCCro
295 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
296 { P.create_len_metadec ar ispure
297 (fun lenname arity name pure check_meta ->
299 check_meta(Ast.MetaExpListDecl(arity,name,Some lenname)) in
300 !Data.add_explist_meta name (Some lenname) pure; tok)
305 { (fun arity name pure check_meta ->
306 let tok = check_meta(Ast.MetaFreshIdDecl(arity,name)) in
307 !Data.add_id_meta name [] pure; tok) }
309 { (fun arity name pure check_meta ->
310 let tok = check_meta(Ast.MetaParamDecl(arity,name)) in
311 !Data.add_param_meta name pure; tok) }
313 { (fun arity name pure check_meta ->
314 let tok = check_meta(Ast.MetaParamListDecl(arity,name,None)) in
315 !Data.add_paramlist_meta name None pure; tok) }
317 { (fun arity name pure check_meta ->
318 let tok = check_meta(Ast.MetaExpListDecl(arity,name,None)) in
319 !Data.add_explist_meta name None pure; tok) }
321 { (fun arity name pure check_meta ->
322 let tok = check_meta(Ast.MetaTypeDecl(arity,name)) in
323 !Data.add_type_meta name pure; tok) }
325 { (fun arity name pure check_meta ->
326 let tok = check_meta(Ast.MetaInitDecl(arity,name)) in
327 !Data.add_init_meta name pure; tok) }
329 { (fun arity name pure check_meta ->
330 let tok = check_meta(Ast.MetaStmDecl(arity,name)) in
331 !Data.add_stm_meta name pure; tok) }
333 { (fun arity name pure check_meta ->
334 let tok = check_meta(Ast.MetaStmListDecl(arity,name)) in
335 !Data.add_stmlist_meta name pure; tok) }
337 { (fun arity (_,name) pure check_meta ->
338 if arity = Ast.NONE && pure = Ast0.Impure
339 then (!Data.add_type_name name; [])
340 else raise (Semantic_cocci.Semantic "bad typedef")) }
342 { (fun arity (_,name) pure check_meta ->
343 if arity = Ast.NONE && pure = Ast0.Impure
344 then (!Data.add_declarer_name name; [])
345 else raise (Semantic_cocci.Semantic "bad declarer")) }
347 { (fun arity (_,name) pure check_meta ->
348 if arity = Ast.NONE && pure = Ast0.Impure
349 then (!Data.add_iterator_name name; [])
350 else raise (Semantic_cocci.Semantic "bad iterator")) }
353 %inline metakind_atomic:
355 { (fun arity name pure check_meta constraints ->
356 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
357 !Data.add_id_meta name constraints pure; tok) }
359 { (fun arity name pure check_meta constraints ->
360 let tok = check_meta(Ast.MetaFuncDecl(arity,name)) in
361 !Data.add_func_meta name constraints pure; tok) }
363 { (fun arity name pure check_meta constraints ->
364 let tok = check_meta(Ast.MetaLocalFuncDecl(arity,name)) in
365 !Data.add_local_func_meta name constraints pure;
368 { (fun arity name pure check_meta constraints ->
369 let tok = check_meta(Ast.MetaDeclarerDecl(arity,name)) in
370 !Data.add_declarer_meta name constraints pure; tok) }
372 { (fun arity name pure check_meta constraints ->
373 let tok = check_meta(Ast.MetaIteratorDecl(arity,name)) in
374 !Data.add_iterator_meta name constraints pure; tok) }
376 %inline metakind_atomic_expi:
378 { (fun arity name pure check_meta constraints ->
379 let tok = check_meta(Ast.MetaErrDecl(arity,name)) in
380 !Data.add_err_meta name constraints pure; tok) }
381 | l=option(TLocal) TIdExpression ty=ioption(meta_exp_type)
382 { (fun arity name pure check_meta constraints ->
385 !Data.add_idexp_meta ty name constraints pure;
386 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
388 !Data.add_local_idexp_meta ty name constraints pure;
389 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
390 | l=option(TLocal) TIdExpression m=nonempty_list(TMul)
391 { (fun arity name pure check_meta constraints ->
392 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
395 !Data.add_idexp_meta ty name constraints pure;
396 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
398 !Data.add_local_idexp_meta ty name constraints pure;
399 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
400 | TExpression m=nonempty_list(TMul)
401 { (fun arity name pure check_meta constraints ->
402 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
403 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
404 !Data.add_exp_meta ty name constraints pure; tok) }
405 | vl=meta_exp_type TOCro TCCro
406 { (fun arity name pure check_meta constraints ->
407 let ty = Some (List.map (function x -> Type_cocci.Array x) vl) in
408 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
409 !Data.add_exp_meta ty name constraints pure; tok) }
410 | TConstant ty=ioption(meta_exp_type)
411 { (fun arity name pure check_meta constraints ->
412 let tok = check_meta(Ast.MetaConstDecl(arity,name,ty)) in
413 !Data.add_const_meta ty name constraints pure; tok) }
415 %inline metakind_atomic_expe:
417 { (fun arity name pure check_meta constraints ->
418 let tok = check_meta(Ast.MetaExpDecl(arity,name,None)) in
419 !Data.add_exp_meta None name constraints pure; tok) }
420 | vl=meta_exp_type // no error if use $1 but doesn't type check
421 { (fun arity name pure check_meta constraints ->
425 match Ast0.unwrap c with
430 Type_cocci.BaseType(Type_cocci.IntType) -> true
431 | Type_cocci.BaseType(Type_cocci.ShortType) -> true
432 | Type_cocci.BaseType(Type_cocci.LongType) -> true
435 then failwith "metavariable with int constraint must be an int"
438 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
439 !Data.add_exp_meta ty name constraints pure; tok) }
444 { [Ast0_cocci.ast0_type_to_type t] }
445 | TOBrace t=comma_list(ctype) TCBrace m=list(TMul)
447 (function x -> P.ty_pointerify (Ast0_cocci.ast0_type_to_type x) m)
450 arity: TBang0 { Ast.UNIQUE }
452 | TPlus0 { Ast.MULTI }
453 | /* empty */ { Ast.NONE }
456 q=ctype_qualif_opt ty=Tchar
457 { q (Ast0.wrap(Ast0.BaseType(Ast.CharType,[P.clt2mcode "char" ty]))) }
458 | q=ctype_qualif_opt ty=Tshort
459 { q (Ast0.wrap(Ast0.BaseType(Ast.ShortType,[P.clt2mcode "short" ty])))}
460 | q=ctype_qualif_opt ty=Tint
461 { q (Ast0.wrap(Ast0.BaseType(Ast.IntType,[P.clt2mcode "int" ty]))) }
463 { Ast0.wrap(Ast0.BaseType(Ast.DoubleType,[P.clt2mcode "double" t])) }
465 { Ast0.wrap(Ast0.BaseType(Ast.FloatType,[P.clt2mcode "float" t])) }
466 | q=ctype_qualif_opt ty=Tlong
467 { q (Ast0.wrap(Ast0.BaseType(Ast.LongType,[P.clt2mcode "long" ty]))) }
468 | q=ctype_qualif_opt ty=Tlong ty1=Tlong
472 [P.clt2mcode "long" ty;P.clt2mcode "long" ty1]))) }
474 { Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, i)) }
475 | s=struct_or_union i=ident
476 { Ast0.wrap(Ast0.StructUnionName(s, Some i)) }
477 | s=struct_or_union i=ioption(ident)
478 l=TOBrace d=struct_decl_list r=TCBrace
479 { (if i = None && !Data.in_iso
480 then failwith "structures must be named in the iso file");
481 Ast0.wrap(Ast0.StructUnionDef(Ast0.wrap(Ast0.StructUnionName(s, i)),
483 d, P.clt2mcode "}" r)) }
484 | s=TMetaType l=TOBrace d=struct_decl_list r=TCBrace
485 { let (nm,pure,clt) = s in
487 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) in
489 (Ast0.StructUnionDef(ty,P.clt2mcode "{" l,d,P.clt2mcode "}" r)) }
490 | r=TRuleName TDot p=TIdent
491 { let nm = (r,P.id2name p) in
492 (* this is only possible when we are in a metavar decl. Otherwise,
493 it will be represented already as a MetaType *)
494 let _ = P.check_meta(Ast.MetaTypeDecl(Ast.NONE,nm)) in
495 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm (P.id2clt p),
496 Ast0.Impure (*will be ignored*))) }
498 { Ast0.wrap(Ast0.TypeName(P.id2mcode p)) }
499 | q=ctype_qualif_opt p=TMetaType
500 { let (nm,pure,clt) = p in
501 q (Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure))) }
504 q=ctype_qualif { q None }
505 | generic_ctype_full { $1 }
508 s=Tstruct { P.clt2mcode Ast.Struct s }
509 | u=Tunion { P.clt2mcode Ast.Union u }
513 | t=ctype d=d_ident pv=TPtVirg
515 [Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] }
516 | t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
517 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar pv=TPtVirg
521 (Ast0.FunctionPointer
522 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
523 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
524 [Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] }
525 | cv=ioption(const_vol) i=pure_ident d=d_ident pv=TPtVirg
527 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
528 [Ast0.wrap(Ast0.UnInit(None,fn idtype,id,P.clt2mcode ";" pv))] }
531 struct_decl_list_start { Ast0.wrap(Ast0.DOTS($1)) }
533 struct_decl_list_start:
535 | struct_decl struct_decl_list_start { $1@$2 }
536 | d=edots_when(TEllipsis,struct_decl) r=continue_struct_decl_list
537 { (P.mkddots "..." d)::r }
539 continue_struct_decl_list:
541 | struct_decl struct_decl_list_start { $1@$2 }
545 cv=ioption(const_vol) ty=generic_ctype m=list(TMul)
546 { P.pointerify (P.make_cv cv ty) m }
547 | cv=ioption(const_vol) t=Tvoid m=nonempty_list(TMul)
549 Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" t])) in
550 P.pointerify (P.make_cv cv ty) m }
551 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
553 { let (mids,code) = t in
555 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
558 cv=ioption(const_vol) ty=generic_ctype_full m=list(TMul)
559 { P.pointerify (P.make_cv cv ty) m }
560 | cv=ioption(const_vol) t=Tvoid m=nonempty_list(TMul)
562 Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" t])) in
563 P.pointerify (P.make_cv cv ty) m }
564 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
566 { let (mids,code) = t in
568 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
571 fn_ctype: // allows metavariables
572 ty=generic_ctype m=list(TMul) { P.pointerify ty m }
573 | t=Tvoid m=list(TMul)
575 (Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" t])))
578 %inline ctype_qualif:
580 { function x -> Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,x)) }
582 { function x -> Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,x)) }
584 %inline ctype_qualif_opt:
585 s=ctype_qualif { function x -> s (Some x) }
586 | /* empty */ { function x -> x }
588 /*****************************************************************************/
590 /* have to inline everything to avoid conflicts? switch to proper
591 declarations, statements, and expressions for the subterms */
595 b=loption(minus_start)
596 ew=loption(error_words)
598 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
599 | code -> Top_level.top_level code }
603 b=loption(plus_start)
604 ew=loption(error_words)
605 { Top_level.top_level (f@b@ew) }
610 ew=loption(error_words)
611 { match f@[b]@ew with
612 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
613 | code -> Top_level.top_level code }
618 ew=loption(error_words)
619 { Top_level.top_level (f@[b]@ew) }
624 (Ast0.FILEINFO(P.id2mcode $1,
630 (Ast0.Include(P.clt2mcode "#include" (P.drop_aft (P.id2clt $1)),
631 let (arity,ln,lln,offset,col,strbef,straft,pos) =
634 (arity,ln,lln,offset,0,strbef,straft,pos) in
636 (Ast.Local (Parse_aux.str2inc (P.id2name $1)))
640 (Ast0.Include(P.clt2mcode "#include" (P.drop_aft (P.id2clt $1)),
641 let (arity,ln,lln,offset,col,strbef,straft,pos) =
644 (arity,ln,lln,offset,0,strbef,straft,pos) in
646 (Ast.NonLocal (Parse_aux.str2inc (P.id2name $1)))
648 | d=defineop t=ctype TLineEnd
649 { let ty = Ast0.wrap(Ast0.TopExp(Ast0.wrap(Ast0.TypeExp(t)))) in
650 d (Ast0.wrap(Ast0.DOTS([ty]))) }
651 | defineop b=toplevel_seq_start(toplevel_after_dots) TLineEnd
655 (match Ast0.unwrap e with
657 [Ast0.rewrap e (Ast0.TopExp(Ast0.set_arg_exp (e1)))]
660 $1 (Ast0.wrap(Ast0.DOTS(body))) }
664 { let (clt,ident) = $1 in
668 (P.clt2mcode "#define" clt,
670 TMetaId((nm,constraints,pure,clt)) ->
671 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
673 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
676 (Semantic_cocci.Semantic
677 "unexpected name for a #define")),
678 Ast0.wrap Ast0.NoParams,
680 | TDefineParam define_param_list_option TCPar
681 { let (clt,ident,parenoff) = $1 in
682 let (arity,line,lline,offset,col,strbef,straft,pos) = clt in
685 (arity,line,lline,parenoff,0,[],[],Ast0.NoMetaPos) in
689 (P.clt2mcode "#define" clt,
691 TMetaId((nm,constraints,pure,clt)) ->
692 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
694 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
697 (Semantic_cocci.Semantic
698 "unexpected name for a #define")),
699 Ast0.wrap (Ast0.DParams (lp,$2,P.clt2mcode ")" $3)),body)) }
701 /* ---------------------------------------------------------------------- */
703 define_param_list: define_param_list_start
705 match Ast0.unwrap x with Ast0.DPcircles(_) -> true | _ -> false in
706 if List.exists circle $1
707 then Ast0.wrap(Ast0.CIRCLES($1))
708 else Ast0.wrap(Ast0.DOTS($1)) }
710 define_param_list_start:
711 ident { [Ast0.wrap(Ast0.DParam $1)] }
712 | ident TComma define_param_list_start
713 { Ast0.wrap(Ast0.DParam $1)::
714 Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $2))::$3 }
715 | d=TEllipsis r=list(dp_comma_args(TEllipsis))
716 { (P.mkdpdots "..." d)::
717 (List.concat (List.map (function x -> x (P.mkdpdots "...")) r)) }
719 dp_comma_args(dotter):
721 { function dot_builder ->
722 [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," c)); dot_builder d] }
724 { function dot_builder ->
725 [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $1));
726 Ast0.wrap(Ast0.DParam $2)] }
728 define_param_list_option: define_param_list { $1 }
729 | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
731 /*****************************************************************************/
734 s=ioption(storage) t=ctype
735 id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
740 (Ast0.FunctionType(Some t,
741 P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
742 id, P.clt2mcode ";" pt)) }
743 | s=ioption(storage) t=Tvoid
744 id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
745 { let t = Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" t])) in
750 (Ast0.FunctionType(Some t,
751 P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
752 id, P.clt2mcode ";" pt)) }
757 TFunDecl i=func_ident lp=TOPar d=decl_list(decl) rp=TCPar
758 lb=TOBrace b=fun_start rb=TCBrace
759 { Ast0.wrap(Ast0.FunDecl((Ast0.default_info(),Ast0.context_befaft()),
761 P.clt2mcode "(" lp, d,
763 P.clt2mcode "{" lb, b,
764 P.clt2mcode "}" rb)) }
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 }
774 | t=fn_ctype r=fninfo_nt { (Ast0.FType(t))::r }
777 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
778 raise (Semantic_cocci.Semantic "duplicate inline")
779 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
782 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
783 raise (Semantic_cocci.Semantic "multiple attributes")
784 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
791 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
792 raise (Semantic_cocci.Semantic "duplicate storage")
793 with Not_found -> (Ast0.FStorage($1))::$2 }
796 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
797 raise (Semantic_cocci.Semantic "duplicate inline")
798 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
801 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
802 raise (Semantic_cocci.Semantic "duplicate init")
803 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
806 s=Tstatic { P.clt2mcode Ast.Static s }
807 | s=Tauto { P.clt2mcode Ast.Auto s }
808 | s=Tregister { P.clt2mcode Ast.Register s }
809 | s=Textern { P.clt2mcode Ast.Extern s }
811 decl: t=ctype i=ident
812 { Ast0.wrap(Ast0.Param(t, Some i)) }
813 | t=fn_ctype lp=TOPar s=TMul i=ident rp=TCPar
814 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
817 (Ast0.FunctionPointer
818 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
819 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
820 Ast0.wrap(Ast0.Param(fnptr, Some i)) }
823 Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" t])) in
824 Ast0.wrap(Ast0.VoidParam(ty)) }
826 { let (nm,pure,clt) = $1 in
827 Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) }
831 | t=ctype { Ast0.wrap(Ast0.Param(t, None)) }
832 | t=fn_ctype lp=TOPar s=TMul rp=TCPar
833 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
836 (Ast0.FunctionPointer
837 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
838 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
839 Ast0.wrap(Ast0.Param(fnptr, None)) }
842 Tconst { P.clt2mcode Ast.Const $1 }
843 | Tvolatile { P.clt2mcode Ast.Volatile $1 }
845 /*****************************************************************************/
848 includes { $1 } /* shouldn't be allowed to be a single_statement... */
853 | TIf TOPar eexpr TCPar single_statement %prec TIf
854 { P.ifthen $1 $2 $3 $4 $5 }
855 | TIf TOPar eexpr TCPar single_statement TElse single_statement
856 { P.ifthenelse $1 $2 $3 $4 $5 $6 $7 }
857 | TFor TOPar option(eexpr) TPtVirg option(eexpr) TPtVirg
858 option(eexpr) TCPar single_statement
859 { P.forloop $1 $2 $3 $4 $5 $6 $7 $8 $9 }
860 | TWhile TOPar eexpr TCPar single_statement
861 { P.whileloop $1 $2 $3 $4 $5 }
862 | TDo single_statement TWhile TOPar eexpr TCPar TPtVirg
863 { P.doloop $1 $2 $3 $4 $5 $6 $7 }
864 | iter_ident TOPar eexpr_list_option TCPar single_statement
865 { P.iterator $1 $2 $3 $4 $5 }
866 | TSwitch TOPar eexpr TCPar TOBrace list(case_line) TCBrace
867 { P.switch $1 $2 $3 $4 $5 $6 $7 }
868 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
869 | TReturn TPtVirg { P.ret $1 $2 }
870 | TBreak TPtVirg { P.break $1 $2 }
871 | TContinue TPtVirg { P.cont $1 $2 }
872 | ident TDotDot { P.label $1 $2 }
873 | TGoto ident TPtVirg { P.goto $1 $2 $3 }
874 | TOBrace fun_start TCBrace
878 TEllipsis w=list(whenppdecs)
879 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." $1, List.concat w)) }
880 | TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
881 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." $1, b,
882 P.clt2mcode "...>" c, List.concat w, false)) }
883 | TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
884 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." $1, b,
885 P.clt2mcode "...+>" c, List.concat w, true)) }
887 %inline stm_dots_ell:
888 a=TEllipsis w=list(whenppdecs)
889 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." a, List.concat w)) }
891 %inline stm_dots_nest:
892 a=TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
893 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." a, b,
894 P.clt2mcode "...>" c, List.concat w, false)) }
895 | a=TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
896 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." a, b,
897 P.clt2mcode "...+>" c, List.concat w, true)) }
899 whenppdecs: w=whens(when_start,rule_elem_statement)
902 /* a statement that fits into a single rule_elem. should nests be included?
903 what about statement metavariables? */
906 { Ast0.wrap(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),$1)) }
907 | expr TPtVirg { P.exp_stm $1 $2 }
908 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
909 | TReturn TPtVirg { P.ret $1 $2 }
910 | TBreak TPtVirg { P.break $1 $2 }
911 | TContinue TPtVirg { P.cont $1 $2 }
912 | TOPar0 midzero_list(rule_elem_statement,rule_elem_statement) TCPar0
913 { let (mids,code) = $2 in
915 (Ast0.Disj(P.clt2mcode "(" $1,
916 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
917 mids, P.clt2mcode ")" $3)) }
919 /* a statement on its own */
922 | TOPar0 midzero_list(statement,statement) TCPar0
923 /* degenerate case, elements are single statements and thus don't
925 { let (mids,code) = $2 in
927 (Ast0.Disj(P.clt2mcode "(" $1,
928 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
929 mids, P.clt2mcode ")" $3)) }
932 TDefault TDotDot fun_start
933 { Ast0.wrap(Ast0.Default(P.clt2mcode "default" $1,P.clt2mcode ":" $2,$3)) }
934 | TCase eexpr TDotDot fun_start
935 { Ast0.wrap(Ast0.Case(P.clt2mcode "case" $1,$2,P.clt2mcode ":" $3,$4)) }
937 /* In the following, an identifier as a type is not fully supported. Indeed,
938 the language is ambiguous: what is foo * bar; */
939 /* The AST DisjDecl cannot be generated because it would be ambiguous with
940 a disjunction on a statement with a declaration in each branch */
943 { [Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv))] }
944 | s=ioption(storage) t=ctype d=comma_list(d_ident) pv=TPtVirg
947 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)))
950 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
952 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
953 /* type is a typedef name */
954 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
955 d=comma_list(d_ident) pv=TPtVirg
959 P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
960 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)))
962 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
963 e=initialize pv=TPtVirg
965 !Data.add_type_name (P.id2name i);
966 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
967 [Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
968 P.clt2mcode ";" pv))] }
969 /* function pointer type */
971 t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
972 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
977 (Ast0.FunctionPointer
978 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
979 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
980 [Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv))] }
981 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
982 { [Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
983 P.clt2mcode ")" $4,P.clt2mcode ";" $5))] }
985 t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
986 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
987 q=TEq e=initialize pv=TPtVirg
991 (Ast0.FunctionPointer
992 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
993 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
994 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
995 | s=Ttypedef t=ctype_full id=typedef_ident pv=TPtVirg
996 { let s = P.clt2mcode "typedef" s in
997 [Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv))] }
1001 { Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv)) }
1002 | s=ioption(storage) t=ctype d=d_ident pv=TPtVirg
1003 { let (id,fn) = d in
1004 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1006 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
1007 { let (id,fn) = d in
1008 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv)) }
1009 /* type is a typedef name */
1010 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
1011 d=d_ident pv=TPtVirg
1012 { let (id,fn) = d in
1013 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1014 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)) }
1015 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
1016 e=initialize pv=TPtVirg
1017 { let (id,fn) = d in
1018 !Data.add_type_name (P.id2name i);
1019 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1020 Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
1021 P.clt2mcode ";" pv)) }
1022 /* function pointer type */
1023 | s=ioption(storage)
1024 t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1025 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1027 { let (id,fn) = d in
1030 (Ast0.FunctionPointer
1031 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1032 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1033 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1034 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
1035 { Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
1036 P.clt2mcode ")" $4,P.clt2mcode ";" $5)) }
1037 | s=ioption(storage)
1038 t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1039 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1040 q=TEq e=initialize pv=TPtVirg
1041 { let (id,fn) = d in
1044 (Ast0.FunctionPointer
1045 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1046 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1047 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))}
1051 ident list(array_dec)
1055 (function (l,i,r) ->
1058 (Ast0.Array(rest,P.clt2mcode "[" l,i,P.clt2mcode "]" r)))
1061 array_dec: l=TOCro i=option(eexpr) r=TCCro { (l,i,r) }
1065 { Ast0.wrap(Ast0.InitExpr($1)) }
1066 | TOBrace initialize_list TCBrace
1067 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1070 (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []),
1071 P.clt2mcode "}" $2)) }
1073 {let (nm,pure,clt) = $1 in
1074 Ast0.wrap(Ast0.MetaInit(P.clt2mcode nm clt,pure)) }
1077 /*arithexpr and not eexpr because can have ambiguity with comma*/
1078 /*dots and nests probably not allowed at top level, haven't looked into why*/
1079 arith_expr(eexpr,invalid) { Ast0.wrap(Ast0.InitExpr($1)) }
1080 | TOBrace initialize_list TCBrace
1081 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1084 (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []),
1085 P.clt2mcode "}" $2)) }
1086 /* gccext:, labeled elements */
1087 | list(designator) TEq initialize2
1088 { Ast0.wrap(Ast0.InitGccExt($1,P.clt2mcode "=" $2,$3)) }
1089 | ident TDotDot initialize2
1090 { Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */
1094 { Ast0.DesignatorField (P.clt2mcode "." $1,$2) }
1096 { Ast0.DesignatorIndex (P.clt2mcode "[" $1,$2,P.clt2mcode "]" $3) }
1097 | TOCro eexpr TEllipsis eexpr TCCro
1098 { Ast0.DesignatorRange (P.clt2mcode "[" $1,$2,P.clt2mcode "..." $3,
1099 $4,P.clt2mcode "]" $5) }
1102 initialize_list_start { Ast0.wrap(Ast0.DOTS($1)) }
1104 initialize_list_start:
1105 initialize2 TComma { [$1;Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))] }
1106 | initialize2 TComma initialize_list_start
1107 { $1::Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))::$3 }
1108 | d=edots_when(TEllipsis,initialize)
1109 r=comma_initializers(edots_when(TEllipsis,initialize))
1110 { (P.mkidots "..." d)::
1111 (List.concat(List.map (function x -> x (P.mkidots "...")) r)) }
1113 comma_initializers(dotter):
1115 | d=dotter r=comma_initializers2(dotter)
1116 { (function dot_builder -> [dot_builder d])::r }
1117 | i=initialize2 c=TComma r=comma_initializers(dotter)
1118 { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
1121 comma_initializers2(dotter):
1123 | i=initialize2 c=TComma r=comma_initializers(dotter)
1124 { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
1127 /* a statement that is part of a list */
1130 { let (nm,pure,clt) = $1 in
1131 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1136 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1138 | statement { [$1] }
1139 /* this doesn't allow expressions at top level, because the parser doesn't
1140 know whether there is one. If there is one, this is not sequencible.
1141 If there is not one, then it is. It seems complicated to get around
1142 this at the parser level. We would have to have a check afterwards to
1143 allow this. One case where this would be useful is for a when. Now
1144 we allow a sequence of whens, so one can be on only statements and
1145 one can be on only expressions. */
1146 | TOPar0 t=midzero_list(fun_start,fun_start) TCPar0
1147 { let (mids,code) = t in
1150 match Ast0.unwrap x with Ast0.DOTS([]) -> true | _ -> false)
1154 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, code, mids,
1155 P.clt2mcode ")" $3))] }
1157 /* a statement that is part of a list */
1158 decl_statement_expr:
1160 { let (nm,pure,clt) = $1 in
1161 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1166 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1168 | statement { [$1] }
1169 /* this doesn't allow expressions at top level, because the parser doesn't
1170 know whether there is one. If there is one, this is not sequencible.
1171 If there is not one, then it is. It seems complicated to get around
1172 this at the parser level. We would have to have a check afterwards to
1173 allow this. One case where this would be useful is for a when. Now
1174 we allow a sequence of whens, so one can be on only statements and
1175 one can be on only expressions. */
1176 | TOPar0 t=midzero_list(fun_after_stm,fun_after_dots_or) TCPar0
1177 { let (mids,code) = t in
1178 if List.for_all (function [] -> true | _ -> false) code
1182 List.map (function x -> Ast0.wrap(Ast0.DOTS x)) code in
1183 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, dot_code, mids,
1184 P.clt2mcode ")" $3))] }
1186 /*****************************************************************************/
1188 /* The following cannot contain <... ...> at the top level. This can only
1189 be allowed as an expression when the expression is delimited on both sides
1190 by expression-specific markers. In that case, the rule eexpr is used, which
1191 allows <... ...> anywhere. Hopefully, this will not be too much of a problem
1193 expr: basic_expr(expr,invalid) { $1 }
1194 /* allows ... and nests */
1195 eexpr: basic_expr(eexpr,dot_expressions) { $1 }
1196 /* allows nests but not .... */
1197 dexpr: basic_expr(eexpr,nest_expressions) { $1 }
1200 eexpr { Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))) }
1203 TInvalid { raise (Semantic_cocci.Semantic "not matchable") }
1206 TEllipsis { Ast0.wrap(Ast0.Edots(P.clt2mcode "..." $1,None)) }
1207 | nest_expressions { $1 }
1209 /* not clear what whencode would mean, so just drop it */
1211 TOEllipsis e=expr_dots(TEllipsis) c=TCEllipsis
1212 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<..." $1,
1213 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1214 P.clt2mcode "...>" c, None, false)) }
1215 | TPOEllipsis e=expr_dots(TEllipsis) c=TPCEllipsis
1216 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<+..." $1,
1217 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1218 P.clt2mcode "...+>" c, None, true)) }
1220 //whenexp: TWhen TNotEq w=eexpr TLineEnd { w }
1222 basic_expr(recurser,primary_extra):
1223 assign_expr(recurser,primary_extra) { $1 }
1226 cond_expr(r,pe) { $1 }
1227 | unary_expr(r,pe) TAssign assign_expr_bis
1228 { let (op,clt) = $2 in
1229 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1230 Ast0.set_arg_exp $3,false)) }
1231 | unary_expr(r,pe) TEq assign_expr_bis
1234 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1237 cond_expr(eexpr,dot_expressions) { $1 }
1238 | unary_expr(eexpr,dot_expressions) TAssign assign_expr_bis
1239 { let (op,clt) = $2 in
1240 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1241 Ast0.set_arg_exp $3,false)) }
1242 | unary_expr(eexpr,dot_expressions) TEq assign_expr_bis
1245 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1248 arith_expr(r,pe) { $1 }
1249 | l=arith_expr(r,pe) w=TWhy t=option(eexpr) dd=TDotDot r=cond_expr(r,pe)
1250 { Ast0.wrap(Ast0.CondExpr (l, P.clt2mcode "?" w, t,
1251 P.clt2mcode ":" dd, r)) }
1254 cast_expr(r,pe) { $1 }
1255 | arith_expr(r,pe) TMul arith_expr(r,pe)
1256 { P.arith_op Ast.Mul $1 $2 $3 }
1257 | arith_expr(r,pe) TDmOp arith_expr(r,pe)
1258 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1259 | arith_expr(r,pe) TPlus arith_expr(r,pe)
1260 { P.arith_op Ast.Plus $1 $2 $3 }
1261 | arith_expr(r,pe) TMinus arith_expr(r,pe)
1262 { P.arith_op Ast.Minus $1 $2 $3 }
1263 | arith_expr(r,pe) TShOp arith_expr(r,pe)
1264 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1265 | arith_expr(r,pe) TLogOp arith_expr(r,pe)
1266 { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
1267 | arith_expr(r,pe) TEqEq arith_expr(r,pe)
1268 { P.logic_op Ast.Eq $1 $2 $3 }
1269 | arith_expr(r,pe) TNotEq arith_expr(r,pe)
1270 { P.logic_op Ast.NotEq $1 $2 $3 }
1271 | arith_expr(r,pe) TAnd arith_expr(r,pe)
1272 { P.arith_op Ast.And $1 $2 $3 }
1273 | arith_expr(r,pe) TOr arith_expr(r,pe)
1274 { P.arith_op Ast.Or $1 $2 $3 }
1275 | arith_expr(r,pe) TXor arith_expr(r,pe)
1276 { P.arith_op Ast.Xor $1 $2 $3 }
1277 | arith_expr(r,pe) TAndLog arith_expr(r,pe)
1278 { P.logic_op Ast.AndLog $1 $2 $3 }
1279 | arith_expr(r,pe) TOrLog arith_expr(r,pe)
1280 { P.logic_op Ast.OrLog $1 $2 $3 }
1283 unary_expr(r,pe) { $1 }
1284 | lp=TOPar t=ctype rp=TCPar e=cast_expr(r,pe)
1285 { Ast0.wrap(Ast0.Cast (P.clt2mcode "(" lp, t,
1286 P.clt2mcode ")" rp, e)) }
1289 postfix_expr(r,pe) { $1 }
1290 | TInc unary_expr(r,pe)
1291 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
1292 | TDec unary_expr(r,pe)
1293 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
1294 | unary_op cast_expr(r,pe)
1295 { let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
1296 | TBang unary_expr(r,pe)
1297 { let mcode = P.clt2mcode Ast.Not $1 in
1298 Ast0.wrap(Ast0.Unary($2, mcode)) }
1299 | TSizeof unary_expr(r,pe)
1300 { Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
1301 | s=TSizeof lp=TOPar t=ctype rp=TCPar
1302 { Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
1303 P.clt2mcode "(" lp,t,
1304 P.clt2mcode ")" rp)) }
1306 unary_op: TAnd { P.clt2mcode Ast.GetRef $1 }
1307 | TMul { P.clt2mcode Ast.DeRef $1 }
1308 | TPlus { P.clt2mcode Ast.UnPlus $1 }
1309 | TMinus { P.clt2mcode Ast.UnMinus $1 }
1310 | TTilde { P.clt2mcode Ast.Tilde $1 }
1313 primary_expr(r,pe) { $1 }
1314 | postfix_expr(r,pe) TOCro eexpr TCCro
1315 { Ast0.wrap(Ast0.ArrayAccess ($1,P.clt2mcode "[" $2,$3,
1316 P.clt2mcode "]" $4)) }
1317 | postfix_expr(r,pe) TDot ident
1318 { Ast0.wrap(Ast0.RecordAccess($1, P.clt2mcode "." $2, $3)) }
1319 | postfix_expr(r,pe) TPtrOp ident
1320 { Ast0.wrap(Ast0.RecordPtAccess($1, P.clt2mcode "->" $2,
1322 | postfix_expr(r,pe) TInc
1323 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Inc $2)) }
1324 | postfix_expr(r,pe) TDec
1325 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Dec $2)) }
1326 | postfix_expr(r,pe) TOPar eexpr_list_option TCPar
1327 { Ast0.wrap(Ast0.FunCall($1,P.clt2mcode "(" $2,
1329 P.clt2mcode ")" $4)) }
1331 primary_expr(recurser,primary_extra):
1332 func_ident { Ast0.wrap(Ast0.Ident($1)) }
1334 { let (x,clt) = $1 in
1335 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1337 { let (x,clt) = $1 in
1338 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Float x) clt)) }
1340 { let (x,clt) = $1 in
1341 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.String x) clt)) }
1343 { let (x,clt) = $1 in
1344 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Char x) clt)) }
1346 { let (nm,constraints,pure,ty,clt) = $1 in
1348 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
1350 { let (nm,constraints,pure,clt) = $1 in
1351 Ast0.wrap(Ast0.MetaErr(P.clt2mcode nm clt,constraints,pure)) }
1353 { let (nm,constraints,pure,ty,clt) = $1 in
1355 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
1357 { let (nm,constraints,pure,ty,clt) = $1 in
1359 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
1361 { let (nm,constraints,pure,ty,clt) = $1 in
1363 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.LocalID,pure)) }
1365 { Ast0.wrap(Ast0.Paren(P.clt2mcode "(" $1,$2,
1366 P.clt2mcode ")" $3)) }
1367 | TOPar0 midzero_list(recurser,eexpr) TCPar0
1368 { let (mids,code) = $2 in
1369 Ast0.wrap(Ast0.DisjExpr(P.clt2mcode "(" $1,
1371 P.clt2mcode ")" $3)) }
1372 | primary_extra { $1 }
1375 r=no_dot_start_end(dexpr,edots_when(dotter,eexpr)) { r }
1378 no_dot_start_end(grammar,dotter):
1379 g=grammar dg=list(pair(dotter,grammar))
1380 { function dot_builder ->
1381 g :: (List.concat(List.map (function (d,g) -> [dot_builder d;g]) dg)) }
1383 /*****************************************************************************/
1389 TRuleName TDot pure_ident { (Some $1,P.id2name $3) }
1391 pure_ident_or_meta_ident:
1392 pure_ident { (None,P.id2name $1) }
1394 | Tlist { (None,"list") }
1395 | TError { (None,"error") }
1396 | TType { (None,"type") }
1397 | TName { (None,"name") }
1399 pure_ident_or_meta_ident_with_not_eq(not_eq):
1400 i=pure_ident_or_meta_ident l=loption(not_eq) { (i,l) }
1405 then failwith "constraints not allowed in iso file");
1406 (if !Data.in_generating
1407 (* pb: constraints not stored with metavars; too lazy to search for
1408 them in the pattern *)
1409 then failwith "constraints not allowed in a generated rule file");
1410 [Ast0.wrap(Ast0.Id(P.id2mcode i))] }
1411 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1413 then failwith "constraints not allowed in iso file");
1414 (if !Data.in_generating
1415 then failwith "constraints not allowed in a generated rule file");
1416 List.map (function i -> Ast0.wrap(Ast0.Id(P.id2mcode i))) l }
1421 then failwith "constraints not allowed in iso file");
1422 (if !Data.in_generating
1423 then failwith "constraints not allowed in a generated rule file");
1424 [Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))] }
1425 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1427 then failwith "constraints not allowed in iso file");
1428 (if !Data.in_generating
1429 then failwith "constraints not allowed in a generated rule file");
1432 Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))))
1436 TNotEq i=ident_or_const
1438 then failwith "constraints not allowed in iso file");
1439 (if !Data.in_generating
1440 then failwith "constraints not allowed in a generated rule file");
1442 | TNotEq TOBrace l=comma_list(ident_or_const) TCBrace
1444 then failwith "constraints not allowed in iso file");
1445 (if !Data.in_generating
1446 then failwith "constraints not allowed in a generated rule file");
1450 i=pure_ident { Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))) }
1452 { let (x,clt) = $1 in
1453 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1458 then failwith "constraints not allowed in iso file");
1459 (if !Data.in_generating
1460 then failwith "constraints not allowed in a generated rule file");
1462 (None,_) -> failwith "constraint must be an inherited variable"
1463 | (Some rule,name) ->
1464 let i = (rule,name) in
1465 P.check_meta(Ast.MetaPosDecl(Ast.NONE,i));
1467 | TNotEq TOBrace l=comma_list(meta_ident) TCBrace
1469 then failwith "constraints not allowed in iso file");
1470 (if !Data.in_generating
1471 then failwith "constraints not allowed in a generated rule file");
1475 failwith "constraint must be an inherited variable"
1476 | (Some rule,name) ->
1477 let i = (rule,name) in
1478 P.check_meta(Ast.MetaPosDecl(Ast.NONE,i));
1482 func_ident: pure_ident
1483 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1485 { let (nm,constraints,pure,clt) = $1 in
1486 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1488 { let (nm,constraints,pure,clt) = $1 in
1489 Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
1491 { let (nm,constraints,pure,clt) = $1 in
1493 (Ast0.MetaLocalFunc(P.clt2mcode nm clt,constraints,pure)) }
1496 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1498 { let (nm,constraints,pure,clt) = $1 in
1499 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1503 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1505 { let (nm,constraints,pure,clt) = $1 in
1506 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1510 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1512 { let (nm,constraints,pure,clt) = $1 in
1513 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1517 { Ast0.wrap(Ast0.TypeName(P.id2mcode $1)) }
1519 { let (nm,pure,clt) = $1 in
1520 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
1522 /*****************************************************************************/
1525 /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
1526 | decl_list_start(decl)
1528 match Ast0.unwrap x with Ast0.Pcircles(_) -> true | _ -> false in
1529 if List.exists circle $1
1530 then Ast0.wrap(Ast0.CIRCLES($1))
1531 else Ast0.wrap(Ast0.DOTS($1)) }
1533 decl_list_start(decl):
1534 one_dec(decl) { [$1] }
1535 | one_dec(decl) TComma decl_list_start(decl)
1536 { $1::Ast0.wrap(Ast0.PComma(P.clt2mcode "," $2))::$3 }
1537 | TEllipsis list(comma_decls(TEllipsis,decl))
1538 { Ast0.wrap(Ast0.Pdots(P.clt2mcode "..." $1))::
1539 (List.concat(List.map (function x -> x (P.mkpdots "...")) $2)) }
1544 { let (nm,lenname,pure,clt) = $1 in
1545 let nm = P.clt2mcode nm clt in
1548 Some nm -> Some(P.clt2mcode nm clt)
1550 Ast0.wrap(Ast0.MetaParamList(nm,lenname,pure)) }
1552 comma_decls(dotter,decl):
1554 { function dot_builder ->
1555 [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1));
1557 | TComma one_dec(decl)
1558 { function dot_builder ->
1559 [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1)); $2] }
1561 /* ---------------------------------------------------------------------- */
1564 TError TWords TEq TOCro cl=comma_list(dexpr) TCCro
1565 { [Ast0.wrap(Ast0.ERRORWORDS(cl))] }
1567 /* ---------------------------------------------------------------------- */
1568 /* sequences of statements and expressions */
1570 /* There are number of cases that must be considered:
1573 Dots and nests allowed at the beginning or end
1574 Expressions allowed at the beginning or end
1575 One function allowed, by itself
1577 Dots and nests allowed at the beginning or end
1578 Expressions not allowed at the beginning or end
1579 Functions not allowed
1580 3. The body of a nest:
1581 Dots and nests not allowed at the beginning or end
1582 Expressions allowed at the beginning or end
1583 Functions not allowed
1585 Dots and nests not allowed at the beginning but allowed at the end
1586 Expressions allowed at the beginning or end
1587 Functions not allowed
1589 These are implemented by the rules minus_toplevel_sequence,
1590 plus_toplevel_sequence, function_body_sequence, nest_body_sequence, and
1593 /* ------------------------------------------------------------------------ */
1594 /* Minus top level */
1596 /* doesn't allow only ... */
1598 fundecl { [Ast0.wrap(Ast0.DECL($1))] }
1599 | ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1600 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1601 | toplevel_seq_startne(toplevel_after_dots_init)
1602 { List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1 }
1604 toplevel_seq_startne(after_dots_init):
1605 a=stm_dots_ell b=after_dots_init { a::b }
1606 | a=stm_dots_nest b=after_dots_init { a::b }
1607 | a=stm_dots_nest { [a] }
1608 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1609 | decl_statement_expr toplevel_after_stm { $1@$2 }
1611 toplevel_seq_start(after_dots_init):
1612 stm_dots after_dots_init { $1::$2 }
1613 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1614 | decl_statement_expr toplevel_after_stm { $1@$2 }
1616 toplevel_after_dots_init:
1617 TNothing toplevel_after_exp {$2}
1618 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1619 | decl_statement_expr toplevel_after_stm {$1@$2}
1623 | stm_dots toplevel_after_dots {$1::$2}
1625 toplevel_after_dots:
1627 | TNothing toplevel_after_exp {$2}
1628 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1629 | decl_statement_expr toplevel_after_stm {$1@$2}
1633 | stm_dots toplevel_after_dots {$1::$2}
1634 | decl_statement toplevel_after_stm {$1@$2}
1637 TOInit initialize_list TCBrace
1638 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1640 /* ------------------------------------------------------------------------ */
1641 /* Plus top level */
1643 /* does allow only ... also allows multiple top-level functions */
1645 ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1646 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1647 | stm_dots plus_after_dots
1648 { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1649 | expr plus_after_exp
1650 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1651 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1652 | decl_statement_expr plus_after_stm
1653 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1657 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1661 | TNothing plus_after_exp {$2}
1662 | expr plus_after_exp
1663 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1664 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1665 | decl_statement_expr plus_after_stm
1666 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1670 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1671 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1672 | decl_statement plus_after_stm
1673 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1675 /* ------------------------------------------------------------------------ */
1679 fun_after_stm { Ast0.wrap(Ast0.DOTS($1)) }
1683 | stm_dots fun_after_dots {$1::$2}
1684 | decl_statement fun_after_stm {$1@$2}
1688 | TNothing fun_after_exp {$2}
1689 | expr fun_after_exp {Ast0.wrap(Ast0.Exp($1))::$2}
1690 | decl_statement_expr fun_after_stm {$1@$2}
1693 stm_dots fun_after_dots {$1::$2}
1695 /* hack to allow mixing statements and expressions in an or */
1698 | TNothing fun_after_exp_or {$2}
1699 | expr fun_after_exp_or {Ast0.wrap(Ast0.Exp($1))::$2}
1700 | decl_statement_expr fun_after_stm {$1@$2}
1704 | stm_dots fun_after_dots {$1::$2}
1706 /* ------------------------------------------------------------------------ */
1710 nest_after_dots { Ast0.wrap(Ast0.DOTS($1)) }
1713 decl_statement_expr nest_after_stm {$1@$2}
1714 | TNothing nest_after_exp {$2}
1715 | expr nest_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1719 | stm_dots nest_after_dots {$1::$2}
1720 | decl_statement nest_after_stm {$1@$2}
1724 | stm_dots nest_after_dots {$1::$2}
1726 /* ------------------------------------------------------------------------ */
1730 expr toplevel_after_exp
1731 { Ast0.wrap(Ast0.DOTS((Ast0.wrap(Ast0.Exp($1)))::$2)) }
1732 | decl_statement toplevel_after_stm
1733 { Ast0.wrap(Ast0.DOTS($1@$2)) }
1735 /* ---------------------------------------------------------------------- */
1740 match Ast0.unwrap x with Ast0.Ecircles(_) -> true | _ -> false in
1742 match Ast0.unwrap x with Ast0.Estars(_) -> true | _ -> false in
1743 if List.exists circle $1
1744 then Ast0.wrap(Ast0.CIRCLES($1))
1746 if List.exists star $1
1747 then Ast0.wrap(Ast0.STARS($1))
1748 else Ast0.wrap(Ast0.DOTS($1)) }
1750 /* arg expr. may contain a type or a explist metavariable */
1753 { Ast0.set_arg_exp $1 }
1755 { let (nm,lenname,pure,clt) = $1 in
1756 let nm = P.clt2mcode nm clt in
1759 Some nm -> Some(P.clt2mcode nm clt)
1761 Ast0.wrap(Ast0.MetaExprList(nm,lenname,pure)) }
1763 { Ast0.set_arg_exp(Ast0.wrap(Ast0.TypeExp($1))) }
1767 | aexpr TComma eexpr_list_start
1768 { $1::Ast0.wrap(Ast0.EComma(P.clt2mcode "," $2))::$3 }
1772 { function dot_builder ->
1773 [Ast0.wrap(Ast0.EComma(P.clt2mcode "," c)); dot_builder d] }
1775 { function dot_builder ->
1776 [Ast0.wrap(Ast0.EComma(P.clt2mcode "," $1)); $2] }
1778 eexpr_list_option: eexpr_list { $1 }
1779 | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
1781 /****************************************************************************/
1783 // non-empty lists - drop separator
1785 separated_nonempty_list(TComma,elem) { $1 }
1787 midzero_list(elem,aft):
1788 a=elem b=list(mzl(aft))
1789 { let (mids,code) = List.split b in (mids,(a::code)) }
1792 a=TMid0 b=elem { (P.clt2mcode "|" a, b) }
1794 edots_when(dotter,when_grammar):
1795 d=dotter { (d,None) }
1796 | d=dotter TWhen TNotEq w=when_grammar TLineEnd { (d,Some w) }
1798 whens(when_grammar,simple_when_grammar):
1799 TWhen TNotEq w=when_grammar TLineEnd { [Ast0.WhenNot w] }
1800 | TWhen TEq w=simple_when_grammar TLineEnd { [Ast0.WhenAlways w] }
1801 | TWhen comma_list(any_strict) TLineEnd
1802 { List.map (function x -> Ast0.WhenModifier(x)) $2 }
1803 | TWhenTrue TNotEq e = eexpr TLineEnd { [Ast0.WhenNotTrue e] }
1804 | TWhenFalse TNotEq e = eexpr TLineEnd { [Ast0.WhenNotFalse e] }
1807 TAny { Ast.WhenAny }
1808 | TStrict { Ast.WhenStrict }
1809 | TForall { Ast.WhenForall }
1810 | TExists { Ast.WhenExists }
1812 /*****************************************************************************
1815 *****************************************************************************/
1818 TIsoExpression e1=dexpr el=list(iso(dexpr)) EOF
1819 { P.iso_adjust (function x -> Ast0.ExprTag x) e1 el }
1820 | TIsoArgExpression e1=dexpr el=list(iso(dexpr)) EOF
1821 { P.iso_adjust (function x -> Ast0.ArgExprTag x) e1 el }
1822 | TIsoTestExpression e1=dexpr el=list(iso(dexpr)) EOF
1823 { P.iso_adjust (function x -> Ast0.TestExprTag x) e1 el }
1824 | TIsoStatement s1=single_statement sl=list(iso(single_statement)) EOF
1825 { P.iso_adjust (function x -> Ast0.StmtTag x) s1 sl }
1826 | TIsoType t1=ctype tl=list(iso(ctype)) EOF
1827 { P.iso_adjust (function x -> Ast0.TypeCTag x) t1 tl }
1828 | TIsoTopLevel e1=nest_start el=list(iso(nest_start)) EOF
1829 { P.iso_adjust (function x -> Ast0.DotsStmtTag x) e1 el }
1830 | TIsoDeclaration d1=decl_var dl=list(iso(decl_var)) EOF
1831 { let check_one = function
1835 (Semantic_cocci.Semantic
1836 "only one variable per declaration in an isomorphism rule") in
1837 let d1 = check_one d1 in
1841 Common.Left x -> Common.Left(check_one x)
1842 | Common.Right x -> Common.Right(check_one x))
1844 P.iso_adjust (function x -> Ast0.DeclTag x) d1 dl }
1847 TIso t=term { Common.Left t }
1848 | TRightIso t=term { Common.Right t }
1850 /*****************************************************************************
1853 *****************************************************************************/
1855 never_used: TPragma { () }
1856 | TPArob TMetaPos { () }
1857 | TScriptData { () }
1859 script_meta_main: py=pure_ident TShOp TRuleName TDot cocci=pure_ident TMPtVirg
1860 { (P.id2name py, ($3, P.id2name cocci)) }