2 * Copyright 2005-2010, Ecole des Mines de Nantes, University of Copenhagen
3 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
4 * This file is part of Coccinelle.
6 * Coccinelle is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, according to version 2 of the License.
10 * Coccinelle is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
18 * The authors reserve the right to distribute this or future versions of
19 * Coccinelle under other licenses.
24 * Copyright 2005-2010, Ecole des Mines de Nantes, University of Copenhagen
25 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
26 * This file is part of Coccinelle.
28 * Coccinelle is free software: you can redistribute it and/or modify
29 * it under the terms of the GNU General Public License as published by
30 * the Free Software Foundation, according to version 2 of the License.
32 * Coccinelle is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 * GNU General Public License for more details.
37 * You should have received a copy of the GNU General Public License
38 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
40 * The authors reserve the right to distribute this or future versions of
41 * Coccinelle under other licenses.
47 (* Not clear how to allow function declarations to specify a return type
48 and how to allow both to be specified as static, because they are in
49 different rules. The rules seem to have to be combined, which would allow
50 functions to be declared as local variables *)
52 (* Not clear how to let a function have a parameter of type void. At the
53 moment, void is allowed to be the type of a variable, which is wrong, and a
54 parameter needs both a type and an identifier *)
55 module Ast0 = Ast0_cocci
56 module Ast = Ast_cocci
62 %token TIdentifier TExpression TStatement TFunction TLocal TType TParameter
63 %token TIdExpression TInitialiser
64 %token Tlist TFresh TConstant TError TWords TWhy0 TPlus0 TBang0
65 %token TPure TContext TGenerated
66 %token TTypedef TDeclarer TIterator TName TPosition TPosAny
67 %token TUsing TDisable TExtends TDepends TOn TEver TNever TExists TForall
68 %token TScript TInitialize TFinalize TNothing TVirtual
69 %token<string> TRuleName
71 %token<Data.clt> Tchar Tshort Tint Tdouble Tfloat Tlong
72 %token<Data.clt> Tvoid Tstruct Tunion Tenum
73 %token<Data.clt> Tunsigned Tsigned
75 %token<Data.clt> Tstatic Tauto Tregister Textern Tinline Ttypedef
76 %token<Data.clt> Tconst Tvolatile
77 %token<string * Data.clt> Tattr
79 %token <Data.clt> TIf TElse TWhile TFor TDo TSwitch TCase TDefault TReturn
80 %token <Data.clt> TBreak TContinue TGoto TSizeof TFunDecl
81 %token <string * Data.clt> TIdent TTypeId TDeclarerId TIteratorId
82 %token <Ast_cocci.added_string * Data.clt> TPragma
84 %token <Parse_aux.idinfo> TMetaId TMetaFunc TMetaLocalFunc
85 %token <Parse_aux.idinfo> TMetaIterator TMetaDeclarer
86 %token <Parse_aux.expinfo> TMetaErr
87 %token <Parse_aux.info> TMetaParam TMetaStm TMetaStmList TMetaType
88 %token <Parse_aux.info> TMetaInit
89 %token <Parse_aux.list_info> TMetaParamList TMetaExpList
90 %token <Parse_aux.typed_expinfo> TMetaExp TMetaIdExp TMetaLocalIdExp TMetaConst
91 %token <Parse_aux.pos_info> TMetaPos
93 %token TArob TArobArob TPArob
94 %token <string> TScriptData
96 %token <Data.clt> TEllipsis TOEllipsis TCEllipsis TPOEllipsis TPCEllipsis
97 %token <Data.clt> TWhen TWhenTrue TWhenFalse TAny TStrict TLineEnd
99 %token <Data.clt> TWhy TDotDot TBang TOPar TOPar0
100 %token <Data.clt> TMid0 TCPar TCPar0
102 %token <string> TPathIsoFile
103 %token <string * Data.clt> TIncludeL TIncludeNL
104 %token <Data.clt * token> TDefine
105 %token <Data.clt * token * int * int> TDefineParam
106 %token <string * Data.clt> TMinusFile TPlusFile
108 %token <Data.clt> TInc TDec
110 %token <string * Data.clt> TString TChar TFloat TInt
112 %token <Data.clt> TOrLog
113 %token <Data.clt> TAndLog
114 %token <Data.clt> TOr
115 %token <Data.clt> TXor
116 %token <Data.clt> TAnd
117 %token <Data.clt> TEqEq TNotEq TTildeEq TTildeExclEq TSub
118 %token <Ast_cocci.logicalOp * Data.clt> TLogOp /* TInf TSup TInfEq TSupEq */
119 %token <Ast_cocci.arithOp * Data.clt> TShOp /* TShl TShr */
120 %token <Ast_cocci.arithOp * Data.clt> TDmOp /* TDiv TMod */
121 %token <Data.clt> TPlus TMinus
122 %token <Data.clt> TMul TTilde
124 %token <Data.clt> TOBrace TCBrace TOInit
125 %token <Data.clt> TOCro TCCro
127 %token <Data.clt> TPtrOp
129 %token TMPtVirg TCppConcatOp
130 %token <Data.clt> TEq TDot TComma TPtVirg
131 %token <Ast_cocci.assignOp * Data.clt> TAssign
133 %token TIso TRightIso TIsoExpression TIsoStatement TIsoDeclaration TIsoType
134 %token TIsoTopLevel TIsoArgExpression TIsoTestExpression TIsoToTestExpression
138 /* operator precedence */
148 %left TLogOp /* TInf TSup TInfEq TSupEq */
149 %left TShOp /* TShl TShr */
151 %left TMul TDmOp /* TDiv TMod */
157 %type <Ast0_cocci.rule> minus_main
159 %start minus_exp_main
160 %type <Ast0_cocci.rule> minus_exp_main
163 %type <Ast0_cocci.rule> plus_main
166 %type <Ast0_cocci.rule> plus_exp_main
169 %type <Data.incl_iso list> include_main
172 %type <Ast_cocci.rulename>
176 %type <Ast_cocci.rulename>
180 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> meta_main
182 %start <string * Ast_cocci.meta_name> script_meta_main
185 %type <Ast0_cocci.anything list list> iso_main
188 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> iso_meta_main
191 %type <unit> never_used
196 minus_main: minus_body EOF { $1 } | m=minus_body TArobArob { m }
197 | m=minus_body TArob { m }
198 plus_main: plus_body EOF { $1 } | p=plus_body TArobArob { p }
199 | p=plus_body TArob { p }
200 minus_exp_main: minus_exp_body EOF { $1 } | m=minus_exp_body TArobArob { m }
201 | m=minus_exp_body TArob { m }
202 plus_exp_main: plus_exp_body EOF { $1 } | p=plus_exp_body TArobArob { p }
203 | p=plus_exp_body TArob { p }
204 meta_main: m=metadec { m (!Ast0.rule_name) }
205 iso_meta_main: m=metadec { m "" }
207 /*****************************************************************************
210 *****************************************************************************/
214 | TContext { Ast0.Context }
215 | TPure TContext { Ast0.PureContext }
216 | TContext TPure { Ast0.PureContext }
217 | /* empty */ { Ast0.Impure }
220 nm=pure_ident TArob { P.make_iso_rule_name_result (P.id2name nm) }
223 nm=ioption(pure_ident) extends d=depends i=loption(choose_iso)
224 a=loption(disable) e=exists ee=is_expression TArob
225 { P.make_cocci_rule_name_result nm d i a e ee }
226 | TGenerated extends d=depends i=loption(choose_iso)
227 a=loption(disable) e=exists ee=is_expression TArob
228 /* these rules have no name as a cheap way to ensure that no normal
229 rule inherits their metavariables or depends on them */
230 { P.make_generated_rule_name_result None d i a e ee }
231 | TScript TDotDot lang=pure_ident d=depends TArob
232 { P.make_script_rule_name_result lang d }
233 | TInitialize TDotDot lang=pure_ident d=depends TArob
234 { P.make_initial_script_rule_name_result lang d }
235 | TFinalize TDotDot lang=pure_ident d=depends TArob
236 { P.make_final_script_rule_name_result lang d }
240 | TExtends parent=TRuleName
241 { !Data.install_bindings (parent) }
244 /* empty */ { Ast.NoDep }
245 | TDepends TOn parents=dep { parents }
249 | dep TAndLog dep { Ast.AndDep($1, $3) }
250 | dep TOrLog dep { Ast.OrDep ($1, $3) }
253 TRuleName { Ast.Dep $1 }
254 | TBang TRuleName { Ast.AntiDep $2 }
255 | TEver TRuleName { Ast.EverDep $2 }
256 | TNever TRuleName { Ast.NeverDep $2 }
257 | TOPar dep TCPar { $2 }
260 TUsing separated_nonempty_list(TComma,TString) { List.map P.id2name $2 }
263 TDisable separated_nonempty_list(TComma,pure_ident) { List.map P.id2name $2 }
266 TExists { Ast.Exists }
267 | TForall { Ast.Forall }
268 | { Ast.Undetermined }
270 is_expression: // for more flexible parsing of top level expressions
272 | TExpression { true }
275 list(incl) TArob { $1 }
276 | list(incl) TArobArob { $1 }
279 TIncludeL { let (x,_) = $1 in Data.Include(x) }
280 | TUsing TString { Data.Iso(Common.Left(P.id2name $2)) }
281 | TUsing TPathIsoFile { Data.Iso(Common.Right $2) }
282 | TVirtual comma_list(pure_ident)
283 { let names = List.map P.id2name $2 in
284 (* ensure that the names of virtual and real rules don't overlap *)
286 (function name -> Hashtbl.add Data.all_metadecls name [])
292 kindfn=metakind ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
293 { P.create_metadec ar ispure kindfn ids }
294 | kindfn=metakind_fresh ids=comma_list(pure_ident_or_meta_ident_with_seed)
296 { P.create_fresh_metadec kindfn ids }
297 | ar=arity ispure=pure
298 kindfn=metakind_atomic_maybe_virt
300 comma_list(pure_ident_or_meta_ident_with_idconstraint_virt(re_or_not_eqid))
302 { let (normal,virt) = Common.partition_either (fun x -> x) ids in
303 let (idfn,virtfn) = kindfn in
305 (P.create_metadec_with_constraints ar ispure idfn normal cr) @
306 (P.create_metadec_virt ar ispure virtfn virt cr) }
307 | ar=arity ispure=pure
308 kindfn=metakind_atomic
309 ids=comma_list(pure_ident_or_meta_ident_with_idconstraint(re_or_not_eqid))
311 { P.create_metadec_with_constraints ar ispure kindfn ids }
312 | ar=arity ispure=pure
313 kindfn=metakind_atomic_expi
314 ids=comma_list(pure_ident_or_meta_ident_with_econstraint(re_or_not_eqe_or_sub))
316 { P.create_metadec_with_constraints ar ispure kindfn ids }
317 | ar=arity ispure=pure
318 kindfn=metakind_atomic_expe
319 ids=comma_list(pure_ident_or_meta_ident_with_econstraint(not_ceq_or_sub))
321 { P.create_metadec_with_constraints ar ispure kindfn ids }
322 | ar=arity TPosition a=option(TPosAny)
323 ids=comma_list(pure_ident_or_meta_ident_with_x_eq(not_pos)) TMPtVirg
324 (* pb: position variables can't be inherited from normal rules, and then
325 there is no way to inherit from a generated rule, so there is no point
326 to have a position variable *)
327 { (if !Data.in_generating
328 then failwith "position variables not allowed in a generated rule file");
329 let kindfn arity name pure check_meta constraints =
330 let tok = check_meta(Ast.MetaPosDecl(arity,name)) in
331 let any = match a with None -> Ast.PER | Some _ -> Ast.ALL in
332 !Data.add_pos_meta name constraints any; tok in
333 P.create_metadec_with_constraints ar false kindfn ids }
334 | ar=arity ispure=pure
335 TParameter Tlist TOCro id=pure_ident_or_meta_ident TCCro
336 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
337 { P.create_len_metadec ar ispure
338 (fun lenname arity name pure check_meta ->
340 check_meta(Ast.MetaParamListDecl(arity,name,Some lenname)) in
341 !Data.add_paramlist_meta name (Some lenname) pure; tok)
343 | ar=arity ispure=pure
344 TExpression Tlist TOCro id=pure_ident_or_meta_ident TCCro
345 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
346 { P.create_len_metadec ar ispure
347 (fun lenname arity name pure check_meta ->
349 check_meta(Ast.MetaExpListDecl(arity,name,Some lenname)) in
350 !Data.add_explist_meta name (Some lenname) pure; tok)
353 %inline metakind_fresh:
355 { (fun name check_meta seed ->
356 let tok = check_meta(Ast.MetaFreshIdDecl(name,seed)) in
357 !Data.add_fresh_id_meta name; tok) }
359 /* metavariable kinds with no constraints, etc */
362 { (fun arity name pure check_meta ->
363 let tok = check_meta(Ast.MetaParamDecl(arity,name)) in
364 !Data.add_param_meta name pure; tok) }
366 { (fun arity name pure check_meta ->
367 let tok = check_meta(Ast.MetaParamListDecl(arity,name,None)) in
368 !Data.add_paramlist_meta name None pure; tok) }
370 { (fun arity name pure check_meta ->
371 let tok = check_meta(Ast.MetaExpListDecl(arity,name,None)) in
372 !Data.add_explist_meta name None pure; tok) }
374 { (fun arity name pure check_meta ->
375 let tok = check_meta(Ast.MetaTypeDecl(arity,name)) in
376 !Data.add_type_meta name pure; tok) }
378 { (fun arity name pure check_meta ->
379 let tok = check_meta(Ast.MetaInitDecl(arity,name)) in
380 !Data.add_init_meta name pure; tok) }
382 { (fun arity name pure check_meta ->
383 let tok = check_meta(Ast.MetaStmDecl(arity,name)) in
384 !Data.add_stm_meta name pure; tok) }
386 { (fun arity name pure check_meta ->
387 let tok = check_meta(Ast.MetaStmListDecl(arity,name)) in
388 !Data.add_stmlist_meta name pure; tok) }
390 { (fun arity (_,name) pure check_meta ->
391 if arity = Ast.NONE && pure = Ast0.Impure
392 then (!Data.add_type_name name; [])
393 else raise (Semantic_cocci.Semantic "bad typedef")) }
395 { (fun arity (_,name) pure check_meta ->
396 if arity = Ast.NONE && pure = Ast0.Impure
397 then (!Data.add_declarer_name name; [])
398 else raise (Semantic_cocci.Semantic "bad declarer")) }
400 { (fun arity (_,name) pure check_meta ->
401 if arity = Ast.NONE && pure = Ast0.Impure
402 then (!Data.add_iterator_name name; [])
403 else raise (Semantic_cocci.Semantic "bad iterator")) }
405 %inline metakind_atomic_maybe_virt:
408 let idfn arity name pure check_meta constraints =
409 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
410 !Data.add_id_meta name constraints pure; tok in
411 let virtfn arity name pure check_meta virtual_env =
413 let vl = List.assoc name virtual_env in
414 !Data.add_virt_id_meta_found name vl; []
416 let name = ("virtual",name) in
417 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
418 !Data.add_virt_id_meta_not_found name pure; tok in
421 %inline metakind_atomic:
423 { (fun arity name pure check_meta constraints ->
424 let tok = check_meta(Ast.MetaFuncDecl(arity,name)) in
425 !Data.add_func_meta name constraints pure; tok) }
427 { (fun arity name pure check_meta constraints ->
428 let tok = check_meta(Ast.MetaLocalFuncDecl(arity,name)) in
429 !Data.add_local_func_meta name constraints pure;
432 { (fun arity name pure check_meta constraints ->
433 let tok = check_meta(Ast.MetaDeclarerDecl(arity,name)) in
434 !Data.add_declarer_meta name constraints pure; tok) }
436 { (fun arity name pure check_meta constraints ->
437 let tok = check_meta(Ast.MetaIteratorDecl(arity,name)) in
438 !Data.add_iterator_meta name constraints pure; tok) }
440 %inline metakind_atomic_expi:
442 { (fun arity name pure check_meta constraints ->
443 let tok = check_meta(Ast.MetaErrDecl(arity,name)) in
444 !Data.add_err_meta name constraints pure; tok) }
445 | l=option(TLocal) TIdExpression ty=ioption(meta_exp_type)
446 { (fun arity name pure check_meta constraints ->
449 !Data.add_idexp_meta ty name constraints pure;
450 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
452 !Data.add_local_idexp_meta ty name constraints pure;
453 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
454 | l=option(TLocal) TIdExpression m=nonempty_list(TMul)
455 { (fun arity name pure check_meta constraints ->
456 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
459 !Data.add_idexp_meta ty name constraints pure;
460 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
462 !Data.add_local_idexp_meta ty name constraints pure;
463 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
464 | TExpression m=nonempty_list(TMul)
465 { (fun arity name pure check_meta constraints ->
466 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
467 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
468 !Data.add_exp_meta ty name constraints pure; tok) }
469 | vl=meta_exp_type TOCro TCCro
470 { (fun arity name pure check_meta constraints ->
471 let ty = Some (List.map (function x -> Type_cocci.Array x) vl) in
472 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
473 !Data.add_exp_meta ty name constraints pure; tok) }
474 | TConstant ty=ioption(meta_exp_type)
475 { (fun arity name pure check_meta constraints ->
476 let tok = check_meta(Ast.MetaConstDecl(arity,name,ty)) in
477 !Data.add_const_meta ty name constraints pure; tok) }
479 %inline metakind_atomic_expe:
481 { (fun arity name pure check_meta constraints ->
482 let tok = check_meta(Ast.MetaExpDecl(arity,name,None)) in
483 !Data.add_exp_meta None name constraints pure; tok) }
484 | vl=meta_exp_type // no error if use $1 but doesn't type check
485 { (fun arity name pure check_meta constraints ->
487 (match constraints with
488 Ast0.NotExpCstrt constraints ->
491 match Ast0.unwrap c with
496 Type_cocci.BaseType(Type_cocci.IntType) -> true
497 | Type_cocci.BaseType(Type_cocci.ShortType) -> true
498 | Type_cocci.BaseType(Type_cocci.LongType) -> true
502 failwith "metavariable with int constraint must be an int"
506 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
507 !Data.add_exp_meta ty name constraints pure; tok)
513 { [Ast0_cocci.ast0_type_to_type t] }
514 | TOBrace t=comma_list(ctype) TCBrace m=list(TMul)
516 (function x -> P.ty_pointerify (Ast0_cocci.ast0_type_to_type x) m)
519 arity: TBang0 { Ast.UNIQUE }
521 | TPlus0 { Ast.MULTI }
522 | /* empty */ { Ast.NONE }
524 /* ---------------------------------------------------------------------- */
529 { Ast0.wrap(Ast0.BaseType(Ast.CharType,[P.clt2mcode "char" ty])) }
531 { Ast0.wrap(Ast0.BaseType(Ast.ShortType,[P.clt2mcode "short" ty])) }
533 { Ast0.wrap(Ast0.BaseType(Ast.IntType,[P.clt2mcode "int" ty])) }
535 { let (nm,pure,clt) = p in
536 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
537 | r=TRuleName TDot p=TIdent
538 { let nm = (r,P.id2name p) in
539 (* this is only possible when we are in a metavar decl. Otherwise,
540 it will be represented already as a MetaType *)
541 let _ = P.check_meta(Ast.MetaTypeDecl(Ast.NONE,nm)) in
542 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm (P.id2clt p),
543 Ast0.Impure (*will be ignored*))) }
545 { Ast0.wrap(Ast0.BaseType(Ast.LongType,[P.clt2mcode "long" ty])) }
546 | ty1=Tlong ty2=Tlong
550 [P.clt2mcode "long" ty1;P.clt2mcode "long" ty2])) }
555 { Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" ty])) }
557 { Ast0.wrap(Ast0.BaseType(Ast.DoubleType,[P.clt2mcode "double" ty])) }
559 { Ast0.wrap(Ast0.BaseType(Ast.FloatType,[P.clt2mcode "float" ty])) }
561 { Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, i)) }
562 | s=struct_or_union i=ident
563 { Ast0.wrap(Ast0.StructUnionName(s, Some i)) }
564 | s=struct_or_union i=ioption(ident)
565 l=TOBrace d=struct_decl_list r=TCBrace
566 { (if i = None && !Data.in_iso
567 then failwith "structures must be named in the iso file");
568 Ast0.wrap(Ast0.StructUnionDef(Ast0.wrap(Ast0.StructUnionName(s, i)),
570 d, P.clt2mcode "}" r)) }
571 | s=TMetaType l=TOBrace d=struct_decl_list r=TCBrace
572 { let (nm,pure,clt) = s in
573 let ty = Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) in
574 Ast0.wrap(Ast0.StructUnionDef(ty,P.clt2mcode "{" l,d,P.clt2mcode "}" r)) }
576 { Ast0.wrap(Ast0.TypeName(P.id2mcode p)) }
580 r=Tsigned ty=signable_types
581 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,Some ty)) }
582 | r=Tunsigned ty=signable_types
583 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,Some ty)) }
584 | ty=signable_types { ty }
585 | ty=non_signable_types { ty }
588 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
589 { P.pointerify (P.make_cv cv ty) m }
591 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,None)) }
593 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,None)) }
594 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
595 { let (mids,code) = t in
597 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
599 /* signed, unsigned alone not allowed */
601 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
602 { P.pointerify (P.make_cv cv ty) m }
603 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
604 { let (mids,code) = t in
606 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
608 /* ---------------------------------------------------------------------- */
611 s=Tstruct { P.clt2mcode Ast.Struct s }
612 | u=Tunion { P.clt2mcode Ast.Union u }
616 | t=ctype d=d_ident pv=TPtVirg
618 [Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] }
619 | t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
620 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar pv=TPtVirg
624 (Ast0.FunctionPointer
625 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
626 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
627 [Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] }
628 | cv=ioption(const_vol) i=pure_ident d=d_ident pv=TPtVirg
630 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
631 [Ast0.wrap(Ast0.UnInit(None,fn idtype,id,P.clt2mcode ";" pv))] }
634 struct_decl_list_start { Ast0.wrap(Ast0.DOTS($1)) }
636 struct_decl_list_start:
638 | struct_decl struct_decl_list_start { $1@$2 }
639 | d=edots_when(TEllipsis,struct_decl) r=continue_struct_decl_list
640 { (P.mkddots "..." d)::r }
642 continue_struct_decl_list:
644 | struct_decl struct_decl_list_start { $1@$2 }
648 /*****************************************************************************/
650 /* have to inline everything to avoid conflicts? switch to proper
651 declarations, statements, and expressions for the subterms */
655 b=loption(minus_start)
656 /*ew=loption(error_words)*/
657 { match f@b(*@ew*) with
658 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
659 | code -> Top_level.top_level code }
663 b=loption(plus_start)
664 /*ew=loption(error_words)*/
665 { Top_level.top_level (f@b(*@ew*)) }
670 /*ew=loption(error_words)*/
671 { match f@[b](*@ew*) with
672 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
673 | code -> Top_level.top_level code }
678 /*ew=loption(error_words)*/
679 { Top_level.top_level (f@[b](*@ew*)) }
684 (Ast0.FILEINFO(P.id2mcode $1,
690 (Ast0.Include(P.clt2mcode "#include"
691 (P.drop_pos (P.drop_aft (P.id2clt $1))),
692 let (arity,ln,lln,offset,col,strbef,straft,pos) =
695 (arity,ln,lln,offset,0,strbef,straft,pos) in
697 (Ast.Local (Parse_aux.str2inc (P.id2name $1)))
701 (Ast0.Include(P.clt2mcode "#include"
702 (P.drop_pos (P.drop_aft (P.id2clt $1))),
703 let (arity,ln,lln,offset,col,strbef,straft,pos) =
706 (arity,ln,lln,offset,0,strbef,straft,pos) in
708 (Ast.NonLocal (Parse_aux.str2inc (P.id2name $1)))
710 | d=defineop TLineEnd
711 { d (Ast0.wrap(Ast0.DOTS([]))) }
712 | d=defineop t=ctype TLineEnd
713 { let ty = Ast0.wrap(Ast0.TopExp(Ast0.wrap(Ast0.TypeExp(t)))) in
714 d (Ast0.wrap(Ast0.DOTS([ty]))) }
715 | defineop b=toplevel_seq_start(toplevel_after_dots) TLineEnd
719 (match Ast0.unwrap e with
721 [Ast0.rewrap e (Ast0.TopExp(Ast0.set_arg_exp (e1)))]
724 $1 (Ast0.wrap(Ast0.DOTS(body))) }
728 { let (clt,ident) = $1 in
732 (P.clt2mcode "#define" clt,
734 TMetaId((nm,constraints,pure,clt)) ->
735 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
737 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
740 (Semantic_cocci.Semantic
741 "unexpected name for a #define")),
742 Ast0.wrap Ast0.NoParams,
744 | TDefineParam define_param_list_option TCPar
745 { let (clt,ident,parenoff,parencol) = $1 in
746 (* clt is the start of the #define itself *)
747 let (arity,line,lline,offset,col,strbef,straft,pos) = clt in
750 (arity,line,lline,parenoff,parencol,[],[],Ast0.NoMetaPos) in
754 (P.clt2mcode "#define" clt,
756 TMetaId((nm,constraints,pure,clt)) ->
757 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
759 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
762 (Semantic_cocci.Semantic
763 "unexpected name for a #define")),
764 Ast0.wrap (Ast0.DParams (lp,$2,P.clt2mcode ")" $3)),body)) }
766 /* ---------------------------------------------------------------------- */
768 define_param_list: define_param_list_start
770 match Ast0.unwrap x with Ast0.DPcircles(_) -> true | _ -> false in
771 if List.exists circle $1
772 then Ast0.wrap(Ast0.CIRCLES($1))
773 else Ast0.wrap(Ast0.DOTS($1)) }
775 define_param_list_start:
776 ident { [Ast0.wrap(Ast0.DParam $1)] }
777 | ident TComma define_param_list_start
778 { Ast0.wrap(Ast0.DParam $1)::
779 Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $2))::$3 }
780 | d=TEllipsis r=list(dp_comma_args(TEllipsis))
781 { (P.mkdpdots "..." d)::
782 (List.concat (List.map (function x -> x (P.mkdpdots "...")) r)) }
784 dp_comma_args(dotter):
786 { function dot_builder ->
787 [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," c)); dot_builder d] }
789 { function dot_builder ->
790 [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $1));
791 Ast0.wrap(Ast0.DParam $2)] }
793 define_param_list_option: define_param_list { $1 }
794 | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
796 /*****************************************************************************/
799 s=ioption(storage) t=ctype
800 id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
805 (Ast0.FunctionType(Some t,
806 P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
807 id, P.clt2mcode ";" pt)) }
811 TFunDecl i=func_ident lp=TOPar d=decl_list(decl) rp=TCPar
812 lb=TOBrace b=fun_start rb=TCBrace
813 { P.verify_parameter_declarations (Ast0.undots d);
814 Ast0.wrap(Ast0.FunDecl((Ast0.default_info(),Ast0.context_befaft()),
816 P.clt2mcode "(" lp, d,
818 P.clt2mcode "{" lb, b,
819 P.clt2mcode "}" rb)) }
826 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
827 raise (Semantic_cocci.Semantic "duplicate storage")
828 with Not_found -> (Ast0.FStorage($1))::$2 }
829 | t=ctype r=fninfo_nt { (Ast0.FType(t))::r }
832 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
833 raise (Semantic_cocci.Semantic "duplicate inline")
834 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
837 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
838 raise (Semantic_cocci.Semantic "multiple attributes")
839 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
846 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
847 raise (Semantic_cocci.Semantic "duplicate storage")
848 with Not_found -> (Ast0.FStorage($1))::$2 }
851 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
852 raise (Semantic_cocci.Semantic "duplicate inline")
853 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
856 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
857 raise (Semantic_cocci.Semantic "duplicate init")
858 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
861 s=Tstatic { P.clt2mcode Ast.Static s }
862 | s=Tauto { P.clt2mcode Ast.Auto s }
863 | s=Tregister { P.clt2mcode Ast.Register s }
864 | s=Textern { P.clt2mcode Ast.Extern s }
866 decl: t=ctype i=ident
867 { Ast0.wrap(Ast0.Param(t, Some i)) }
868 | t=ctype { (*verify in FunDecl*) Ast0.wrap(Ast0.Param(t, None)) }
869 | t=ctype lp=TOPar s=TMul i=ident rp=TCPar
870 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
873 (Ast0.FunctionPointer
874 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
875 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
876 Ast0.wrap(Ast0.Param(fnptr, Some i)) }
878 { let (nm,pure,clt) = $1 in
879 Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) }
883 | t=ctype lp=TOPar s=TMul rp=TCPar
884 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
887 (Ast0.FunctionPointer
888 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
889 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
890 Ast0.wrap(Ast0.Param(fnptr, None)) }
893 Tconst { P.clt2mcode Ast.Const $1 }
894 | Tvolatile { P.clt2mcode Ast.Volatile $1 }
896 /*****************************************************************************/
899 includes { $1 } /* shouldn't be allowed to be a single_statement... */
904 | TIf TOPar eexpr TCPar single_statement %prec TIf
905 { P.ifthen $1 $2 $3 $4 $5 }
906 | TIf TOPar eexpr TCPar single_statement TElse single_statement
907 { P.ifthenelse $1 $2 $3 $4 $5 $6 $7 }
908 | TFor TOPar option(eexpr) TPtVirg option(eexpr) TPtVirg
909 option(eexpr) TCPar single_statement
910 { P.forloop $1 $2 $3 $4 $5 $6 $7 $8 $9 }
911 | TWhile TOPar eexpr TCPar single_statement
912 { P.whileloop $1 $2 $3 $4 $5 }
913 | TDo single_statement TWhile TOPar eexpr TCPar TPtVirg
914 { P.doloop $1 $2 $3 $4 $5 $6 $7 }
915 | iter_ident TOPar eexpr_list_option TCPar single_statement
916 { P.iterator $1 $2 $3 $4 $5 }
917 | TSwitch TOPar eexpr TCPar TOBrace list(decl_var) list(case_line) TCBrace
918 { P.switch $1 $2 $3 $4 $5 (List.concat $6) $7 $8 }
919 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
920 | TReturn TPtVirg { P.ret $1 $2 }
921 | TBreak TPtVirg { P.break $1 $2 }
922 | TContinue TPtVirg { P.cont $1 $2 }
923 | ident TDotDot { P.label $1 $2 }
924 | TGoto ident TPtVirg { P.goto $1 $2 $3 }
925 | TOBrace fun_start TCBrace
929 TEllipsis w=list(whenppdecs)
930 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." $1, List.concat w)) }
931 | TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
932 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." $1, b,
933 P.clt2mcode "...>" c, List.concat w, false)) }
934 | TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
935 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." $1, b,
936 P.clt2mcode "...+>" c, List.concat w, true)) }
938 %inline stm_dots_ell:
939 a=TEllipsis w=list(whenppdecs)
940 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." a, List.concat w)) }
942 %inline stm_dots_nest:
943 a=TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
944 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." a, b,
945 P.clt2mcode "...>" c, List.concat w, false)) }
946 | a=TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
947 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." a, b,
948 P.clt2mcode "...+>" c, List.concat w, true)) }
950 whenppdecs: w=whens(when_start,rule_elem_statement,any_strict)
953 /* a statement that fits into a single rule_elem. should nests be included?
954 what about statement metavariables? */
957 { Ast0.wrap(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),$1)) }
958 | expr TPtVirg { P.exp_stm $1 $2 }
959 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
960 | TReturn TPtVirg { P.ret $1 $2 }
961 | TBreak TPtVirg { P.break $1 $2 }
962 | TContinue TPtVirg { P.cont $1 $2 }
963 | TOPar0 midzero_list(rule_elem_statement,rule_elem_statement) TCPar0
964 { let (mids,code) = $2 in
966 (Ast0.Disj(P.clt2mcode "(" $1,
967 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
968 mids, P.clt2mcode ")" $3)) }
970 /* a statement on its own */
973 | TOPar0 midzero_list(statement,statement) TCPar0
974 /* degenerate case, elements are single statements and thus don't
976 { let (mids,code) = $2 in
978 (Ast0.Disj(P.clt2mcode "(" $1,
979 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
980 mids, P.clt2mcode ")" $3)) }
983 TDefault TDotDot fun_start
985 (Ast0.Default(P.clt2mcode "default" $1,P.clt2mcode ":" $2,$3)) }
986 | TCase eexpr TDotDot fun_start
987 { Ast0.wrap(Ast0.Case(P.clt2mcode "case" $1,$2,P.clt2mcode ":" $3,$4)) }
988 /* | lp=TOPar0 t=midzero_list(case_line,case_line) rp=TCPar0
989 { let (mids,code) = ([],[t]) in
991 (Ast0.DisjCase(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) } */
993 /* In the following, an identifier as a type is not fully supported. Indeed,
994 the language is ambiguous: what is foo * bar; */
995 /* The AST DisjDecl cannot be generated because it would be ambiguous with
996 a disjunction on a statement with a declaration in each branch */
999 { [Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv))] }
1000 | s=ioption(storage) t=ctype d=comma_list(d_ident) pv=TPtVirg
1002 (function (id,fn) ->
1003 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)))
1005 | f=funproto { [f] }
1006 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
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=comma_list(d_ident) pv=TPtVirg
1013 (function (id,fn) ->
1015 P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1016 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)))
1018 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
1019 e=initialize pv=TPtVirg
1020 { let (id,fn) = d in
1021 !Data.add_type_name (P.id2name i);
1022 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1023 [Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
1024 P.clt2mcode ";" pv))] }
1025 /* function pointer type */
1026 | s=ioption(storage)
1027 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1028 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1030 { let (id,fn) = d in
1033 (Ast0.FunctionPointer
1034 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1035 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1036 [Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv))] }
1037 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
1038 { [Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
1039 P.clt2mcode ")" $4,P.clt2mcode ";" $5))] }
1040 | s=ioption(storage)
1041 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1042 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1043 q=TEq e=initialize pv=TPtVirg
1044 { let (id,fn) = d in
1047 (Ast0.FunctionPointer
1048 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1049 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1050 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
1051 | s=Ttypedef t=typedef_ctype id=comma_list(typedef_ident) pv=TPtVirg
1052 { let s = P.clt2mcode "typedef" s in
1055 Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv)))
1060 { Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv)) }
1061 | s=ioption(storage) t=ctype d=d_ident pv=TPtVirg
1062 { let (id,fn) = d in
1063 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1065 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
1066 { let (id,fn) = d in
1067 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv)) }
1068 /* type is a typedef name */
1069 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
1070 d=d_ident pv=TPtVirg
1071 { let (id,fn) = d in
1072 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1073 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)) }
1074 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
1075 e=initialize pv=TPtVirg
1076 { let (id,fn) = d in
1077 !Data.add_type_name (P.id2name i);
1078 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1079 Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
1080 P.clt2mcode ";" pv)) }
1081 /* function pointer type */
1082 | s=ioption(storage)
1083 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1084 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1086 { let (id,fn) = d in
1089 (Ast0.FunctionPointer
1090 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1091 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1092 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1093 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
1094 { Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
1095 P.clt2mcode ")" $4,P.clt2mcode ";" $5)) }
1096 | s=ioption(storage)
1097 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1098 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1099 q=TEq e=initialize pv=TPtVirg
1100 { let (id,fn) = d in
1103 (Ast0.FunctionPointer
1104 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1105 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1106 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))}
1110 ident list(array_dec)
1114 (function (l,i,r) ->
1117 (Ast0.Array(rest,P.clt2mcode "[" l,i,P.clt2mcode "]" r)))
1120 array_dec: l=TOCro i=option(eexpr) r=TCCro { (l,i,r) }
1124 { Ast0.wrap(Ast0.InitExpr($1)) }
1125 | TOBrace initialize_list TCBrace
1126 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1129 (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []),
1130 P.clt2mcode "}" $2)) }
1132 {let (nm,pure,clt) = $1 in
1133 Ast0.wrap(Ast0.MetaInit(P.clt2mcode nm clt,pure)) }
1136 /*arithexpr and not eexpr because can have ambiguity with comma*/
1137 /*dots and nests probably not allowed at top level, haven't looked into why*/
1138 arith_expr(eexpr,invalid) { Ast0.wrap(Ast0.InitExpr($1)) }
1139 | TOBrace initialize_list TCBrace
1140 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1143 (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []),
1144 P.clt2mcode "}" $2)) }
1145 /* gccext:, labeled elements */
1146 | list(designator) TEq initialize2
1147 { Ast0.wrap(Ast0.InitGccExt($1,P.clt2mcode "=" $2,$3)) }
1148 | ident TDotDot initialize2
1149 { Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */
1153 { Ast0.DesignatorField (P.clt2mcode "." $1,$2) }
1155 { Ast0.DesignatorIndex (P.clt2mcode "[" $1,$2,P.clt2mcode "]" $3) }
1156 | TOCro eexpr TEllipsis eexpr TCCro
1157 { Ast0.DesignatorRange (P.clt2mcode "[" $1,$2,P.clt2mcode "..." $3,
1158 $4,P.clt2mcode "]" $5) }
1161 initialize_list_start { Ast0.wrap(Ast0.DOTS($1)) }
1163 initialize_list_start:
1164 initialize2 TComma { [$1;Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))] }
1165 | initialize2 TComma initialize_list_start
1166 { $1::Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))::$3 }
1167 | d=edots_when(TEllipsis,initialize)
1168 r=comma_initializers(edots_when(TEllipsis,initialize))
1169 { (P.mkidots "..." d)::
1170 (List.concat(List.map (function x -> x (P.mkidots "...")) r)) }
1172 comma_initializers(dotter):
1174 | d=dotter r=comma_initializers2(dotter)
1175 { (function dot_builder -> [dot_builder d])::r }
1176 | i=initialize2 c=TComma r=comma_initializers(dotter)
1177 { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
1180 comma_initializers2(dotter):
1182 | i=initialize2 c=TComma r=comma_initializers(dotter)
1183 { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
1186 /* a statement that is part of a list */
1189 { let (nm,pure,clt) = $1 in
1190 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1195 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1197 | statement { [$1] }
1198 /* this doesn't allow expressions at top level, because the parser doesn't
1199 know whether there is one. If there is one, this is not sequencible.
1200 If there is not one, then it is. It seems complicated to get around
1201 this at the parser level. We would have to have a check afterwards to
1202 allow this. One case where this would be useful is for a when. Now
1203 we allow a sequence of whens, so one can be on only statements and
1204 one can be on only expressions. */
1205 | TOPar0 t=midzero_list(fun_start,fun_start) TCPar0
1206 { let (mids,code) = t in
1209 match Ast0.unwrap x with Ast0.DOTS([]) -> true | _ -> false)
1213 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, code, mids,
1214 P.clt2mcode ")" $3))] }
1216 /* a statement that is part of a list */
1217 decl_statement_expr:
1219 { let (nm,pure,clt) = $1 in
1220 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1225 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1227 | statement { [$1] }
1228 /* this doesn't allow expressions at top level, because the parser doesn't
1229 know whether there is one. If there is one, this is not sequencible.
1230 If there is not one, then it is. It seems complicated to get around
1231 this at the parser level. We would have to have a check afterwards to
1232 allow this. One case where this would be useful is for a when. Now
1233 we allow a sequence of whens, so one can be on only statements and
1234 one can be on only expressions. */
1235 | TOPar0 t=midzero_list(fun_after_stm,fun_after_dots_or) TCPar0
1236 { let (mids,code) = t in
1237 if List.for_all (function [] -> true | _ -> false) code
1241 List.map (function x -> Ast0.wrap(Ast0.DOTS x)) code in
1242 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, dot_code, mids,
1243 P.clt2mcode ")" $3))] }
1245 /*****************************************************************************/
1247 /* The following cannot contain <... ...> at the top level. This can only
1248 be allowed as an expression when the expression is delimited on both sides
1249 by expression-specific markers. In that case, the rule eexpr is used, which
1250 allows <... ...> anywhere. Hopefully, this will not be too much of a problem
1252 expr: basic_expr(expr,invalid) { $1 }
1253 /* allows ... and nests */
1254 eexpr: basic_expr(eexpr,dot_expressions) { $1 }
1255 /* allows nests but not .... */
1256 dexpr: basic_expr(eexpr,nest_expressions) { $1 }
1259 eexpr { Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))) }
1262 TInvalid { raise (Semantic_cocci.Semantic "not matchable") }
1265 TEllipsis { Ast0.wrap(Ast0.Edots(P.clt2mcode "..." $1,None)) }
1266 | nest_expressions { $1 }
1268 /* not clear what whencode would mean, so just drop it */
1270 TOEllipsis e=expr_dots(TEllipsis) c=TCEllipsis
1271 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<..." $1,
1272 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1273 P.clt2mcode "...>" c, None, false)) }
1274 | TPOEllipsis e=expr_dots(TEllipsis) c=TPCEllipsis
1275 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<+..." $1,
1276 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1277 P.clt2mcode "...+>" c, None, true)) }
1279 //whenexp: TWhen TNotEq w=eexpr TLineEnd { w }
1281 basic_expr(recurser,primary_extra):
1282 assign_expr(recurser,primary_extra) { $1 }
1285 cond_expr(r,pe) { $1 }
1286 | unary_expr(r,pe) TAssign assign_expr_bis
1287 { let (op,clt) = $2 in
1288 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1289 Ast0.set_arg_exp $3,false)) }
1290 | unary_expr(r,pe) TEq assign_expr_bis
1293 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1296 cond_expr(eexpr,dot_expressions) { $1 }
1297 | unary_expr(eexpr,dot_expressions) TAssign assign_expr_bis
1298 { let (op,clt) = $2 in
1299 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1300 Ast0.set_arg_exp $3,false)) }
1301 | unary_expr(eexpr,dot_expressions) TEq assign_expr_bis
1304 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1307 arith_expr(r,pe) { $1 }
1308 | l=arith_expr(r,pe) w=TWhy t=option(eexpr) dd=TDotDot r=cond_expr(r,pe)
1309 { Ast0.wrap(Ast0.CondExpr (l, P.clt2mcode "?" w, t,
1310 P.clt2mcode ":" dd, r)) }
1313 cast_expr(r,pe) { $1 }
1314 | arith_expr(r,pe) TMul arith_expr(r,pe)
1315 { P.arith_op Ast.Mul $1 $2 $3 }
1316 | arith_expr(r,pe) TDmOp arith_expr(r,pe)
1317 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1318 | arith_expr(r,pe) TPlus arith_expr(r,pe)
1319 { P.arith_op Ast.Plus $1 $2 $3 }
1320 | arith_expr(r,pe) TMinus arith_expr(r,pe)
1321 { P.arith_op Ast.Minus $1 $2 $3 }
1322 | arith_expr(r,pe) TShOp arith_expr(r,pe)
1323 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1324 | arith_expr(r,pe) TLogOp arith_expr(r,pe)
1325 { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
1326 | arith_expr(r,pe) TEqEq arith_expr(r,pe)
1327 { P.logic_op Ast.Eq $1 $2 $3 }
1328 | arith_expr(r,pe) TNotEq arith_expr(r,pe)
1329 { P.logic_op Ast.NotEq $1 $2 $3 }
1330 | arith_expr(r,pe) TAnd arith_expr(r,pe)
1331 { P.arith_op Ast.And $1 $2 $3 }
1332 | arith_expr(r,pe) TOr arith_expr(r,pe)
1333 { P.arith_op Ast.Or $1 $2 $3 }
1334 | arith_expr(r,pe) TXor arith_expr(r,pe)
1335 { P.arith_op Ast.Xor $1 $2 $3 }
1336 | arith_expr(r,pe) TAndLog arith_expr(r,pe)
1337 { P.logic_op Ast.AndLog $1 $2 $3 }
1338 | arith_expr(r,pe) TOrLog arith_expr(r,pe)
1339 { P.logic_op Ast.OrLog $1 $2 $3 }
1342 unary_expr(r,pe) { $1 }
1343 | lp=TOPar t=ctype rp=TCPar e=cast_expr(r,pe)
1344 { Ast0.wrap(Ast0.Cast (P.clt2mcode "(" lp, t,
1345 P.clt2mcode ")" rp, e)) }
1348 postfix_expr(r,pe) { $1 }
1349 | TInc unary_expr(r,pe)
1350 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
1351 | TDec unary_expr(r,pe)
1352 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
1353 | unary_op cast_expr(r,pe)
1354 { let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
1355 | TBang unary_expr(r,pe)
1356 { let mcode = P.clt2mcode Ast.Not $1 in
1357 Ast0.wrap(Ast0.Unary($2, mcode)) }
1358 | TSizeof unary_expr(r,pe)
1359 { Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
1360 | s=TSizeof lp=TOPar t=ctype rp=TCPar
1361 { Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
1362 P.clt2mcode "(" lp,t,
1363 P.clt2mcode ")" rp)) }
1365 unary_op: TAnd { P.clt2mcode Ast.GetRef $1 }
1366 | TMul { P.clt2mcode Ast.DeRef $1 }
1367 | TPlus { P.clt2mcode Ast.UnPlus $1 }
1368 | TMinus { P.clt2mcode Ast.UnMinus $1 }
1369 | TTilde { P.clt2mcode Ast.Tilde $1 }
1372 primary_expr(r,pe) { $1 }
1373 | postfix_expr(r,pe) TOCro eexpr TCCro
1374 { Ast0.wrap(Ast0.ArrayAccess ($1,P.clt2mcode "[" $2,$3,
1375 P.clt2mcode "]" $4)) }
1376 | postfix_expr(r,pe) TDot ident
1377 { Ast0.wrap(Ast0.RecordAccess($1, P.clt2mcode "." $2, $3)) }
1378 | postfix_expr(r,pe) TPtrOp ident
1379 { Ast0.wrap(Ast0.RecordPtAccess($1, P.clt2mcode "->" $2,
1381 | postfix_expr(r,pe) TInc
1382 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Inc $2)) }
1383 | postfix_expr(r,pe) TDec
1384 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Dec $2)) }
1385 | postfix_expr(r,pe) TOPar eexpr_list_option TCPar
1386 { Ast0.wrap(Ast0.FunCall($1,P.clt2mcode "(" $2,
1388 P.clt2mcode ")" $4)) }
1390 primary_expr(recurser,primary_extra):
1391 func_ident { Ast0.wrap(Ast0.Ident($1)) }
1393 { let (x,clt) = $1 in
1394 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1396 { let (x,clt) = $1 in
1397 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Float x) clt)) }
1399 { let (x,clt) = $1 in
1400 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.String x) clt)) }
1402 { let (x,clt) = $1 in
1403 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Char x) clt)) }
1405 { let (nm,constraints,pure,ty,clt) = $1 in
1407 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
1409 { let (nm,constraints,pure,clt) = $1 in
1410 Ast0.wrap(Ast0.MetaErr(P.clt2mcode nm clt,constraints,pure)) }
1412 { let (nm,constraints,pure,ty,clt) = $1 in
1414 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
1416 { let (nm,constraints,pure,ty,clt) = $1 in
1418 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
1420 { let (nm,constraints,pure,ty,clt) = $1 in
1422 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.LocalID,pure)) }
1424 { Ast0.wrap(Ast0.Paren(P.clt2mcode "(" $1,$2,
1425 P.clt2mcode ")" $3)) }
1426 | TOPar0 midzero_list(recurser,eexpr) TCPar0
1427 { let (mids,code) = $2 in
1428 Ast0.wrap(Ast0.DisjExpr(P.clt2mcode "(" $1,
1430 P.clt2mcode ")" $3)) }
1431 | primary_extra { $1 }
1434 r=no_dot_start_end(dexpr,edots_when(dotter,eexpr)) { r }
1437 no_dot_start_end(grammar,dotter):
1438 g=grammar dg=list(pair(dotter,grammar))
1439 { function dot_builder ->
1440 g :: (List.concat(List.map (function (d,g) -> [dot_builder d;g]) dg)) }
1442 /*****************************************************************************/
1448 | TIdentifier { "identifier" }
1449 | TExpression { "expression" }
1450 | TStatement { "statement" }
1451 | TFunction { "function" }
1452 | TLocal { "local" }
1454 | TParameter { "parameter" }
1455 | TIdExpression { "idexpression" }
1456 | TInitialiser { "initialiser" }
1458 | TFresh { "fresh" }
1459 | TConstant { "constant" }
1460 | TError { "error" }
1461 | TWords { "words" }
1463 | TContext { "context" }
1464 | TGenerated { "generated" }
1465 | TTypedef { "typedef" }
1466 | TDeclarer { "declarer" }
1467 | TIterator { "iterator" }
1469 | TPosition { "position" }
1472 TRuleName TDot pure_ident { (Some $1,P.id2name $3) }
1473 | TRuleName TDot pure_ident_kwd { (Some $1,$3) }
1475 pure_ident_or_meta_ident:
1476 pure_ident { (None,P.id2name $1) }
1477 | pure_ident_kwd { (None,$1) }
1480 pure_ident_or_meta_ident_with_seed:
1481 pure_ident_or_meta_ident { ($1,Ast.NoVal) }
1482 | pure_ident_or_meta_ident TEq
1483 separated_nonempty_list(TCppConcatOp,seed_elem)
1485 [Ast.SeedString s] -> ($1,Ast.StringSeed s)
1486 | _ -> ($1,Ast.ListSeed $3) }
1489 TString { let (x,_) = $1 in Ast.SeedString x }
1490 | TMetaId { let (x,_,_,_) = $1 in Ast.SeedId x }
1491 | TRuleName TDot pure_ident
1492 { let nm = ($1,P.id2name $3) in
1493 P.check_meta(Ast.MetaIdDecl(Ast.NONE,nm));
1496 pure_ident_or_meta_ident_with_x_eq(x_eq):
1497 i=pure_ident_or_meta_ident l=loption(x_eq)
1502 pure_ident_or_meta_ident_with_econstraint(x_eq):
1503 i=pure_ident_or_meta_ident optc=option(x_eq)
1506 None -> (i, Ast0.NoConstraint)
1510 pure_ident_or_meta_ident_with_idconstraint_virt(constraint_type):
1511 i=pure_ident_or_meta_ident c=option(constraint_type)
1515 None -> (i, Ast.IdNoConstraint)
1516 | Some constraint_ -> (i,constraint_))
1518 | TVirtual TDot pure_ident { Common.Right (P.id2name $3) }
1520 pure_ident_or_meta_ident_with_idconstraint(constraint_type):
1521 i=pure_ident_or_meta_ident c=option(constraint_type)
1524 None -> (i, Ast.IdNoConstraint)
1525 | Some constraint_ -> (i,constraint_)
1529 re=regexp_eqid {Ast.IdRegExpConstraint re}
1535 then failwith "constraints not allowed in iso file");
1536 (if !Data.in_generating
1537 then failwith "constraints not allowed in a generated rule file");
1538 let (s,_) = re in Ast.IdRegExp (s,Str.regexp s)
1540 | TTildeExclEq re=TString
1542 then failwith "constraints not allowed in iso file");
1543 (if !Data.in_generating
1544 then failwith "constraints not allowed in a generated rule file");
1545 let (s,_) = re in Ast.IdNotRegExp (s,Str.regexp s)
1549 TNotEq i=pure_ident_or_meta_ident
1551 then failwith "constraints not allowed in iso file");
1552 (if !Data.in_generating
1553 (* pb: constraints not stored with metavars; too lazy to search for
1554 them in the pattern *)
1555 then failwith "constraints not allowed in a generated rule file");
1559 P.check_inherited_constraint i
1560 (function mv -> Ast.MetaIdDecl(Ast.NONE,mv)) in
1561 Ast.IdNegIdSet([],[i])
1562 | (None,i) -> Ast.IdNegIdSet([i],[])) }
1563 | TNotEq TOBrace l=comma_list(pure_ident_or_meta_ident) TCBrace
1565 then failwith "constraints not allowed in iso file");
1566 (if !Data.in_generating
1567 then failwith "constraints not allowed in a generated rule file");
1570 (function (str,meta) ->
1572 (Some rn,id) as i ->
1574 P.check_inherited_constraint i
1575 (function mv -> Ast.MetaIdDecl(Ast.NONE,mv)) in
1577 | (None,i) -> (i::str,meta))
1579 Ast.IdNegIdSet(str,meta)
1582 re_or_not_eqe_or_sub:
1583 re=regexp_eqid {Ast0.NotIdCstrt re}
1584 | ne=not_eqe {Ast0.NotExpCstrt ne}
1585 | s=sub {Ast0.SubExpCstrt s}
1588 ceq=not_ceq {Ast0.NotExpCstrt ceq}
1589 | s=sub {Ast0.SubExpCstrt s}
1594 then failwith "constraints not allowed in iso file");
1595 (if !Data.in_generating
1596 then failwith "constraints not allowed in a generated rule file");
1597 [Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))]
1599 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1601 then failwith "constraints not allowed in iso file");
1602 (if !Data.in_generating
1603 then failwith "constraints not allowed in a generated rule file");
1606 Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))))
1611 TNotEq i=ident_or_const
1613 then failwith "constraints not allowed in iso file");
1614 (if !Data.in_generating
1615 then failwith "constraints not allowed in a generated rule file");
1617 | TNotEq TOBrace l=comma_list(ident_or_const) TCBrace
1619 then failwith "constraints not allowed in iso file");
1620 (if !Data.in_generating
1621 then failwith "constraints not allowed in a generated rule file");
1625 (* has to be inherited because not clear how to check subterm constraints
1626 in the functorized CTL engine, so need the variable to be bound
1627 already when bind the subterm constrained metavariable *)
1630 then failwith "constraints not allowed in iso file");
1631 (if !Data.in_generating
1632 then failwith "constraints not allowed in a generated rule file");
1634 P.check_inherited_constraint i
1635 (function mv -> Ast.MetaExpDecl(Ast.NONE,mv,None)) in
1637 | TSub TOBrace l=comma_list(meta_ident) TCBrace
1639 then failwith "constraints not allowed in iso file");
1640 (if !Data.in_generating
1641 then failwith "constraints not allowed in a generated rule file");
1644 P.check_inherited_constraint i
1645 (function mv -> Ast.MetaExpDecl(Ast.NONE,mv,None)))
1649 i=pure_ident { Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))) }
1651 { let (x,clt) = $1 in
1652 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1657 then failwith "constraints not allowed in iso file");
1658 (if !Data.in_generating
1659 then failwith "constraints not allowed in a generated rule file");
1661 P.check_inherited_constraint i
1662 (function mv -> Ast.MetaPosDecl(Ast.NONE,mv)) in
1664 | TNotEq TOBrace l=comma_list(meta_ident) TCBrace
1666 then failwith "constraints not allowed in iso file");
1667 (if !Data.in_generating
1668 then failwith "constraints not allowed in a generated rule file");
1671 P.check_inherited_constraint i
1672 (function mv -> Ast.MetaPosDecl(Ast.NONE,mv)))
1675 func_ident: pure_ident
1676 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1678 { let (nm,constraints,pure,clt) = $1 in
1679 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1681 { let (nm,constraints,pure,clt) = $1 in
1682 Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
1684 { let (nm,constraints,pure,clt) = $1 in
1686 (Ast0.MetaLocalFunc(P.clt2mcode nm clt,constraints,pure)) }
1689 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1691 { let (nm,constraints,pure,clt) = $1 in
1692 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1696 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1698 { let (nm,constraints,pure,clt) = $1 in
1699 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1703 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1705 { let (nm,constraints,pure,clt) = $1 in
1706 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1710 { Ast0.wrap(Ast0.TypeName(P.id2mcode $1)) }
1712 { let (nm,pure,clt) = $1 in
1713 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
1715 /*****************************************************************************/
1718 /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
1719 | decl_list_start(decl)
1721 match Ast0.unwrap x with Ast0.Pcircles(_) -> true | _ -> false in
1722 if List.exists circle $1
1723 then Ast0.wrap(Ast0.CIRCLES($1))
1724 else Ast0.wrap(Ast0.DOTS($1)) }
1726 decl_list_start(decl):
1727 one_dec(decl) { [$1] }
1728 | one_dec(decl) TComma decl_list_start(decl)
1729 { $1::Ast0.wrap(Ast0.PComma(P.clt2mcode "," $2))::$3 }
1730 | TEllipsis list(comma_decls(TEllipsis,decl))
1731 { Ast0.wrap(Ast0.Pdots(P.clt2mcode "..." $1))::
1732 (List.concat(List.map (function x -> x (P.mkpdots "...")) $2)) }
1737 { let (nm,lenname,pure,clt) = $1 in
1738 let nm = P.clt2mcode nm clt in
1741 Some nm -> Some(P.clt2mcode nm clt)
1743 Ast0.wrap(Ast0.MetaParamList(nm,lenname,pure)) }
1745 comma_decls(dotter,decl):
1747 { function dot_builder ->
1748 [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1));
1750 | TComma one_dec(decl)
1751 { function dot_builder ->
1752 [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1)); $2] }
1754 /* ---------------------------------------------------------------------- */
1756 /* error words make it complicated to be able to use error as a metavariable
1757 name or a type in a metavariable list; for that we would like to allow TError
1758 as an ident, but that makes conflicts with this rule. To add back error words,
1759 need to find some appropriate delimiter for it, but it has not been used much
1762 TError TWords TEq TOCro cl=comma_list(dexpr) TCCro
1763 { [Ast0.wrap(Ast0.ERRORWORDS(cl))] }
1766 /* ---------------------------------------------------------------------- */
1767 /* sequences of statements and expressions */
1769 /* There are number of cases that must be considered:
1772 Dots and nests allowed at the beginning or end
1773 Expressions allowed at the beginning or end
1774 One function allowed, by itself
1776 Dots and nests allowed at the beginning or end
1777 Expressions not allowed at the beginning or end
1778 Functions not allowed
1779 3. The body of a nest:
1780 Dots and nests not allowed at the beginning or end
1781 Expressions allowed at the beginning or end
1782 Functions not allowed
1784 Dots and nests not allowed at the beginning but allowed at the end
1785 Expressions allowed at the beginning or end
1786 Functions not allowed
1788 These are implemented by the rules minus_toplevel_sequence,
1789 plus_toplevel_sequence, function_body_sequence, nest_body_sequence, and
1792 /* ------------------------------------------------------------------------ */
1793 /* Minus top level */
1795 /* doesn't allow only ... */
1797 fundecl { [Ast0.wrap(Ast0.DECL($1))] }
1798 | ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1799 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1800 | toplevel_seq_startne(toplevel_after_dots_init)
1801 { List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1 }
1803 toplevel_seq_startne(after_dots_init):
1804 a=stm_dots_ell b=after_dots_init { a::b }
1805 | a=stm_dots_nest b=after_dots_init { a::b }
1806 | a=stm_dots_nest { [a] }
1807 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1808 | decl_statement_expr toplevel_after_stm { $1@$2 }
1810 toplevel_seq_start(after_dots_init):
1811 stm_dots after_dots_init { $1::$2 }
1812 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1813 | decl_statement_expr toplevel_after_stm { $1@$2 }
1815 toplevel_after_dots_init:
1816 TNothing toplevel_after_exp {$2}
1817 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1818 | decl_statement_expr toplevel_after_stm {$1@$2}
1822 | stm_dots toplevel_after_dots {$1::$2}
1824 toplevel_after_dots:
1826 | TNothing toplevel_after_exp {$2}
1827 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1828 | decl_statement_expr toplevel_after_stm {$1@$2}
1832 | stm_dots toplevel_after_dots {$1::$2}
1833 | decl_statement toplevel_after_stm {$1@$2}
1836 TOInit initialize_list TCBrace
1837 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1839 /* ------------------------------------------------------------------------ */
1840 /* Plus top level */
1842 /* does allow only ... also allows multiple top-level functions */
1844 ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1845 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1846 | stm_dots plus_after_dots
1847 { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1848 | expr plus_after_exp
1849 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1850 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1851 | decl_statement_expr plus_after_stm
1852 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1856 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1860 | TNothing plus_after_exp {$2}
1861 | expr plus_after_exp
1862 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1863 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1864 | decl_statement_expr plus_after_stm
1865 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1869 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1870 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1871 | decl_statement plus_after_stm
1872 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1874 /* ------------------------------------------------------------------------ */
1878 fun_after_stm { Ast0.wrap(Ast0.DOTS($1)) }
1882 | stm_dots fun_after_dots {$1::$2}
1883 | decl_statement fun_after_stm {$1@$2}
1887 | TNothing fun_after_exp {$2}
1888 | expr fun_after_exp {Ast0.wrap(Ast0.Exp($1))::$2}
1889 | decl_statement_expr fun_after_stm {$1@$2}
1892 stm_dots fun_after_dots {$1::$2}
1894 /* hack to allow mixing statements and expressions in an or */
1897 | TNothing fun_after_exp_or {$2}
1898 | expr fun_after_exp_or {Ast0.wrap(Ast0.Exp($1))::$2}
1899 | decl_statement_expr fun_after_stm {$1@$2}
1903 | stm_dots fun_after_dots {$1::$2}
1905 /* ------------------------------------------------------------------------ */
1909 nest_after_dots { Ast0.wrap(Ast0.DOTS($1)) }
1912 decl_statement_expr nest_after_stm {$1@$2}
1913 | TNothing nest_after_exp {$2}
1914 | expr nest_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1918 | stm_dots nest_after_dots {$1::$2}
1919 | decl_statement nest_after_stm {$1@$2}
1923 | stm_dots nest_after_dots {$1::$2}
1925 /* ------------------------------------------------------------------------ */
1929 expr toplevel_after_exp
1930 { Ast0.wrap(Ast0.DOTS((Ast0.wrap(Ast0.Exp($1)))::$2)) }
1931 | decl_statement toplevel_after_stm
1932 { Ast0.wrap(Ast0.DOTS($1@$2)) }
1934 /* ---------------------------------------------------------------------- */
1939 match Ast0.unwrap x with Ast0.Ecircles(_) -> true | _ -> false in
1941 match Ast0.unwrap x with Ast0.Estars(_) -> true | _ -> false in
1942 if List.exists circle $1
1943 then Ast0.wrap(Ast0.CIRCLES($1))
1945 if List.exists star $1
1946 then Ast0.wrap(Ast0.STARS($1))
1947 else Ast0.wrap(Ast0.DOTS($1)) }
1949 /* arg expr. may contain a type or a explist metavariable */
1952 { Ast0.set_arg_exp $1 }
1954 { let (nm,lenname,pure,clt) = $1 in
1955 let nm = P.clt2mcode nm clt in
1958 Some nm -> Some(P.clt2mcode nm clt)
1960 Ast0.wrap(Ast0.MetaExprList(nm,lenname,pure)) }
1962 { Ast0.set_arg_exp(Ast0.wrap(Ast0.TypeExp($1))) }
1966 | aexpr TComma eexpr_list_start
1967 { $1::Ast0.wrap(Ast0.EComma(P.clt2mcode "," $2))::$3 }
1971 { function dot_builder ->
1972 [Ast0.wrap(Ast0.EComma(P.clt2mcode "," c)); dot_builder d] }
1974 { function dot_builder ->
1975 [Ast0.wrap(Ast0.EComma(P.clt2mcode "," $1)); $2] }
1977 eexpr_list_option: eexpr_list { $1 }
1978 | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
1980 /****************************************************************************/
1982 // non-empty lists - drop separator
1984 separated_nonempty_list(TComma,elem) { $1 }
1986 midzero_list(elem,aft):
1987 a=elem b=list(mzl(aft))
1988 { let (mids,code) = List.split b in (mids,(a::code)) }
1991 a=TMid0 b=elem { (P.clt2mcode "|" a, b) }
1993 edots_when(dotter,when_grammar):
1994 d=dotter { (d,None) }
1995 | d=dotter TWhen TNotEq w=when_grammar TLineEnd { (d,Some w) }
1997 whens(when_grammar,simple_when_grammar,any_strict):
1998 TWhen TNotEq w=when_grammar TLineEnd { [Ast0.WhenNot w] }
1999 | TWhen TEq w=simple_when_grammar TLineEnd { [Ast0.WhenAlways w] }
2000 | TWhen comma_list(any_strict) TLineEnd
2001 { List.map (function x -> Ast0.WhenModifier(x)) $2 }
2002 | TWhenTrue TNotEq e = eexpr TLineEnd { [Ast0.WhenNotTrue e] }
2003 | TWhenFalse TNotEq e = eexpr TLineEnd { [Ast0.WhenNotFalse e] }
2006 TAny { Ast.WhenAny }
2007 | TStrict { Ast.WhenStrict }
2008 | TForall { Ast.WhenForall }
2009 | TExists { Ast.WhenExists }
2011 /*****************************************************************************
2014 *****************************************************************************/
2017 TIsoExpression e1=eexpr el=list(iso(eexpr)) EOF
2018 { let fn x = Ast0.ExprTag x in P.iso_adjust fn fn e1 el }
2019 | TIsoArgExpression e1=eexpr el=list(iso(eexpr)) EOF
2020 { let fn x = Ast0.ArgExprTag x in P.iso_adjust fn fn e1 el }
2021 | TIsoTestExpression e1=eexpr el=list(iso(eexpr)) EOF
2022 { let fn x = Ast0.TestExprTag x in P.iso_adjust fn fn e1 el }
2023 | TIsoToTestExpression e1=eexpr el=list(iso(eexpr)) EOF
2024 { let ffn x = Ast0.ExprTag x in
2025 let fn x = Ast0.TestExprTag x in
2026 P.iso_adjust ffn fn e1 el }
2027 | TIsoStatement s1=single_statement sl=list(iso(single_statement)) EOF
2028 { let fn x = Ast0.StmtTag x in P.iso_adjust fn fn s1 sl }
2029 | TIsoType t1=ctype tl=list(iso(ctype)) EOF
2030 { let fn x = Ast0.TypeCTag x in P.iso_adjust fn fn t1 tl }
2031 | TIsoTopLevel e1=nest_start el=list(iso(nest_start)) EOF
2032 { let fn x = Ast0.DotsStmtTag x in P.iso_adjust fn fn e1 el }
2033 | TIsoDeclaration d1=decl_var dl=list(iso(decl_var)) EOF
2034 { let check_one = function
2038 (Semantic_cocci.Semantic
2039 "only one variable per declaration in an isomorphism rule") in
2040 let d1 = check_one d1 in
2044 Common.Left x -> Common.Left(check_one x)
2045 | Common.Right x -> Common.Right(check_one x))
2047 let fn x = Ast0.DeclTag x in P.iso_adjust fn fn d1 dl }
2050 TIso t=term { Common.Left t }
2051 | TRightIso t=term { Common.Right t }
2053 /*****************************************************************************
2056 *****************************************************************************/
2058 never_used: TPragma { () }
2059 | TPArob TMetaPos { () }
2060 | TScriptData { () }
2063 py=pure_ident TShOp TRuleName TDot cocci=pure_ident TMPtVirg
2064 { (P.id2name py, ($3, P.id2name cocci)) }
2065 | py=pure_ident TShOp TVirtual TDot cocci=pure_ident TMPtVirg
2066 { (P.id2name py, ("virtual", P.id2name cocci)) }