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 TInitialize TFinalize 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 }
210 | TInitialize TDotDot lang=pure_ident TArob
211 { P.make_initial_script_rule_name_result lang }
212 | TFinalize TDotDot lang=pure_ident TArob
213 { P.make_final_script_rule_name_result lang }
217 | TExtends parent=TRuleName
218 { !Data.install_bindings (parent) }
221 /* empty */ { Ast.NoDep }
222 | TDepends TOn parents=dep { parents }
226 | dep TAndLog dep { Ast.AndDep($1, $3) }
227 | dep TOrLog dep { Ast.OrDep ($1, $3) }
230 TRuleName { Ast.Dep $1 }
231 | TBang TRuleName { Ast.AntiDep $2 }
232 | TEver TRuleName { Ast.EverDep $2 }
233 | TNever TRuleName { Ast.NeverDep $2 }
234 | TOPar dep TCPar { $2 }
237 TUsing separated_nonempty_list(TComma,TString) { List.map P.id2name $2 }
240 TDisable separated_nonempty_list(TComma,pure_ident) { List.map P.id2name $2 }
243 TExists { Ast.Exists }
244 | TForall { Ast.Forall }
245 | TReverse TForall { Ast.ReverseForall }
246 | { Ast.Undetermined }
248 is_expression: // for more flexible parsing of top level expressions
250 | TExpression { true }
253 list(incl) TArob { $1 }
254 | list(incl) TArobArob { $1 }
257 TUsing TString { Common.Left(P.id2name $2) }
258 | TUsing TPathIsoFile { Common.Right $2 }
262 kindfn=metakind ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
263 { P.create_metadec ar ispure kindfn ids }
264 | kindfn=metakind_fresh ids=comma_list(pure_ident_or_meta_ident_with_seed)
266 { P.create_fresh_metadec kindfn ids }
267 | ar=arity ispure=pure
268 kindfn=metakind_atomic
269 ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_eq)) TMPtVirg
270 { P.create_metadec_ne ar ispure kindfn ids }
271 | ar=arity ispure=pure
272 kindfn=metakind_atomic_expi
273 ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_eqe)) TMPtVirg
274 { P.create_metadec_ne ar ispure kindfn ids }
275 | ar=arity ispure=pure
276 kindfn=metakind_atomic_expe
277 ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_ceq)) TMPtVirg
278 { P.create_metadec_ne ar ispure kindfn ids }
279 | ar=arity TPosition a=option(TPosAny)
280 ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_pos)) TMPtVirg
281 (* pb: position variables can't be inherited from normal rules, and then
282 there is no way to inherit from a generated rule, so there is no point
283 to have a position variable *)
284 { (if !Data.in_generating
285 then failwith "position variables not allowed in a generated rule file");
286 let kindfn arity name pure check_meta constraints =
287 let tok = check_meta(Ast.MetaPosDecl(arity,name)) in
288 let any = match a with None -> Ast.PER | Some _ -> Ast.ALL in
289 !Data.add_pos_meta name constraints any; tok in
290 P.create_metadec_ne ar false kindfn ids }
291 | ar=arity ispure=pure
292 TParameter Tlist TOCro id=pure_ident_or_meta_ident TCCro
293 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
294 { P.create_len_metadec ar ispure
295 (fun lenname arity name pure check_meta ->
297 check_meta(Ast.MetaParamListDecl(arity,name,Some lenname)) in
298 !Data.add_paramlist_meta name (Some lenname) pure; tok)
300 | ar=arity ispure=pure
301 TExpression Tlist TOCro id=pure_ident_or_meta_ident TCCro
302 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
303 { P.create_len_metadec ar ispure
304 (fun lenname arity name pure check_meta ->
306 check_meta(Ast.MetaExpListDecl(arity,name,Some lenname)) in
307 !Data.add_explist_meta name (Some lenname) pure; tok)
310 %inline metakind_fresh:
312 { (fun name check_meta seed ->
313 let tok = check_meta(Ast.MetaFreshIdDecl(name,seed)) in
314 !Data.add_fresh_id_meta name; tok) }
318 { (fun arity name pure check_meta ->
319 let tok = check_meta(Ast.MetaParamDecl(arity,name)) in
320 !Data.add_param_meta name pure; tok) }
322 { (fun arity name pure check_meta ->
323 let tok = check_meta(Ast.MetaParamListDecl(arity,name,None)) in
324 !Data.add_paramlist_meta name None pure; tok) }
326 { (fun arity name pure check_meta ->
327 let tok = check_meta(Ast.MetaExpListDecl(arity,name,None)) in
328 !Data.add_explist_meta name None pure; tok) }
330 { (fun arity name pure check_meta ->
331 let tok = check_meta(Ast.MetaTypeDecl(arity,name)) in
332 !Data.add_type_meta name pure; tok) }
334 { (fun arity name pure check_meta ->
335 let tok = check_meta(Ast.MetaInitDecl(arity,name)) in
336 !Data.add_init_meta name pure; tok) }
338 { (fun arity name pure check_meta ->
339 let tok = check_meta(Ast.MetaStmDecl(arity,name)) in
340 !Data.add_stm_meta name pure; tok) }
342 { (fun arity name pure check_meta ->
343 let tok = check_meta(Ast.MetaStmListDecl(arity,name)) in
344 !Data.add_stmlist_meta name pure; tok) }
346 { (fun arity (_,name) pure check_meta ->
347 if arity = Ast.NONE && pure = Ast0.Impure
348 then (!Data.add_type_name name; [])
349 else raise (Semantic_cocci.Semantic "bad typedef")) }
351 { (fun arity (_,name) pure check_meta ->
352 if arity = Ast.NONE && pure = Ast0.Impure
353 then (!Data.add_declarer_name name; [])
354 else raise (Semantic_cocci.Semantic "bad declarer")) }
356 { (fun arity (_,name) pure check_meta ->
357 if arity = Ast.NONE && pure = Ast0.Impure
358 then (!Data.add_iterator_name name; [])
359 else raise (Semantic_cocci.Semantic "bad iterator")) }
362 %inline metakind_atomic:
364 { (fun arity name pure check_meta constraints ->
365 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
366 !Data.add_id_meta name constraints pure; tok) }
368 { (fun arity name pure check_meta constraints ->
369 let tok = check_meta(Ast.MetaFuncDecl(arity,name)) in
370 !Data.add_func_meta name constraints pure; tok) }
372 { (fun arity name pure check_meta constraints ->
373 let tok = check_meta(Ast.MetaLocalFuncDecl(arity,name)) in
374 !Data.add_local_func_meta name constraints pure;
377 { (fun arity name pure check_meta constraints ->
378 let tok = check_meta(Ast.MetaDeclarerDecl(arity,name)) in
379 !Data.add_declarer_meta name constraints pure; tok) }
381 { (fun arity name pure check_meta constraints ->
382 let tok = check_meta(Ast.MetaIteratorDecl(arity,name)) in
383 !Data.add_iterator_meta name constraints pure; tok) }
385 %inline metakind_atomic_expi:
387 { (fun arity name pure check_meta constraints ->
388 let tok = check_meta(Ast.MetaErrDecl(arity,name)) in
389 !Data.add_err_meta name constraints pure; tok) }
390 | l=option(TLocal) TIdExpression ty=ioption(meta_exp_type)
391 { (fun arity name pure check_meta constraints ->
394 !Data.add_idexp_meta ty name constraints pure;
395 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
397 !Data.add_local_idexp_meta ty name constraints pure;
398 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
399 | l=option(TLocal) TIdExpression m=nonempty_list(TMul)
400 { (fun arity name pure check_meta constraints ->
401 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
404 !Data.add_idexp_meta ty name constraints pure;
405 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
407 !Data.add_local_idexp_meta ty name constraints pure;
408 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
409 | TExpression m=nonempty_list(TMul)
410 { (fun arity name pure check_meta constraints ->
411 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
412 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
413 !Data.add_exp_meta ty name constraints pure; tok) }
414 | vl=meta_exp_type TOCro TCCro
415 { (fun arity name pure check_meta constraints ->
416 let ty = Some (List.map (function x -> Type_cocci.Array x) vl) in
417 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
418 !Data.add_exp_meta ty name constraints pure; tok) }
419 | TConstant ty=ioption(meta_exp_type)
420 { (fun arity name pure check_meta constraints ->
421 let tok = check_meta(Ast.MetaConstDecl(arity,name,ty)) in
422 !Data.add_const_meta ty name constraints pure; tok) }
424 %inline metakind_atomic_expe:
426 { (fun arity name pure check_meta constraints ->
427 let tok = check_meta(Ast.MetaExpDecl(arity,name,None)) in
428 !Data.add_exp_meta None name constraints pure; tok) }
429 | vl=meta_exp_type // no error if use $1 but doesn't type check
430 { (fun arity name pure check_meta constraints ->
434 match Ast0.unwrap c with
439 Type_cocci.BaseType(Type_cocci.IntType) -> true
440 | Type_cocci.BaseType(Type_cocci.ShortType) -> true
441 | Type_cocci.BaseType(Type_cocci.LongType) -> true
444 then failwith "metavariable with int constraint must be an int"
447 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
448 !Data.add_exp_meta ty name constraints pure; tok) }
453 { [Ast0_cocci.ast0_type_to_type t] }
454 | TOBrace t=comma_list(ctype) TCBrace m=list(TMul)
456 (function x -> P.ty_pointerify (Ast0_cocci.ast0_type_to_type x) m)
459 arity: TBang0 { Ast.UNIQUE }
461 | TPlus0 { Ast.MULTI }
462 | /* empty */ { Ast.NONE }
465 q=ctype_qualif_opt ty=Tchar
466 { q (Ast0.wrap(Ast0.BaseType(Ast.CharType,[P.clt2mcode "char" ty]))) }
467 | q=ctype_qualif_opt ty=Tshort
468 { q (Ast0.wrap(Ast0.BaseType(Ast.ShortType,[P.clt2mcode "short" ty])))}
469 | q=ctype_qualif_opt ty=Tint
470 { q (Ast0.wrap(Ast0.BaseType(Ast.IntType,[P.clt2mcode "int" ty]))) }
472 { Ast0.wrap(Ast0.BaseType(Ast.DoubleType,[P.clt2mcode "double" t])) }
474 { Ast0.wrap(Ast0.BaseType(Ast.FloatType,[P.clt2mcode "float" t])) }
475 | q=ctype_qualif_opt ty=Tlong
476 { q (Ast0.wrap(Ast0.BaseType(Ast.LongType,[P.clt2mcode "long" ty]))) }
477 | q=ctype_qualif_opt ty=Tlong ty1=Tlong
481 [P.clt2mcode "long" ty;P.clt2mcode "long" ty1]))) }
483 { Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, i)) }
484 | s=struct_or_union i=ident
485 { Ast0.wrap(Ast0.StructUnionName(s, Some i)) }
486 | s=struct_or_union i=ioption(ident)
487 l=TOBrace d=struct_decl_list r=TCBrace
488 { (if i = None && !Data.in_iso
489 then failwith "structures must be named in the iso file");
490 Ast0.wrap(Ast0.StructUnionDef(Ast0.wrap(Ast0.StructUnionName(s, i)),
492 d, P.clt2mcode "}" r)) }
493 | s=TMetaType l=TOBrace d=struct_decl_list r=TCBrace
494 { let (nm,pure,clt) = s in
496 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) in
498 (Ast0.StructUnionDef(ty,P.clt2mcode "{" l,d,P.clt2mcode "}" r)) }
499 | r=TRuleName TDot p=TIdent
500 { let nm = (r,P.id2name p) in
501 (* this is only possible when we are in a metavar decl. Otherwise,
502 it will be represented already as a MetaType *)
503 let _ = P.check_meta(Ast.MetaTypeDecl(Ast.NONE,nm)) in
504 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm (P.id2clt p),
505 Ast0.Impure (*will be ignored*))) }
507 { Ast0.wrap(Ast0.TypeName(P.id2mcode p)) }
508 | q=ctype_qualif_opt p=TMetaType
509 { let (nm,pure,clt) = p in
510 q (Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure))) }
513 q=ctype_qualif { q None }
514 | generic_ctype_full { $1 }
517 s=Tstruct { P.clt2mcode Ast.Struct s }
518 | u=Tunion { P.clt2mcode Ast.Union u }
522 | t=ctype d=d_ident pv=TPtVirg
524 [Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] }
525 | t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
526 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar pv=TPtVirg
530 (Ast0.FunctionPointer
531 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
532 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
533 [Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] }
534 | cv=ioption(const_vol) i=pure_ident d=d_ident pv=TPtVirg
536 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
537 [Ast0.wrap(Ast0.UnInit(None,fn idtype,id,P.clt2mcode ";" pv))] }
540 struct_decl_list_start { Ast0.wrap(Ast0.DOTS($1)) }
542 struct_decl_list_start:
544 | struct_decl struct_decl_list_start { $1@$2 }
545 | d=edots_when(TEllipsis,struct_decl) r=continue_struct_decl_list
546 { (P.mkddots "..." d)::r }
548 continue_struct_decl_list:
550 | struct_decl struct_decl_list_start { $1@$2 }
554 cv=ioption(const_vol) ty=generic_ctype m=list(TMul)
555 { P.pointerify (P.make_cv cv ty) m }
556 | cv=ioption(const_vol) t=Tvoid m=nonempty_list(TMul)
558 Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" t])) in
559 P.pointerify (P.make_cv cv ty) m }
560 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
562 { let (mids,code) = t in
564 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
567 cv=ioption(const_vol) ty=generic_ctype_full m=list(TMul)
568 { P.pointerify (P.make_cv cv ty) m }
569 | cv=ioption(const_vol) t=Tvoid m=nonempty_list(TMul)
571 Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" t])) in
572 P.pointerify (P.make_cv cv ty) m }
573 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
575 { let (mids,code) = t in
577 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
580 fn_ctype: // allows metavariables
581 ty=generic_ctype m=list(TMul) { P.pointerify ty m }
582 | t=Tvoid m=list(TMul)
584 (Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" t])))
587 %inline ctype_qualif:
589 { function x -> Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,x)) }
591 { function x -> Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,x)) }
593 %inline ctype_qualif_opt:
594 s=ctype_qualif { function x -> s (Some x) }
595 | /* empty */ { function x -> x }
597 /*****************************************************************************/
599 /* have to inline everything to avoid conflicts? switch to proper
600 declarations, statements, and expressions for the subterms */
604 b=loption(minus_start)
605 ew=loption(error_words)
607 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
608 | code -> Top_level.top_level code }
612 b=loption(plus_start)
613 ew=loption(error_words)
614 { Top_level.top_level (f@b@ew) }
619 ew=loption(error_words)
620 { match f@[b]@ew with
621 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
622 | code -> Top_level.top_level code }
627 ew=loption(error_words)
628 { Top_level.top_level (f@[b]@ew) }
633 (Ast0.FILEINFO(P.id2mcode $1,
639 (Ast0.Include(P.clt2mcode "#include" (P.drop_aft (P.id2clt $1)),
640 let (arity,ln,lln,offset,col,strbef,straft,pos) =
643 (arity,ln,lln,offset,0,strbef,straft,pos) in
645 (Ast.Local (Parse_aux.str2inc (P.id2name $1)))
649 (Ast0.Include(P.clt2mcode "#include" (P.drop_aft (P.id2clt $1)),
650 let (arity,ln,lln,offset,col,strbef,straft,pos) =
653 (arity,ln,lln,offset,0,strbef,straft,pos) in
655 (Ast.NonLocal (Parse_aux.str2inc (P.id2name $1)))
657 | d=defineop t=ctype TLineEnd
658 { let ty = Ast0.wrap(Ast0.TopExp(Ast0.wrap(Ast0.TypeExp(t)))) in
659 d (Ast0.wrap(Ast0.DOTS([ty]))) }
660 | defineop b=toplevel_seq_start(toplevel_after_dots) TLineEnd
664 (match Ast0.unwrap e with
666 [Ast0.rewrap e (Ast0.TopExp(Ast0.set_arg_exp (e1)))]
669 $1 (Ast0.wrap(Ast0.DOTS(body))) }
673 { let (clt,ident) = $1 in
677 (P.clt2mcode "#define" clt,
679 TMetaId((nm,constraints,pure,clt)) ->
680 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
682 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
685 (Semantic_cocci.Semantic
686 "unexpected name for a #define")),
687 Ast0.wrap Ast0.NoParams,
689 | TDefineParam define_param_list_option TCPar
690 { let (clt,ident,parenoff) = $1 in
691 let (arity,line,lline,offset,col,strbef,straft,pos) = clt in
694 (arity,line,lline,parenoff,0,[],[],Ast0.NoMetaPos) in
698 (P.clt2mcode "#define" clt,
700 TMetaId((nm,constraints,pure,clt)) ->
701 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
703 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
706 (Semantic_cocci.Semantic
707 "unexpected name for a #define")),
708 Ast0.wrap (Ast0.DParams (lp,$2,P.clt2mcode ")" $3)),body)) }
710 /* ---------------------------------------------------------------------- */
712 define_param_list: define_param_list_start
714 match Ast0.unwrap x with Ast0.DPcircles(_) -> true | _ -> false in
715 if List.exists circle $1
716 then Ast0.wrap(Ast0.CIRCLES($1))
717 else Ast0.wrap(Ast0.DOTS($1)) }
719 define_param_list_start:
720 ident { [Ast0.wrap(Ast0.DParam $1)] }
721 | ident TComma define_param_list_start
722 { Ast0.wrap(Ast0.DParam $1)::
723 Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $2))::$3 }
724 | d=TEllipsis r=list(dp_comma_args(TEllipsis))
725 { (P.mkdpdots "..." d)::
726 (List.concat (List.map (function x -> x (P.mkdpdots "...")) r)) }
728 dp_comma_args(dotter):
730 { function dot_builder ->
731 [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," c)); dot_builder d] }
733 { function dot_builder ->
734 [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $1));
735 Ast0.wrap(Ast0.DParam $2)] }
737 define_param_list_option: define_param_list { $1 }
738 | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
740 /*****************************************************************************/
743 s=ioption(storage) t=ctype
744 id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
749 (Ast0.FunctionType(Some t,
750 P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
751 id, P.clt2mcode ";" pt)) }
752 | s=ioption(storage) t=Tvoid
753 id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
754 { let t = Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" t])) in
759 (Ast0.FunctionType(Some t,
760 P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
761 id, P.clt2mcode ";" pt)) }
766 TFunDecl i=func_ident lp=TOPar d=decl_list(decl) rp=TCPar
767 lb=TOBrace b=fun_start rb=TCBrace
768 { Ast0.wrap(Ast0.FunDecl((Ast0.default_info(),Ast0.context_befaft()),
770 P.clt2mcode "(" lp, d,
772 P.clt2mcode "{" lb, b,
773 P.clt2mcode "}" rb)) }
780 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
781 raise (Semantic_cocci.Semantic "duplicate storage")
782 with Not_found -> (Ast0.FStorage($1))::$2 }
783 | t=fn_ctype r=fninfo_nt { (Ast0.FType(t))::r }
786 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
787 raise (Semantic_cocci.Semantic "duplicate inline")
788 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
791 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
792 raise (Semantic_cocci.Semantic "multiple attributes")
793 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
800 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
801 raise (Semantic_cocci.Semantic "duplicate storage")
802 with Not_found -> (Ast0.FStorage($1))::$2 }
805 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
806 raise (Semantic_cocci.Semantic "duplicate inline")
807 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
810 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
811 raise (Semantic_cocci.Semantic "duplicate init")
812 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
815 s=Tstatic { P.clt2mcode Ast.Static s }
816 | s=Tauto { P.clt2mcode Ast.Auto s }
817 | s=Tregister { P.clt2mcode Ast.Register s }
818 | s=Textern { P.clt2mcode Ast.Extern s }
820 decl: t=ctype i=ident
821 { Ast0.wrap(Ast0.Param(t, Some i)) }
822 | t=fn_ctype lp=TOPar s=TMul i=ident rp=TCPar
823 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
826 (Ast0.FunctionPointer
827 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
828 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
829 Ast0.wrap(Ast0.Param(fnptr, Some i)) }
832 Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" t])) in
833 Ast0.wrap(Ast0.VoidParam(ty)) }
835 { let (nm,pure,clt) = $1 in
836 Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) }
840 | t=ctype { Ast0.wrap(Ast0.Param(t, None)) }
841 | t=fn_ctype lp=TOPar s=TMul rp=TCPar
842 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
845 (Ast0.FunctionPointer
846 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
847 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
848 Ast0.wrap(Ast0.Param(fnptr, None)) }
851 Tconst { P.clt2mcode Ast.Const $1 }
852 | Tvolatile { P.clt2mcode Ast.Volatile $1 }
854 /*****************************************************************************/
857 includes { $1 } /* shouldn't be allowed to be a single_statement... */
862 | TIf TOPar eexpr TCPar single_statement %prec TIf
863 { P.ifthen $1 $2 $3 $4 $5 }
864 | TIf TOPar eexpr TCPar single_statement TElse single_statement
865 { P.ifthenelse $1 $2 $3 $4 $5 $6 $7 }
866 | TFor TOPar option(eexpr) TPtVirg option(eexpr) TPtVirg
867 option(eexpr) TCPar single_statement
868 { P.forloop $1 $2 $3 $4 $5 $6 $7 $8 $9 }
869 | TWhile TOPar eexpr TCPar single_statement
870 { P.whileloop $1 $2 $3 $4 $5 }
871 | TDo single_statement TWhile TOPar eexpr TCPar TPtVirg
872 { P.doloop $1 $2 $3 $4 $5 $6 $7 }
873 | iter_ident TOPar eexpr_list_option TCPar single_statement
874 { P.iterator $1 $2 $3 $4 $5 }
875 | TSwitch TOPar eexpr TCPar TOBrace list(case_line) TCBrace
876 { P.switch $1 $2 $3 $4 $5 $6 $7 }
877 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
878 | TReturn TPtVirg { P.ret $1 $2 }
879 | TBreak TPtVirg { P.break $1 $2 }
880 | TContinue TPtVirg { P.cont $1 $2 }
881 | ident TDotDot { P.label $1 $2 }
882 | TGoto ident TPtVirg { P.goto $1 $2 $3 }
883 | TOBrace fun_start TCBrace
887 TEllipsis w=list(whenppdecs)
888 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." $1, List.concat w)) }
889 | TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
890 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." $1, b,
891 P.clt2mcode "...>" c, List.concat w, false)) }
892 | TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
893 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." $1, b,
894 P.clt2mcode "...+>" c, List.concat w, true)) }
896 %inline stm_dots_ell:
897 a=TEllipsis w=list(whenppdecs)
898 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." a, List.concat w)) }
900 %inline stm_dots_nest:
901 a=TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
902 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." a, b,
903 P.clt2mcode "...>" c, List.concat w, false)) }
904 | a=TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
905 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." a, b,
906 P.clt2mcode "...+>" c, List.concat w, true)) }
908 whenppdecs: w=whens(when_start,rule_elem_statement)
911 /* a statement that fits into a single rule_elem. should nests be included?
912 what about statement metavariables? */
915 { Ast0.wrap(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),$1)) }
916 | expr TPtVirg { P.exp_stm $1 $2 }
917 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
918 | TReturn TPtVirg { P.ret $1 $2 }
919 | TBreak TPtVirg { P.break $1 $2 }
920 | TContinue TPtVirg { P.cont $1 $2 }
921 | TOPar0 midzero_list(rule_elem_statement,rule_elem_statement) TCPar0
922 { let (mids,code) = $2 in
924 (Ast0.Disj(P.clt2mcode "(" $1,
925 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
926 mids, P.clt2mcode ")" $3)) }
928 /* a statement on its own */
931 | TOPar0 midzero_list(statement,statement) TCPar0
932 /* degenerate case, elements are single statements and thus don't
934 { let (mids,code) = $2 in
936 (Ast0.Disj(P.clt2mcode "(" $1,
937 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
938 mids, P.clt2mcode ")" $3)) }
941 TDefault TDotDot fun_start
942 { Ast0.wrap(Ast0.Default(P.clt2mcode "default" $1,P.clt2mcode ":" $2,$3)) }
943 | TCase eexpr TDotDot fun_start
944 { Ast0.wrap(Ast0.Case(P.clt2mcode "case" $1,$2,P.clt2mcode ":" $3,$4)) }
946 /* In the following, an identifier as a type is not fully supported. Indeed,
947 the language is ambiguous: what is foo * bar; */
948 /* The AST DisjDecl cannot be generated because it would be ambiguous with
949 a disjunction on a statement with a declaration in each branch */
952 { [Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv))] }
953 | s=ioption(storage) t=ctype d=comma_list(d_ident) pv=TPtVirg
956 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)))
959 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
961 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
962 /* type is a typedef name */
963 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
964 d=comma_list(d_ident) pv=TPtVirg
968 P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
969 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)))
971 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
972 e=initialize pv=TPtVirg
974 !Data.add_type_name (P.id2name i);
975 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
976 [Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
977 P.clt2mcode ";" pv))] }
978 /* function pointer type */
980 t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
981 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
986 (Ast0.FunctionPointer
987 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
988 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
989 [Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv))] }
990 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
991 { [Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
992 P.clt2mcode ")" $4,P.clt2mcode ";" $5))] }
994 t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
995 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
996 q=TEq e=initialize pv=TPtVirg
1000 (Ast0.FunctionPointer
1001 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1002 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1003 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
1004 | s=Ttypedef t=ctype_full id=typedef_ident pv=TPtVirg
1005 { let s = P.clt2mcode "typedef" s in
1006 [Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv))] }
1010 { Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv)) }
1011 | s=ioption(storage) t=ctype d=d_ident pv=TPtVirg
1012 { let (id,fn) = d in
1013 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1015 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
1016 { let (id,fn) = d in
1017 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv)) }
1018 /* type is a typedef name */
1019 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
1020 d=d_ident pv=TPtVirg
1021 { let (id,fn) = d in
1022 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1023 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)) }
1024 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
1025 e=initialize pv=TPtVirg
1026 { let (id,fn) = d in
1027 !Data.add_type_name (P.id2name i);
1028 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1029 Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
1030 P.clt2mcode ";" pv)) }
1031 /* function pointer type */
1032 | s=ioption(storage)
1033 t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1034 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1036 { let (id,fn) = d in
1039 (Ast0.FunctionPointer
1040 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1041 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1042 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1043 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
1044 { Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
1045 P.clt2mcode ")" $4,P.clt2mcode ";" $5)) }
1046 | s=ioption(storage)
1047 t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1048 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1049 q=TEq e=initialize pv=TPtVirg
1050 { let (id,fn) = d in
1053 (Ast0.FunctionPointer
1054 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1055 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1056 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))}
1060 ident list(array_dec)
1064 (function (l,i,r) ->
1067 (Ast0.Array(rest,P.clt2mcode "[" l,i,P.clt2mcode "]" r)))
1070 array_dec: l=TOCro i=option(eexpr) r=TCCro { (l,i,r) }
1074 { Ast0.wrap(Ast0.InitExpr($1)) }
1075 | TOBrace initialize_list TCBrace
1076 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1079 (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []),
1080 P.clt2mcode "}" $2)) }
1082 {let (nm,pure,clt) = $1 in
1083 Ast0.wrap(Ast0.MetaInit(P.clt2mcode nm clt,pure)) }
1086 /*arithexpr and not eexpr because can have ambiguity with comma*/
1087 /*dots and nests probably not allowed at top level, haven't looked into why*/
1088 arith_expr(eexpr,invalid) { Ast0.wrap(Ast0.InitExpr($1)) }
1089 | TOBrace initialize_list TCBrace
1090 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1093 (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []),
1094 P.clt2mcode "}" $2)) }
1095 /* gccext:, labeled elements */
1096 | list(designator) TEq initialize2
1097 { Ast0.wrap(Ast0.InitGccExt($1,P.clt2mcode "=" $2,$3)) }
1098 | ident TDotDot initialize2
1099 { Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */
1103 { Ast0.DesignatorField (P.clt2mcode "." $1,$2) }
1105 { Ast0.DesignatorIndex (P.clt2mcode "[" $1,$2,P.clt2mcode "]" $3) }
1106 | TOCro eexpr TEllipsis eexpr TCCro
1107 { Ast0.DesignatorRange (P.clt2mcode "[" $1,$2,P.clt2mcode "..." $3,
1108 $4,P.clt2mcode "]" $5) }
1111 initialize_list_start { Ast0.wrap(Ast0.DOTS($1)) }
1113 initialize_list_start:
1114 initialize2 TComma { [$1;Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))] }
1115 | initialize2 TComma initialize_list_start
1116 { $1::Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))::$3 }
1117 | d=edots_when(TEllipsis,initialize)
1118 r=comma_initializers(edots_when(TEllipsis,initialize))
1119 { (P.mkidots "..." d)::
1120 (List.concat(List.map (function x -> x (P.mkidots "...")) r)) }
1122 comma_initializers(dotter):
1124 | d=dotter r=comma_initializers2(dotter)
1125 { (function dot_builder -> [dot_builder d])::r }
1126 | i=initialize2 c=TComma r=comma_initializers(dotter)
1127 { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
1130 comma_initializers2(dotter):
1132 | i=initialize2 c=TComma r=comma_initializers(dotter)
1133 { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
1136 /* a statement that is part of a list */
1139 { let (nm,pure,clt) = $1 in
1140 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1145 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1147 | statement { [$1] }
1148 /* this doesn't allow expressions at top level, because the parser doesn't
1149 know whether there is one. If there is one, this is not sequencible.
1150 If there is not one, then it is. It seems complicated to get around
1151 this at the parser level. We would have to have a check afterwards to
1152 allow this. One case where this would be useful is for a when. Now
1153 we allow a sequence of whens, so one can be on only statements and
1154 one can be on only expressions. */
1155 | TOPar0 t=midzero_list(fun_start,fun_start) TCPar0
1156 { let (mids,code) = t in
1159 match Ast0.unwrap x with Ast0.DOTS([]) -> true | _ -> false)
1163 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, code, mids,
1164 P.clt2mcode ")" $3))] }
1166 /* a statement that is part of a list */
1167 decl_statement_expr:
1169 { let (nm,pure,clt) = $1 in
1170 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1175 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1177 | statement { [$1] }
1178 /* this doesn't allow expressions at top level, because the parser doesn't
1179 know whether there is one. If there is one, this is not sequencible.
1180 If there is not one, then it is. It seems complicated to get around
1181 this at the parser level. We would have to have a check afterwards to
1182 allow this. One case where this would be useful is for a when. Now
1183 we allow a sequence of whens, so one can be on only statements and
1184 one can be on only expressions. */
1185 | TOPar0 t=midzero_list(fun_after_stm,fun_after_dots_or) TCPar0
1186 { let (mids,code) = t in
1187 if List.for_all (function [] -> true | _ -> false) code
1191 List.map (function x -> Ast0.wrap(Ast0.DOTS x)) code in
1192 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, dot_code, mids,
1193 P.clt2mcode ")" $3))] }
1195 /*****************************************************************************/
1197 /* The following cannot contain <... ...> at the top level. This can only
1198 be allowed as an expression when the expression is delimited on both sides
1199 by expression-specific markers. In that case, the rule eexpr is used, which
1200 allows <... ...> anywhere. Hopefully, this will not be too much of a problem
1202 expr: basic_expr(expr,invalid) { $1 }
1203 /* allows ... and nests */
1204 eexpr: basic_expr(eexpr,dot_expressions) { $1 }
1205 /* allows nests but not .... */
1206 dexpr: basic_expr(eexpr,nest_expressions) { $1 }
1209 eexpr { Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))) }
1212 TInvalid { raise (Semantic_cocci.Semantic "not matchable") }
1215 TEllipsis { Ast0.wrap(Ast0.Edots(P.clt2mcode "..." $1,None)) }
1216 | nest_expressions { $1 }
1218 /* not clear what whencode would mean, so just drop it */
1220 TOEllipsis e=expr_dots(TEllipsis) c=TCEllipsis
1221 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<..." $1,
1222 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1223 P.clt2mcode "...>" c, None, false)) }
1224 | TPOEllipsis e=expr_dots(TEllipsis) c=TPCEllipsis
1225 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<+..." $1,
1226 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1227 P.clt2mcode "...+>" c, None, true)) }
1229 //whenexp: TWhen TNotEq w=eexpr TLineEnd { w }
1231 basic_expr(recurser,primary_extra):
1232 assign_expr(recurser,primary_extra) { $1 }
1235 cond_expr(r,pe) { $1 }
1236 | unary_expr(r,pe) TAssign assign_expr_bis
1237 { let (op,clt) = $2 in
1238 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1239 Ast0.set_arg_exp $3,false)) }
1240 | unary_expr(r,pe) TEq assign_expr_bis
1243 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1246 cond_expr(eexpr,dot_expressions) { $1 }
1247 | unary_expr(eexpr,dot_expressions) TAssign assign_expr_bis
1248 { let (op,clt) = $2 in
1249 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1250 Ast0.set_arg_exp $3,false)) }
1251 | unary_expr(eexpr,dot_expressions) TEq assign_expr_bis
1254 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1257 arith_expr(r,pe) { $1 }
1258 | l=arith_expr(r,pe) w=TWhy t=option(eexpr) dd=TDotDot r=cond_expr(r,pe)
1259 { Ast0.wrap(Ast0.CondExpr (l, P.clt2mcode "?" w, t,
1260 P.clt2mcode ":" dd, r)) }
1263 cast_expr(r,pe) { $1 }
1264 | arith_expr(r,pe) TMul arith_expr(r,pe)
1265 { P.arith_op Ast.Mul $1 $2 $3 }
1266 | arith_expr(r,pe) TDmOp arith_expr(r,pe)
1267 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1268 | arith_expr(r,pe) TPlus arith_expr(r,pe)
1269 { P.arith_op Ast.Plus $1 $2 $3 }
1270 | arith_expr(r,pe) TMinus arith_expr(r,pe)
1271 { P.arith_op Ast.Minus $1 $2 $3 }
1272 | arith_expr(r,pe) TShOp arith_expr(r,pe)
1273 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1274 | arith_expr(r,pe) TLogOp arith_expr(r,pe)
1275 { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
1276 | arith_expr(r,pe) TEqEq arith_expr(r,pe)
1277 { P.logic_op Ast.Eq $1 $2 $3 }
1278 | arith_expr(r,pe) TNotEq arith_expr(r,pe)
1279 { P.logic_op Ast.NotEq $1 $2 $3 }
1280 | arith_expr(r,pe) TAnd arith_expr(r,pe)
1281 { P.arith_op Ast.And $1 $2 $3 }
1282 | arith_expr(r,pe) TOr arith_expr(r,pe)
1283 { P.arith_op Ast.Or $1 $2 $3 }
1284 | arith_expr(r,pe) TXor arith_expr(r,pe)
1285 { P.arith_op Ast.Xor $1 $2 $3 }
1286 | arith_expr(r,pe) TAndLog arith_expr(r,pe)
1287 { P.logic_op Ast.AndLog $1 $2 $3 }
1288 | arith_expr(r,pe) TOrLog arith_expr(r,pe)
1289 { P.logic_op Ast.OrLog $1 $2 $3 }
1292 unary_expr(r,pe) { $1 }
1293 | lp=TOPar t=ctype rp=TCPar e=cast_expr(r,pe)
1294 { Ast0.wrap(Ast0.Cast (P.clt2mcode "(" lp, t,
1295 P.clt2mcode ")" rp, e)) }
1298 postfix_expr(r,pe) { $1 }
1299 | TInc unary_expr(r,pe)
1300 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
1301 | TDec unary_expr(r,pe)
1302 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
1303 | unary_op cast_expr(r,pe)
1304 { let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
1305 | TBang unary_expr(r,pe)
1306 { let mcode = P.clt2mcode Ast.Not $1 in
1307 Ast0.wrap(Ast0.Unary($2, mcode)) }
1308 | TSizeof unary_expr(r,pe)
1309 { Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
1310 | s=TSizeof lp=TOPar t=ctype rp=TCPar
1311 { Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
1312 P.clt2mcode "(" lp,t,
1313 P.clt2mcode ")" rp)) }
1315 unary_op: TAnd { P.clt2mcode Ast.GetRef $1 }
1316 | TMul { P.clt2mcode Ast.DeRef $1 }
1317 | TPlus { P.clt2mcode Ast.UnPlus $1 }
1318 | TMinus { P.clt2mcode Ast.UnMinus $1 }
1319 | TTilde { P.clt2mcode Ast.Tilde $1 }
1322 primary_expr(r,pe) { $1 }
1323 | postfix_expr(r,pe) TOCro eexpr TCCro
1324 { Ast0.wrap(Ast0.ArrayAccess ($1,P.clt2mcode "[" $2,$3,
1325 P.clt2mcode "]" $4)) }
1326 | postfix_expr(r,pe) TDot ident
1327 { Ast0.wrap(Ast0.RecordAccess($1, P.clt2mcode "." $2, $3)) }
1328 | postfix_expr(r,pe) TPtrOp ident
1329 { Ast0.wrap(Ast0.RecordPtAccess($1, P.clt2mcode "->" $2,
1331 | postfix_expr(r,pe) TInc
1332 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Inc $2)) }
1333 | postfix_expr(r,pe) TDec
1334 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Dec $2)) }
1335 | postfix_expr(r,pe) TOPar eexpr_list_option TCPar
1336 { Ast0.wrap(Ast0.FunCall($1,P.clt2mcode "(" $2,
1338 P.clt2mcode ")" $4)) }
1340 primary_expr(recurser,primary_extra):
1341 func_ident { Ast0.wrap(Ast0.Ident($1)) }
1343 { let (x,clt) = $1 in
1344 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1346 { let (x,clt) = $1 in
1347 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Float x) clt)) }
1349 { let (x,clt) = $1 in
1350 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.String x) clt)) }
1352 { let (x,clt) = $1 in
1353 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Char x) clt)) }
1355 { let (nm,constraints,pure,ty,clt) = $1 in
1357 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
1359 { let (nm,constraints,pure,clt) = $1 in
1360 Ast0.wrap(Ast0.MetaErr(P.clt2mcode nm clt,constraints,pure)) }
1362 { let (nm,constraints,pure,ty,clt) = $1 in
1364 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
1366 { let (nm,constraints,pure,ty,clt) = $1 in
1368 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
1370 { let (nm,constraints,pure,ty,clt) = $1 in
1372 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.LocalID,pure)) }
1374 { Ast0.wrap(Ast0.Paren(P.clt2mcode "(" $1,$2,
1375 P.clt2mcode ")" $3)) }
1376 | TOPar0 midzero_list(recurser,eexpr) TCPar0
1377 { let (mids,code) = $2 in
1378 Ast0.wrap(Ast0.DisjExpr(P.clt2mcode "(" $1,
1380 P.clt2mcode ")" $3)) }
1381 | primary_extra { $1 }
1384 r=no_dot_start_end(dexpr,edots_when(dotter,eexpr)) { r }
1387 no_dot_start_end(grammar,dotter):
1388 g=grammar dg=list(pair(dotter,grammar))
1389 { function dot_builder ->
1390 g :: (List.concat(List.map (function (d,g) -> [dot_builder d;g]) dg)) }
1392 /*****************************************************************************/
1398 TRuleName TDot pure_ident { (Some $1,P.id2name $3) }
1400 pure_ident_or_meta_ident:
1401 pure_ident { (None,P.id2name $1) }
1403 | Tlist { (None,"list") }
1404 | TError { (None,"error") }
1405 | TType { (None,"type") }
1406 | TName { (None,"name") }
1408 pure_ident_or_meta_ident_with_seed:
1409 pure_ident_or_meta_ident { ($1,None) }
1410 | pure_ident_or_meta_ident TEq s=TString { ($1,Some (P.id2name s)) }
1412 pure_ident_or_meta_ident_with_not_eq(not_eq):
1413 i=pure_ident_or_meta_ident l=loption(not_eq) { (i,l) }
1418 then failwith "constraints not allowed in iso file");
1419 (if !Data.in_generating
1420 (* pb: constraints not stored with metavars; too lazy to search for
1421 them in the pattern *)
1422 then failwith "constraints not allowed in a generated rule file");
1423 [Ast0.wrap(Ast0.Id(P.id2mcode i))] }
1424 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1426 then failwith "constraints not allowed in iso file");
1427 (if !Data.in_generating
1428 then failwith "constraints not allowed in a generated rule file");
1429 List.map (function i -> Ast0.wrap(Ast0.Id(P.id2mcode i))) l }
1434 then failwith "constraints not allowed in iso file");
1435 (if !Data.in_generating
1436 then failwith "constraints not allowed in a generated rule file");
1437 [Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))] }
1438 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1440 then failwith "constraints not allowed in iso file");
1441 (if !Data.in_generating
1442 then failwith "constraints not allowed in a generated rule file");
1445 Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))))
1449 TNotEq i=ident_or_const
1451 then failwith "constraints not allowed in iso file");
1452 (if !Data.in_generating
1453 then failwith "constraints not allowed in a generated rule file");
1455 | TNotEq TOBrace l=comma_list(ident_or_const) TCBrace
1457 then failwith "constraints not allowed in iso file");
1458 (if !Data.in_generating
1459 then failwith "constraints not allowed in a generated rule file");
1463 i=pure_ident { Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))) }
1465 { let (x,clt) = $1 in
1466 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1471 then failwith "constraints not allowed in iso file");
1472 (if !Data.in_generating
1473 then failwith "constraints not allowed in a generated rule file");
1475 (None,_) -> 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));
1480 | TNotEq TOBrace l=comma_list(meta_ident) TCBrace
1482 then failwith "constraints not allowed in iso file");
1483 (if !Data.in_generating
1484 then failwith "constraints not allowed in a generated rule file");
1488 failwith "constraint must be an inherited variable"
1489 | (Some rule,name) ->
1490 let i = (rule,name) in
1491 P.check_meta(Ast.MetaPosDecl(Ast.NONE,i));
1495 func_ident: pure_ident
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)) }
1501 { let (nm,constraints,pure,clt) = $1 in
1502 Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
1504 { let (nm,constraints,pure,clt) = $1 in
1506 (Ast0.MetaLocalFunc(P.clt2mcode nm clt,constraints,pure)) }
1509 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1511 { let (nm,constraints,pure,clt) = $1 in
1512 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1516 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1518 { let (nm,constraints,pure,clt) = $1 in
1519 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1523 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1525 { let (nm,constraints,pure,clt) = $1 in
1526 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1530 { Ast0.wrap(Ast0.TypeName(P.id2mcode $1)) }
1532 { let (nm,pure,clt) = $1 in
1533 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
1535 /*****************************************************************************/
1538 /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
1539 | decl_list_start(decl)
1541 match Ast0.unwrap x with Ast0.Pcircles(_) -> true | _ -> false in
1542 if List.exists circle $1
1543 then Ast0.wrap(Ast0.CIRCLES($1))
1544 else Ast0.wrap(Ast0.DOTS($1)) }
1546 decl_list_start(decl):
1547 one_dec(decl) { [$1] }
1548 | one_dec(decl) TComma decl_list_start(decl)
1549 { $1::Ast0.wrap(Ast0.PComma(P.clt2mcode "," $2))::$3 }
1550 | TEllipsis list(comma_decls(TEllipsis,decl))
1551 { Ast0.wrap(Ast0.Pdots(P.clt2mcode "..." $1))::
1552 (List.concat(List.map (function x -> x (P.mkpdots "...")) $2)) }
1557 { let (nm,lenname,pure,clt) = $1 in
1558 let nm = P.clt2mcode nm clt in
1561 Some nm -> Some(P.clt2mcode nm clt)
1563 Ast0.wrap(Ast0.MetaParamList(nm,lenname,pure)) }
1565 comma_decls(dotter,decl):
1567 { function dot_builder ->
1568 [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1));
1570 | TComma one_dec(decl)
1571 { function dot_builder ->
1572 [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1)); $2] }
1574 /* ---------------------------------------------------------------------- */
1577 TError TWords TEq TOCro cl=comma_list(dexpr) TCCro
1578 { [Ast0.wrap(Ast0.ERRORWORDS(cl))] }
1580 /* ---------------------------------------------------------------------- */
1581 /* sequences of statements and expressions */
1583 /* There are number of cases that must be considered:
1586 Dots and nests allowed at the beginning or end
1587 Expressions allowed at the beginning or end
1588 One function allowed, by itself
1590 Dots and nests allowed at the beginning or end
1591 Expressions not allowed at the beginning or end
1592 Functions not allowed
1593 3. The body of a nest:
1594 Dots and nests not allowed at the beginning or end
1595 Expressions allowed at the beginning or end
1596 Functions not allowed
1598 Dots and nests not allowed at the beginning but allowed at the end
1599 Expressions allowed at the beginning or end
1600 Functions not allowed
1602 These are implemented by the rules minus_toplevel_sequence,
1603 plus_toplevel_sequence, function_body_sequence, nest_body_sequence, and
1606 /* ------------------------------------------------------------------------ */
1607 /* Minus top level */
1609 /* doesn't allow only ... */
1611 fundecl { [Ast0.wrap(Ast0.DECL($1))] }
1612 | ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1613 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1614 | toplevel_seq_startne(toplevel_after_dots_init)
1615 { List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1 }
1617 toplevel_seq_startne(after_dots_init):
1618 a=stm_dots_ell b=after_dots_init { a::b }
1619 | a=stm_dots_nest b=after_dots_init { a::b }
1620 | a=stm_dots_nest { [a] }
1621 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1622 | decl_statement_expr toplevel_after_stm { $1@$2 }
1624 toplevel_seq_start(after_dots_init):
1625 stm_dots after_dots_init { $1::$2 }
1626 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1627 | decl_statement_expr toplevel_after_stm { $1@$2 }
1629 toplevel_after_dots_init:
1630 TNothing toplevel_after_exp {$2}
1631 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1632 | decl_statement_expr toplevel_after_stm {$1@$2}
1636 | stm_dots toplevel_after_dots {$1::$2}
1638 toplevel_after_dots:
1640 | TNothing toplevel_after_exp {$2}
1641 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1642 | decl_statement_expr toplevel_after_stm {$1@$2}
1646 | stm_dots toplevel_after_dots {$1::$2}
1647 | decl_statement toplevel_after_stm {$1@$2}
1650 TOInit initialize_list TCBrace
1651 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1653 /* ------------------------------------------------------------------------ */
1654 /* Plus top level */
1656 /* does allow only ... also allows multiple top-level functions */
1658 ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1659 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1660 | stm_dots plus_after_dots
1661 { (Ast0.wrap(Ast0.OTHER($1)))::$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 }
1674 | TNothing plus_after_exp {$2}
1675 | expr plus_after_exp
1676 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1677 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1678 | decl_statement_expr plus_after_stm
1679 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1683 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1684 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1685 | decl_statement plus_after_stm
1686 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1688 /* ------------------------------------------------------------------------ */
1692 fun_after_stm { Ast0.wrap(Ast0.DOTS($1)) }
1696 | stm_dots fun_after_dots {$1::$2}
1697 | decl_statement fun_after_stm {$1@$2}
1701 | TNothing fun_after_exp {$2}
1702 | expr fun_after_exp {Ast0.wrap(Ast0.Exp($1))::$2}
1703 | decl_statement_expr fun_after_stm {$1@$2}
1706 stm_dots fun_after_dots {$1::$2}
1708 /* hack to allow mixing statements and expressions in an or */
1711 | TNothing fun_after_exp_or {$2}
1712 | expr fun_after_exp_or {Ast0.wrap(Ast0.Exp($1))::$2}
1713 | decl_statement_expr fun_after_stm {$1@$2}
1717 | stm_dots fun_after_dots {$1::$2}
1719 /* ------------------------------------------------------------------------ */
1723 nest_after_dots { Ast0.wrap(Ast0.DOTS($1)) }
1726 decl_statement_expr nest_after_stm {$1@$2}
1727 | TNothing nest_after_exp {$2}
1728 | expr nest_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1732 | stm_dots nest_after_dots {$1::$2}
1733 | decl_statement nest_after_stm {$1@$2}
1737 | stm_dots nest_after_dots {$1::$2}
1739 /* ------------------------------------------------------------------------ */
1743 expr toplevel_after_exp
1744 { Ast0.wrap(Ast0.DOTS((Ast0.wrap(Ast0.Exp($1)))::$2)) }
1745 | decl_statement toplevel_after_stm
1746 { Ast0.wrap(Ast0.DOTS($1@$2)) }
1748 /* ---------------------------------------------------------------------- */
1753 match Ast0.unwrap x with Ast0.Ecircles(_) -> true | _ -> false in
1755 match Ast0.unwrap x with Ast0.Estars(_) -> true | _ -> false in
1756 if List.exists circle $1
1757 then Ast0.wrap(Ast0.CIRCLES($1))
1759 if List.exists star $1
1760 then Ast0.wrap(Ast0.STARS($1))
1761 else Ast0.wrap(Ast0.DOTS($1)) }
1763 /* arg expr. may contain a type or a explist metavariable */
1766 { Ast0.set_arg_exp $1 }
1768 { let (nm,lenname,pure,clt) = $1 in
1769 let nm = P.clt2mcode nm clt in
1772 Some nm -> Some(P.clt2mcode nm clt)
1774 Ast0.wrap(Ast0.MetaExprList(nm,lenname,pure)) }
1776 { Ast0.set_arg_exp(Ast0.wrap(Ast0.TypeExp($1))) }
1780 | aexpr TComma eexpr_list_start
1781 { $1::Ast0.wrap(Ast0.EComma(P.clt2mcode "," $2))::$3 }
1785 { function dot_builder ->
1786 [Ast0.wrap(Ast0.EComma(P.clt2mcode "," c)); dot_builder d] }
1788 { function dot_builder ->
1789 [Ast0.wrap(Ast0.EComma(P.clt2mcode "," $1)); $2] }
1791 eexpr_list_option: eexpr_list { $1 }
1792 | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
1794 /****************************************************************************/
1796 // non-empty lists - drop separator
1798 separated_nonempty_list(TComma,elem) { $1 }
1800 midzero_list(elem,aft):
1801 a=elem b=list(mzl(aft))
1802 { let (mids,code) = List.split b in (mids,(a::code)) }
1805 a=TMid0 b=elem { (P.clt2mcode "|" a, b) }
1807 edots_when(dotter,when_grammar):
1808 d=dotter { (d,None) }
1809 | d=dotter TWhen TNotEq w=when_grammar TLineEnd { (d,Some w) }
1811 whens(when_grammar,simple_when_grammar):
1812 TWhen TNotEq w=when_grammar TLineEnd { [Ast0.WhenNot w] }
1813 | TWhen TEq w=simple_when_grammar TLineEnd { [Ast0.WhenAlways w] }
1814 | TWhen comma_list(any_strict) TLineEnd
1815 { List.map (function x -> Ast0.WhenModifier(x)) $2 }
1816 | TWhenTrue TNotEq e = eexpr TLineEnd { [Ast0.WhenNotTrue e] }
1817 | TWhenFalse TNotEq e = eexpr TLineEnd { [Ast0.WhenNotFalse e] }
1820 TAny { Ast.WhenAny }
1821 | TStrict { Ast.WhenStrict }
1822 | TForall { Ast.WhenForall }
1823 | TExists { Ast.WhenExists }
1825 /*****************************************************************************
1828 *****************************************************************************/
1831 TIsoExpression e1=dexpr el=list(iso(dexpr)) EOF
1832 { P.iso_adjust (function x -> Ast0.ExprTag x) e1 el }
1833 | TIsoArgExpression e1=dexpr el=list(iso(dexpr)) EOF
1834 { P.iso_adjust (function x -> Ast0.ArgExprTag x) e1 el }
1835 | TIsoTestExpression e1=dexpr el=list(iso(dexpr)) EOF
1836 { P.iso_adjust (function x -> Ast0.TestExprTag x) e1 el }
1837 | TIsoStatement s1=single_statement sl=list(iso(single_statement)) EOF
1838 { P.iso_adjust (function x -> Ast0.StmtTag x) s1 sl }
1839 | TIsoType t1=ctype tl=list(iso(ctype)) EOF
1840 { P.iso_adjust (function x -> Ast0.TypeCTag x) t1 tl }
1841 | TIsoTopLevel e1=nest_start el=list(iso(nest_start)) EOF
1842 { P.iso_adjust (function x -> Ast0.DotsStmtTag x) e1 el }
1843 | TIsoDeclaration d1=decl_var dl=list(iso(decl_var)) EOF
1844 { let check_one = function
1848 (Semantic_cocci.Semantic
1849 "only one variable per declaration in an isomorphism rule") in
1850 let d1 = check_one d1 in
1854 Common.Left x -> Common.Left(check_one x)
1855 | Common.Right x -> Common.Right(check_one x))
1857 P.iso_adjust (function x -> Ast0.DeclTag x) d1 dl }
1860 TIso t=term { Common.Left t }
1861 | TRightIso t=term { Common.Right t }
1863 /*****************************************************************************
1866 *****************************************************************************/
1868 never_used: TPragma { () }
1869 | TPArob TMetaPos { () }
1870 | TScriptData { () }
1872 script_meta_main: py=pure_ident TShOp TRuleName TDot cocci=pure_ident TMPtVirg
1873 { (P.id2name py, ($3, P.id2name cocci)) }