2 * Copyright 2010, INRIA, University of Copenhagen
3 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
4 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
5 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
6 * This file is part of Coccinelle.
8 * Coccinelle is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, according to version 2 of the License.
12 * Coccinelle is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
20 * The authors reserve the right to distribute this or future versions of
21 * Coccinelle under other licenses.
27 (* Not clear how to allow function declarations to specify a return type
28 and how to allow both to be specified as static, because they are in
29 different rules. The rules seem to have to be combined, which would allow
30 functions to be declared as local variables *)
32 (* Not clear how to let a function have a parameter of type void. At the
33 moment, void is allowed to be the type of a variable, which is wrong, and a
34 parameter needs both a type and an identifier *)
35 module Ast0 = Ast0_cocci
36 module Ast = Ast_cocci
39 (* ---------------------------------------------------------------------- *)
40 (* support for TMeta *)
42 let print_meta (r,n) = r^"."^n
44 let meta_metatable = Hashtbl.create(101)
46 let coerce_tmeta newty name builder matcher =
48 let x = Hashtbl.find meta_metatable name in
52 (Printf.sprintf "Metavariable %s is used as %s"
53 (print_meta name) newty)
55 (if !Flag_parsing_cocci.show_SP
59 "Metavariable %s is assumed to be %s metavariable"
60 (print_meta name) newty));
61 Hashtbl.add meta_metatable name builder
63 let tmeta_to_type (name,pure,clt) =
64 (coerce_tmeta "a type" name (TMetaType(name,pure,clt))
65 (function TMetaType(_,_,_) -> true | _ -> false));
66 Ast0.wrap(Ast0.MetaType(P.clt2mcode name clt,pure))
68 let tmeta_to_field (name,pure,clt) =
69 (coerce_tmeta "a field" name (TMetaField(name,pure,clt))
70 (function TMetaField(_,_,_) -> true | _ -> false));
71 P.meta_field (name,pure,clt)
73 let tmeta_to_exp (name,pure,clt) =
74 (coerce_tmeta "an expression" name
75 (TMetaExp(name,Ast0.NoConstraint,pure,None,clt))
76 (function TMetaExp(_,_,_,_,_) -> true | _ -> false));
78 (Ast0.MetaExpr(P.clt2mcode name clt,Ast0.NoConstraint,None,Ast.ANY,pure))
80 let tmeta_to_param (name,pure,clt) =
81 (coerce_tmeta "a parameter" name (TMetaParam(name,pure,clt))
82 (function TMetaParam(_,_,_) -> true | _ -> false));
83 Ast0.wrap(Ast0.MetaParam(P.clt2mcode name clt,pure))
85 let tmeta_to_statement (name,pure,clt) =
86 (coerce_tmeta "a statement" name (TMetaType(name,pure,clt))
87 (function TMetaType(_,_,_) -> true | _ -> false));
88 P.meta_stm (name,pure,clt)
90 let tmeta_to_seed_id (name,pure,clt) =
91 (coerce_tmeta "an identifier" name
92 (TMetaId(name,Ast.IdNoConstraint,pure,clt))
93 (function TMetaId(_,_,_,_) -> true | _ -> false));
96 let tmeta_to_ident (name,pure,clt) =
97 (coerce_tmeta "an identifier" name
98 (TMetaId(name,Ast.IdNoConstraint,pure,clt))
99 (function TMetaId(_,_,_,_) -> true | _ -> false));
100 Ast0.wrap(Ast0.MetaId(P.clt2mcode name clt,Ast.IdNoConstraint,pure))
105 %token TIdentifier TExpression TStatement TFunction TLocal TType TParameter
106 %token TIdExpression TInitialiser TDeclaration TField TMetavariable
107 %token Tlist TFresh TConstant TError TWords TWhy0 TPlus0 TBang0
108 %token TPure TContext TGenerated
109 %token TTypedef TDeclarer TIterator TName TPosition TPosAny
110 %token TUsing TDisable TExtends TDepends TOn TEver TNever TExists TForall
111 %token TScript TInitialize TFinalize TNothing TVirtual
112 %token<string> TRuleName
114 %token<Data.clt> Tchar Tshort Tint Tdouble Tfloat Tlong
115 %token<Data.clt> Tsize_t Tssize_t Tptrdiff_t
116 %token<Data.clt> Tvoid Tstruct Tunion Tenum
117 %token<Data.clt> Tunsigned Tsigned
119 %token<Data.clt> Tstatic Tauto Tregister Textern Tinline Ttypedef
120 %token<Data.clt> Tconst Tvolatile
121 %token<string * Data.clt> Tattr
123 %token <Data.clt> TIf TElse TWhile TFor TDo TSwitch TCase TDefault TReturn
124 %token <Data.clt> TBreak TContinue TGoto TSizeof TFunDecl
125 %token <string * Data.clt> TIdent TTypeId TDeclarerId TIteratorId
126 %token <Ast_cocci.added_string * Data.clt> TPragma
128 %token <Parse_aux.idinfo> TMetaId TMetaFunc TMetaLocalFunc
129 %token <Parse_aux.idinfo> TMetaIterator TMetaDeclarer
130 %token <Parse_aux.expinfo> TMetaErr
131 %token <Parse_aux.info> TMetaParam TMetaStm TMetaStmList TMetaType
132 %token <Parse_aux.info> TMetaInit TMetaDecl TMetaField TMeta
133 %token <Parse_aux.list_info> TMetaParamList TMetaExpList
134 %token <Parse_aux.typed_expinfo> TMetaExp TMetaIdExp TMetaLocalIdExp TMetaConst
135 %token <Parse_aux.pos_info> TMetaPos
137 %token TArob TArobArob TPArob
138 %token <string> TScriptData
140 %token <Data.clt> TEllipsis TOEllipsis TCEllipsis TPOEllipsis TPCEllipsis
141 %token <Data.clt> TWhen TWhenTrue TWhenFalse TAny TStrict TLineEnd
143 %token <Data.clt> TWhy TDotDot TBang TOPar TOPar0
144 %token <Data.clt> TMid0 TCPar TCPar0
146 %token <string> TPathIsoFile
147 %token <string * Data.clt> TIncludeL TIncludeNL
148 %token <Data.clt * token> TDefine TUndef
149 %token <Data.clt * token * int * int> TDefineParam
150 %token <string * Data.clt> TMinusFile TPlusFile
152 %token <Data.clt> TInc TDec
154 %token <string * Data.clt> TString TChar TFloat TInt
156 %token <Data.clt> TOrLog
157 %token <Data.clt> TAndLog
158 %token <Data.clt> TOr
159 %token <Data.clt> TXor
160 %token <Data.clt> TAnd
161 %token <Data.clt> TEqEq TNotEq TTildeEq TTildeExclEq TSub
162 %token <Ast_cocci.logicalOp * Data.clt> TLogOp /* TInf TSup TInfEq TSupEq */
163 %token <Ast_cocci.arithOp * Data.clt> TShLOp TShROp /* TShl TShr */
164 %token <Ast_cocci.arithOp * Data.clt> TDmOp /* TDiv TMod */
165 %token <Data.clt> TPlus TMinus
166 %token <Data.clt> TMul TTilde
168 %token <Data.clt> TOBrace TCBrace TOInit
169 %token <Data.clt> TOCro TCCro
171 %token <Data.clt> TPtrOp
173 %token TMPtVirg TCppConcatOp
174 %token <Data.clt> TEq TDot TComma TPtVirg
175 %token <Ast_cocci.assignOp * Data.clt> TAssign
177 %token TIso TRightIso TIsoExpression TIsoStatement TIsoDeclaration TIsoType
178 %token TIsoTopLevel TIsoArgExpression TIsoTestExpression TIsoToTestExpression
184 /* operator precedence */
194 %left TLogOp /* TInf TSup TInfEq TSupEq */
195 %left TShLOp TShROp /* TShl TShr */
197 %left TMul TDmOp /* TDiv TMod */
203 %type <Ast0_cocci.rule> minus_main
205 %start minus_exp_main
206 %type <Ast0_cocci.rule> minus_exp_main
209 %type <Ast0_cocci.rule> plus_main
212 %type <Ast0_cocci.rule> plus_exp_main
215 %type <Data.incl_iso list> include_main
218 %type <Ast_cocci.rulename>
222 %type <Ast_cocci.rulename>
226 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> meta_main
228 %start <(string option (*string*) * string option (*ast*)) * (Ast_cocci.meta_name * Ast_cocci.metavar) option> script_meta_main
231 %type <Ast0_cocci.anything list list> iso_main
234 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> iso_meta_main
237 %type <unit> never_used
242 minus_main: minus_body EOF { $1 } | m=minus_body TArobArob { m }
243 | m=minus_body TArob { m }
244 plus_main: plus_body EOF { $1 } | p=plus_body TArobArob { p }
245 | p=plus_body TArob { p }
246 minus_exp_main: minus_exp_body EOF { $1 } | m=minus_exp_body TArobArob { m }
247 | m=minus_exp_body TArob { m }
248 plus_exp_main: plus_exp_body EOF { $1 } | p=plus_exp_body TArobArob { p }
249 | p=plus_exp_body TArob { p }
250 meta_main: m=metadec { m (!Ast0.rule_name) }
251 iso_meta_main: m=metadec { m "" }
253 /*****************************************************************************
256 *****************************************************************************/
260 | TContext { Ast0.Context }
261 | TPure TContext { Ast0.PureContext }
262 | TContext TPure { Ast0.PureContext }
263 | /* empty */ { Ast0.Impure }
266 nm=pure_ident TArob { P.make_iso_rule_name_result (P.id2name nm) }
269 nm=ioption(pure_ident) extends d=depends i=loption(choose_iso)
270 a=loption(disable) e=exists ee=is_expression TArob
271 { P.make_cocci_rule_name_result nm d i a e ee }
272 | TGenerated extends d=depends i=loption(choose_iso)
273 a=loption(disable) e=exists ee=is_expression TArob
274 /* these rules have no name as a cheap way to ensure that no normal
275 rule inherits their metavariables or depends on them */
276 { P.make_generated_rule_name_result None d i a e ee }
277 | TScript TDotDot lang=pure_ident nm=ioption(pure_ident) d=depends TArob
278 { P.make_script_rule_name_result lang nm d }
279 | TInitialize TDotDot lang=pure_ident d=depends TArob
280 { P.make_initial_script_rule_name_result lang d }
281 | TFinalize TDotDot lang=pure_ident d=depends TArob
282 { P.make_final_script_rule_name_result lang d }
286 | TExtends parent=TRuleName
287 { !Data.install_bindings (parent) }
290 /* empty */ { Ast.NoDep }
291 | TDepends TOn parents=dep { parents }
295 | dep TAndLog dep { Ast.AndDep($1, $3) }
296 | dep TOrLog dep { Ast.OrDep ($1, $3) }
299 TRuleName { Ast.Dep $1 }
300 | TBang TRuleName { Ast.AntiDep $2 }
301 | TEver TRuleName { Ast.EverDep $2 }
302 | TNever TRuleName { Ast.NeverDep $2 }
303 | TOPar dep TCPar { $2 }
306 TUsing separated_nonempty_list(TComma,TString) { List.map P.id2name $2 }
309 TDisable separated_nonempty_list(TComma,pure_ident) { List.map P.id2name $2 }
312 TExists { Ast.Exists }
313 | TForall { Ast.Forall }
314 | { Ast.Undetermined }
316 is_expression: // for more flexible parsing of top level expressions
318 | TExpression { true }
321 list(incl) TArob { $1 }
322 | list(incl) TArobArob { $1 }
325 TIncludeL { let (x,_) = $1 in Data.Include(x) }
326 | TUsing TString { Data.Iso(Common.Left(P.id2name $2)) }
327 | TUsing TPathIsoFile { Data.Iso(Common.Right $2) }
328 | TVirtual comma_list(pure_ident)
329 { let names = List.map P.id2name $2 in
330 Iteration.parsed_virtual_rules :=
331 Common.union_set names !Iteration.parsed_virtual_rules;
332 (* ensure that the names of virtual and real rules don't overlap *)
334 (function name -> Hashtbl.add Data.all_metadecls name [])
340 kindfn=metakind ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
341 { P.create_metadec ar ispure kindfn ids }
342 | kindfn=metakind_fresh ids=comma_list(pure_ident_or_meta_ident_with_seed)
344 { P.create_fresh_metadec kindfn ids }
345 | ar=arity ispure=pure
346 kindfn=metakind_atomic_maybe_virt
348 comma_list(pure_ident_or_meta_ident_with_idconstraint_virt(re_or_not_eqid))
350 { let (normal,virt) = Common.partition_either (fun x -> x) ids in
351 let (idfn,virtfn) = kindfn in
353 (P.create_metadec_with_constraints ar ispure idfn normal cr) @
354 (P.create_metadec_virt ar ispure virtfn virt cr) }
355 | ar=arity ispure=pure
356 kindfn=metakind_atomic
357 ids=comma_list(pure_ident_or_meta_ident_with_idconstraint(re_or_not_eqid))
359 { P.create_metadec_with_constraints ar ispure kindfn ids }
360 | ar=arity ispure=pure
361 kindfn=metakind_atomic_expi
362 ids=comma_list(pure_ident_or_meta_ident_with_econstraint(re_or_not_eqe_or_sub))
364 { P.create_metadec_with_constraints ar ispure kindfn ids }
365 | ar=arity ispure=pure
366 kindfn=metakind_atomic_expe
367 ids=comma_list(pure_ident_or_meta_ident_with_econstraint(not_ceq_or_sub))
369 { P.create_metadec_with_constraints ar ispure kindfn ids }
370 | ar=arity TPosition a=option(TPosAny)
371 ids=comma_list(pure_ident_or_meta_ident_with_x_eq(not_pos)) TMPtVirg
372 (* pb: position variables can't be inherited from normal rules, and then
373 there is no way to inherit from a generated rule, so there is no point
374 to have a position variable *)
375 { (if !Data.in_generating
376 then failwith "position variables not allowed in a generated rule file");
377 let kindfn arity name pure check_meta constraints =
378 let tok = check_meta(Ast.MetaPosDecl(arity,name)) in
379 let any = match a with None -> Ast.PER | Some _ -> Ast.ALL in
380 !Data.add_pos_meta name constraints any; tok in
381 P.create_metadec_with_constraints ar false kindfn ids }
382 | ar=arity ispure=pure
383 TParameter Tlist TOCro len=list_len TCCro
384 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
385 { P.create_len_metadec ar ispure
386 (fun lenname arity name pure check_meta ->
387 let tok = check_meta(Ast.MetaParamListDecl(arity,name,lenname)) in
388 !Data.add_paramlist_meta name lenname pure; tok)
390 | ar=arity ispure=pure
391 TExpression Tlist TOCro len=list_len TCCro
392 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
393 { P.create_len_metadec ar ispure
394 (fun lenname arity name pure check_meta ->
395 let tok = check_meta(Ast.MetaExpListDecl(arity,name,lenname)) in
396 !Data.add_explist_meta name lenname pure; tok)
400 pure_ident_or_meta_ident { Common.Left $1 }
401 | TInt { let (x,clt) = $1 in Common.Right (int_of_string x) }
403 %inline metakind_fresh:
405 { (fun name check_meta seed ->
406 let tok = check_meta(Ast.MetaFreshIdDecl(name,seed)) in
407 !Data.add_fresh_id_meta name; tok) }
409 /* metavariable kinds with no constraints, etc */
412 { (fun arity name pure check_meta ->
413 let tok = check_meta(Ast.MetaMetaDecl(arity,name)) in
414 !Data.add_meta_meta name pure; tok) }
416 { (fun arity name pure check_meta ->
417 let tok = check_meta(Ast.MetaParamDecl(arity,name)) in
418 !Data.add_param_meta name pure; tok) }
420 { (fun arity name pure check_meta ->
421 let len = Ast.AnyLen in
422 let tok = check_meta(Ast.MetaParamListDecl(arity,name,len)) in
423 !Data.add_paramlist_meta name len pure; tok) }
425 { (fun arity name pure check_meta ->
426 let len = Ast.AnyLen in
427 let tok = check_meta(Ast.MetaExpListDecl(arity,name,len)) in
428 !Data.add_explist_meta name len pure; tok) }
430 { (fun arity name pure check_meta ->
431 let tok = check_meta(Ast.MetaTypeDecl(arity,name)) in
432 !Data.add_type_meta name pure; tok) }
434 { (fun arity name pure check_meta ->
435 let tok = check_meta(Ast.MetaInitDecl(arity,name)) in
436 !Data.add_init_meta name pure; tok) }
438 { (fun arity name pure check_meta ->
439 let tok = check_meta(Ast.MetaStmDecl(arity,name)) in
440 !Data.add_stm_meta name pure; tok) }
442 { (fun arity name pure check_meta ->
443 let tok = check_meta(Ast.MetaDeclDecl(arity,name)) in
444 !Data.add_decl_meta name pure; tok) }
446 { (fun arity name pure check_meta ->
447 let tok = check_meta(Ast.MetaFieldDecl(arity,name)) in
448 !Data.add_field_meta name pure; tok) }
450 { (fun arity name pure check_meta ->
451 let tok = check_meta(Ast.MetaStmListDecl(arity,name)) in
452 !Data.add_stmlist_meta name pure; tok) }
454 { (fun arity (_,name) pure check_meta ->
455 if arity = Ast.NONE && pure = Ast0.Impure
456 then (!Data.add_type_name name; [])
457 else raise (Semantic_cocci.Semantic "bad typedef")) }
459 { (fun arity (_,name) pure check_meta ->
460 if arity = Ast.NONE && pure = Ast0.Impure
461 then (!Data.add_declarer_name name; [])
462 else raise (Semantic_cocci.Semantic "bad declarer")) }
464 { (fun arity (_,name) pure check_meta ->
465 if arity = Ast.NONE && pure = Ast0.Impure
466 then (!Data.add_iterator_name name; [])
467 else raise (Semantic_cocci.Semantic "bad iterator")) }
469 %inline metakind_atomic_maybe_virt:
472 let idfn arity name pure check_meta constraints =
473 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
474 !Data.add_id_meta name constraints pure; tok in
475 let virtfn arity name pure check_meta virtual_env =
477 let vl = List.assoc name virtual_env in
478 !Data.add_virt_id_meta_found name vl; []
480 Iteration.parsed_virtual_identifiers :=
481 Common.union_set [name]
482 !Iteration.parsed_virtual_identifiers;
483 let name = ("virtual",name) in
484 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
485 !Data.add_virt_id_meta_not_found name pure; tok in
488 %inline metakind_atomic:
490 { (fun arity name pure check_meta constraints ->
491 let tok = check_meta(Ast.MetaFuncDecl(arity,name)) in
492 !Data.add_func_meta name constraints pure; tok) }
494 { (fun arity name pure check_meta constraints ->
495 let tok = check_meta(Ast.MetaLocalFuncDecl(arity,name)) in
496 !Data.add_local_func_meta name constraints pure;
499 { (fun arity name pure check_meta constraints ->
500 let tok = check_meta(Ast.MetaDeclarerDecl(arity,name)) in
501 !Data.add_declarer_meta name constraints pure; tok) }
503 { (fun arity name pure check_meta constraints ->
504 let tok = check_meta(Ast.MetaIteratorDecl(arity,name)) in
505 !Data.add_iterator_meta name constraints pure; tok) }
507 %inline metakind_atomic_expi:
509 { (fun arity name pure check_meta constraints ->
510 let tok = check_meta(Ast.MetaErrDecl(arity,name)) in
511 !Data.add_err_meta name constraints pure; tok) }
512 | l=option(TLocal) TIdExpression ty=ioption(meta_exp_type)
513 { (fun arity name pure check_meta constraints ->
516 !Data.add_idexp_meta ty name constraints pure;
517 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
519 !Data.add_local_idexp_meta ty name constraints pure;
520 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
521 | l=option(TLocal) TIdExpression m=nonempty_list(TMul)
522 { (fun arity name pure check_meta constraints ->
523 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
526 !Data.add_idexp_meta ty name constraints pure;
527 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
529 !Data.add_local_idexp_meta ty name constraints pure;
530 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
531 | TExpression ty=expression_type
532 { (fun arity name pure check_meta constraints ->
533 let ty = Some [ty] in
534 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
535 !Data.add_exp_meta ty name constraints pure; tok) }
536 | TConstant ty=ioption(meta_exp_type)
537 { (fun arity name pure check_meta constraints ->
538 let tok = check_meta(Ast.MetaConstDecl(arity,name,ty)) in
539 !Data.add_const_meta ty name constraints pure; tok) }
542 m=nonempty_list(TMul) { P.ty_pointerify Type_cocci.Unknown m }
544 { P.ty_pointerify (Type_cocci.EnumName Type_cocci.NoName) m }
545 | Tstruct m=list(TMul)
547 (Type_cocci.StructUnionName (Type_cocci.Struct,Type_cocci.NoName)) m }
548 | Tunion m=list(TMul)
550 (Type_cocci.StructUnionName (Type_cocci.Union,Type_cocci.NoName)) m }
552 %inline metakind_atomic_expe:
554 { (fun arity name pure check_meta constraints ->
555 let tok = check_meta(Ast.MetaExpDecl(arity,name,None)) in
556 !Data.add_exp_meta None name constraints pure; tok) }
557 | vl=meta_exp_type // no error if use $1 but doesn't type check
558 { (fun arity name pure check_meta constraints ->
560 (match constraints with
561 Ast0.NotExpCstrt constraints ->
564 match Ast0.unwrap c with
569 Type_cocci.BaseType(Type_cocci.IntType) -> true
570 | Type_cocci.BaseType(Type_cocci.ShortType) -> true
571 | Type_cocci.BaseType(Type_cocci.LongType) -> true
575 failwith "metavariable with int constraint must be an int"
579 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
580 !Data.add_exp_meta ty name constraints pure; tok)
585 { [Ast0_cocci.ast0_type_to_type t] }
586 | t=typedef_ctype TOCro TCCro
587 { [Type_cocci.Array (Ast0_cocci.ast0_type_to_type t)] }
588 | TOBrace t=comma_list(ctype) TCBrace m=list(TMul)
590 (function x -> P.ty_pointerify (Ast0_cocci.ast0_type_to_type x) m)
593 arity: TBang0 { Ast.UNIQUE }
595 | TPlus0 { Ast.MULTI }
596 | /* empty */ { Ast.NONE }
598 /* ---------------------------------------------------------------------- */
603 { Ast0.wrap(Ast0.BaseType(Ast.CharType,[P.clt2mcode "char" ty])) }
605 { Ast0.wrap(Ast0.BaseType(Ast.ShortType,[P.clt2mcode "short" ty])) }
607 { Ast0.wrap(Ast0.BaseType(Ast.IntType,[P.clt2mcode "int" ty])) }
609 { let (nm,pure,clt) = p in
610 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
611 | r=TRuleName TDot p=TIdent
612 { let nm = (r,P.id2name p) in
613 (* this is only possible when we are in a metavar decl. Otherwise,
614 it will be represented already as a MetaType *)
615 let _ = P.check_meta(Ast.MetaTypeDecl(Ast.NONE,nm)) in
616 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm (P.id2clt p),
617 Ast0.Impure (*will be ignored*))) }
619 { Ast0.wrap(Ast0.BaseType(Ast.LongType,[P.clt2mcode "long" ty])) }
620 | ty1=Tlong ty2=Tlong
624 [P.clt2mcode "long" ty1;P.clt2mcode "long" ty2])) }
629 { Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" ty])) }
631 { Ast0.wrap(Ast0.BaseType(Ast.DoubleType,[P.clt2mcode "double" ty])) }
633 { Ast0.wrap(Ast0.BaseType(Ast.FloatType,[P.clt2mcode "float" ty])) }
635 { Ast0.wrap(Ast0.BaseType(Ast.SizeType,[P.clt2mcode "size_t" ty])) }
637 { Ast0.wrap(Ast0.BaseType(Ast.SSizeType,[P.clt2mcode "ssize_t" ty])) }
639 { Ast0.wrap(Ast0.BaseType(Ast.PtrDiffType,[P.clt2mcode "ptrdiff_t" ty])) }
641 { Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, Some i)) }
642 | s=Tenum i=ioption(ident) l=TOBrace ids=enum_decl_list r=TCBrace
643 { (if i = None && !Data.in_iso
644 then failwith "enums must be named in the iso file");
645 Ast0.wrap(Ast0.EnumDef(Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, i)),
646 P.clt2mcode "{" l, ids, P.clt2mcode "}" r)) }
647 | s=struct_or_union i=type_ident // allow typedef name
648 { Ast0.wrap(Ast0.StructUnionName(s, Some i)) }
649 | s=struct_or_union i=ioption(type_ident)
650 l=TOBrace d=struct_decl_list r=TCBrace
651 { (if i = None && !Data.in_iso
652 then failwith "structures must be named in the iso file");
653 Ast0.wrap(Ast0.StructUnionDef(Ast0.wrap(Ast0.StructUnionName(s, i)),
655 d, P.clt2mcode "}" r)) }
656 | s=TMetaType l=TOBrace d=struct_decl_list r=TCBrace
657 { let (nm,pure,clt) = s in
658 let ty = Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) in
659 Ast0.wrap(Ast0.StructUnionDef(ty,P.clt2mcode "{" l,d,P.clt2mcode "}" r)) }
661 { Ast0.wrap(Ast0.TypeName(P.id2mcode p)) }
665 r=Tsigned ty=signable_types
666 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,Some ty)) }
667 | r=Tunsigned ty=signable_types
668 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,Some ty)) }
669 | ty=signable_types { ty }
670 | ty=non_signable_types { ty }
673 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
674 { P.pointerify (P.make_cv cv ty) m }
676 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,None)) }
678 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,None)) }
679 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
680 { let (mids,code) = t in
682 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
685 | TMeta { tmeta_to_type $1 }
688 /* signed, unsigned alone not allowed */
690 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
691 { P.pointerify (P.make_cv cv ty) m }
692 | lp=TOPar0 t=midzero_list(mctype,mctype) rp=TCPar0
693 { let (mids,code) = t in
695 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
696 | TMeta { tmeta_to_type $1 }
698 /* ---------------------------------------------------------------------- */
701 s=Tstruct { P.clt2mcode Ast.Struct s }
702 | u=Tunion { P.clt2mcode Ast.Union u }
706 | struct_decl_one { [$1] }
709 | TMetaField { P.meta_field $1 }
710 | TMeta { tmeta_to_field $1 }
711 | t=ctype d=d_ident pv=TPtVirg
713 Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv)) }
714 | t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
715 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar pv=TPtVirg
719 (Ast0.FunctionPointer
720 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
721 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
722 Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv)) }
723 | cv=ioption(const_vol) i=pure_ident d=d_ident pv=TPtVirg
725 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
726 Ast0.wrap(Ast0.UnInit(None,fn idtype,id,P.clt2mcode ";" pv)) }
729 struct_decl_list_start { Ast0.wrap(Ast0.DOTS($1)) }
731 struct_decl_list_start:
733 | struct_decl struct_decl_list_start { $1@$2 }
734 | d=edots_when(TEllipsis,struct_decl_one) r=continue_struct_decl_list
735 { (P.mkddots_one "..." d)::r }
737 continue_struct_decl_list:
739 | struct_decl struct_decl_list_start { $1@$2 }
743 /* ---------------------------------------------------------------------- */
744 /* very restricted what kinds of expressions can appear in an enum decl */
747 | disj_ident { Ast0.wrap(Ast0.Ident($1)) }
748 | disj_ident TEq enum_val
749 { let id = Ast0.wrap(Ast0.Ident($1)) in
752 (id,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,
756 ident { Ast0.wrap(Ast0.Ident($1)) }
758 { let (x,clt) = $1 in
759 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
760 | TMeta { tmeta_to_exp $1 }
762 { let (nm,constraints,pure,ty,clt) = $1 in
764 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
766 { let (nm,constraints,pure,ty,clt) = $1 in
768 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
770 { let (nm,constraints,pure,ty,clt) = $1 in
772 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
775 nonempty_list_start(enum_decl_one,edots_when(TEllipsis,enum_decl_one))
776 { Ast0.wrap(Ast0.DOTS($1 P.mkedots (fun c -> Ast0.EComma c))) }
778 /*****************************************************************************/
780 /* have to inline everything to avoid conflicts? switch to proper
781 declarations, statements, and expressions for the subterms */
785 b=loption(minus_start)
786 /*ew=loption(error_words)*/
787 { match f@b(*@ew*) with
788 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
789 | code -> Top_level.top_level code }
793 b=loption(plus_start)
794 /*ew=loption(error_words)*/
795 { Top_level.top_level (f@b(*@ew*)) }
800 /*ew=loption(error_words)*/
801 { match f@[b](*@ew*) with
802 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
803 | code -> Top_level.top_level code }
808 /*ew=loption(error_words)*/
809 { Top_level.top_level (f@[b](*@ew*)) }
814 (Ast0.FILEINFO(P.id2mcode $1,
820 (Ast0.Include(P.clt2mcode "#include"
821 (P.drop_pos (P.drop_aft (P.id2clt $1))),
822 let (arity,ln,lln,offset,col,strbef,straft,pos) =
825 (arity,ln,lln,offset,0,strbef,straft,pos) in
827 (Ast.Local (Parse_aux.str2inc (P.id2name $1)))
831 (Ast0.Include(P.clt2mcode "#include"
832 (P.drop_pos (P.drop_aft (P.id2clt $1))),
833 let (arity,ln,lln,offset,col,strbef,straft,pos) =
836 (arity,ln,lln,offset,0,strbef,straft,pos) in
838 (Ast.NonLocal (Parse_aux.str2inc (P.id2name $1)))
841 { let (clt,ident) = $1 in
844 (P.clt2mcode "#undef" clt,
846 TMetaId((nm,constraints,pure,clt)) ->
847 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
849 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
852 (Semantic_cocci.Semantic
853 "unexpected name for a #define")))) }
854 | d=defineop TLineEnd
855 { d (Ast0.wrap(Ast0.DOTS([]))) }
856 | d=defineop t=ctype TLineEnd
857 { let ty = Ast0.wrap(Ast0.TopExp(Ast0.wrap(Ast0.TypeExp(t)))) in
858 d (Ast0.wrap(Ast0.DOTS([ty]))) }
859 | defineop b=toplevel_seq_start(toplevel_after_dots) TLineEnd
863 (match Ast0.unwrap e with
865 [Ast0.rewrap e (Ast0.TopExp(Ast0.set_arg_exp (e1)))]
868 $1 (Ast0.wrap(Ast0.DOTS(body))) }
872 { let (clt,ident) = $1 in
876 (P.clt2mcode "#define" clt,
878 TMetaId((nm,constraints,pure,clt)) ->
879 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
881 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
884 (Semantic_cocci.Semantic
885 "unexpected name for a #define")),
886 Ast0.wrap Ast0.NoParams,
888 | TDefineParam define_param_list_option TCPar
889 { let (clt,ident,parenoff,parencol) = $1 in
890 (* clt is the start of the #define itself *)
891 let (arity,line,lline,offset,col,strbef,straft,pos) = clt in
894 (arity,line,lline,parenoff,parencol,[],[],Ast0.NoMetaPos) in
898 (P.clt2mcode "#define" clt,
900 TMetaId((nm,constraints,pure,clt)) ->
901 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
903 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
906 (Semantic_cocci.Semantic
907 "unexpected name for a #define")),
908 Ast0.wrap (Ast0.DParams (lp,$2,P.clt2mcode ")" $3)),body)) }
910 /* ---------------------------------------------------------------------- */
912 dparam: mident { Ast0.wrap(Ast0.DParam $1) }
914 define_param_list_option:
915 empty_list_start(dparam,TEllipsis)
919 (fun _ d -> Ast0.wrap(Ast0.DPdots(P.clt2mcode "," d)))
920 (fun c -> Ast0.DPComma c))) }
922 /*****************************************************************************/
925 s=ioption(storage) t=ctype
926 id=fn_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
931 (Ast0.FunctionType(Some t,
932 P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
933 id, P.clt2mcode ";" pt)) }
937 TFunDecl i=fn_ident lp=TOPar d=decl_list(decl) rp=TCPar
938 lb=TOBrace b=fun_start rb=TCBrace
939 { P.verify_parameter_declarations (Ast0.undots d);
940 Ast0.wrap(Ast0.FunDecl((Ast0.default_info(),Ast0.context_befaft()),
942 P.clt2mcode "(" lp, d,
944 P.clt2mcode "{" lb, b,
945 P.clt2mcode "}" rb)) }
952 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
953 raise (Semantic_cocci.Semantic "duplicate storage")
954 with Not_found -> (Ast0.FStorage($1))::$2 }
955 | t=ctype r=fninfo_nt { (Ast0.FType(t))::r }
958 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
959 raise (Semantic_cocci.Semantic "duplicate inline")
960 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
963 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
964 raise (Semantic_cocci.Semantic "multiple attributes")
965 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
972 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
973 raise (Semantic_cocci.Semantic "duplicate storage")
974 with Not_found -> (Ast0.FStorage($1))::$2 }
977 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
978 raise (Semantic_cocci.Semantic "duplicate inline")
979 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
982 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
983 raise (Semantic_cocci.Semantic "duplicate init")
984 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
987 s=Tstatic { P.clt2mcode Ast.Static s }
988 | s=Tauto { P.clt2mcode Ast.Auto s }
989 | s=Tregister { P.clt2mcode Ast.Register s }
990 | s=Textern { P.clt2mcode Ast.Extern s }
992 decl: t=ctype i=disj_ident
993 { Ast0.wrap(Ast0.Param(t, Some i)) }
994 | t=ctype { (*verify in FunDecl*) Ast0.wrap(Ast0.Param(t, None)) }
995 | t=ctype lp=TOPar s=TMul i=disj_ident rp=TCPar
996 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
999 (Ast0.FunctionPointer
1000 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
1001 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
1002 Ast0.wrap(Ast0.Param(fnptr, Some i)) }
1004 { let (nm,pure,clt) = $1 in
1005 Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) }
1006 | TMeta { tmeta_to_param $1 }
1010 | t=ctype lp=TOPar s=TMul rp=TCPar
1011 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
1014 (Ast0.FunctionPointer
1015 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
1016 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
1017 Ast0.wrap(Ast0.Param(fnptr, None)) }
1020 Tconst { P.clt2mcode Ast.Const $1 }
1021 | Tvolatile { P.clt2mcode Ast.Volatile $1 }
1023 /*****************************************************************************/
1026 includes { $1 } /* shouldn't be allowed to be a single_statement... */
1027 | TMeta { tmeta_to_statement $1}
1032 | TIf TOPar eexpr TCPar single_statement %prec TIf
1033 { P.ifthen $1 $2 $3 $4 $5 }
1034 | TIf TOPar eexpr TCPar single_statement TElse single_statement
1035 { P.ifthenelse $1 $2 $3 $4 $5 $6 $7 }
1036 | TFor TOPar option(eexpr) TPtVirg option(eexpr) TPtVirg
1037 option(eexpr) TCPar single_statement
1038 { P.forloop $1 $2 $3 $4 $5 $6 $7 $8 $9 }
1039 | TWhile TOPar eexpr TCPar single_statement
1040 { P.whileloop $1 $2 $3 $4 $5 }
1041 | TDo single_statement TWhile TOPar eexpr TCPar TPtVirg
1042 { P.doloop $1 $2 $3 $4 $5 $6 $7 }
1043 | iter_ident TOPar eexpr_list_option TCPar single_statement
1044 { P.iterator $1 $2 $3 $4 $5 }
1045 | TSwitch TOPar eexpr TCPar TOBrace list(decl_var) list(case_line) TCBrace
1046 { P.switch $1 $2 $3 $4 $5 (List.concat $6) $7 $8 }
1047 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
1048 | TReturn TPtVirg { P.ret $1 $2 }
1049 | TBreak TPtVirg { P.break $1 $2 }
1050 | TContinue TPtVirg { P.cont $1 $2 }
1051 | mident TDotDot { P.label $1 $2 }
1052 | TGoto disj_ident TPtVirg { P.goto $1 $2 $3 }
1053 | TOBrace fun_start TCBrace
1057 TEllipsis w=list(whenppdecs)
1058 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." $1, List.concat w)) }
1059 | TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
1060 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." $1, b,
1061 P.clt2mcode "...>" c, List.concat w, false)) }
1062 | TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
1063 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." $1, b,
1064 P.clt2mcode "...+>" c, List.concat w, true)) }
1066 %inline stm_dots_ell:
1067 a=TEllipsis w=list(whenppdecs)
1068 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." a, List.concat w)) }
1070 %inline stm_dots_nest:
1071 a=TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
1072 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." a, b,
1073 P.clt2mcode "...>" c, List.concat w, false)) }
1074 | a=TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
1075 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." a, b,
1076 P.clt2mcode "...+>" c, List.concat w, true)) }
1078 whenppdecs: w=whens(when_start,rule_elem_statement,any_strict)
1081 /* a statement that fits into a single rule_elem. should nests be included?
1082 what about statement metavariables? */
1083 rule_elem_statement:
1085 { Ast0.wrap(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),$1)) }
1086 | expr TPtVirg { P.exp_stm $1 $2 }
1087 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
1088 | TReturn TPtVirg { P.ret $1 $2 }
1089 | TBreak TPtVirg { P.break $1 $2 }
1090 | TContinue TPtVirg { P.cont $1 $2 }
1091 | TOPar0 midzero_list(rule_elem_statement,rule_elem_statement) TCPar0
1092 { let (mids,code) = $2 in
1094 (Ast0.Disj(P.clt2mcode "(" $1,
1095 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
1096 mids, P.clt2mcode ")" $3)) }
1098 /* a statement on its own */
1101 | TOPar0 midzero_list(statement,statement) TCPar0
1102 /* degenerate case, elements are single statements and thus don't
1104 { let (mids,code) = $2 in
1106 (Ast0.Disj(P.clt2mcode "(" $1,
1107 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
1108 mids, P.clt2mcode ")" $3)) }
1111 TDefault TDotDot fun_start
1113 (Ast0.Default(P.clt2mcode "default" $1,P.clt2mcode ":" $2,$3)) }
1114 | TCase eexpr TDotDot fun_start
1115 { Ast0.wrap(Ast0.Case(P.clt2mcode "case" $1,$2,P.clt2mcode ":" $3,$4)) }
1116 /* | lp=TOPar0 t=midzero_list(case_line,case_line) rp=TCPar0
1117 { let (mids,code) = ([],[t]) in
1119 (Ast0.DisjCase(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) } */
1121 /* In the following, an identifier as a type is not fully supported. Indeed,
1122 the language is ambiguous: what is foo * bar; */
1123 /* The AST DisjDecl cannot be generated because it would be ambiguous with
1124 a disjunction on a statement with a declaration in each branch */
1127 { [Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv))] }
1128 | TMetaDecl { [P.meta_decl $1] }
1129 | s=ioption(storage) t=ctype d=comma_list(d_ident) pv=TPtVirg
1131 (function (id,fn) ->
1132 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)))
1134 | f=funproto { [f] }
1135 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
1137 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
1138 /* type is a typedef name */
1139 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
1140 d=comma_list(d_ident) pv=TPtVirg
1142 (function (id,fn) ->
1144 P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1145 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)))
1147 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
1148 e=initialize pv=TPtVirg
1149 { let (id,fn) = d in
1150 !Data.add_type_name (P.id2name i);
1151 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1152 [Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
1153 P.clt2mcode ";" pv))] }
1154 /* function pointer type */
1155 | s=ioption(storage)
1156 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1157 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1159 { let (id,fn) = d in
1162 (Ast0.FunctionPointer
1163 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1164 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1165 [Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv))] }
1166 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
1167 { [Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
1168 P.clt2mcode ")" $4,P.clt2mcode ";" $5))] }
1169 | s=ioption(storage)
1170 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1171 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1172 q=TEq e=initialize pv=TPtVirg
1173 { let (id,fn) = d in
1176 (Ast0.FunctionPointer
1177 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1178 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1179 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
1180 | s=Ttypedef t=typedef_ctype id=comma_list(typedef_ident) pv=TPtVirg
1181 { let s = P.clt2mcode "typedef" s in
1184 Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv)))
1189 { Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv)) }
1190 | TMetaDecl { P.meta_decl $1 }
1191 | s=ioption(storage) t=ctype d=d_ident pv=TPtVirg
1192 { let (id,fn) = d in
1193 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1195 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
1196 { let (id,fn) = d in
1197 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv)) }
1198 /* type is a typedef name */
1199 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
1200 d=d_ident pv=TPtVirg
1201 { let (id,fn) = d in
1202 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1203 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)) }
1204 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
1205 e=initialize pv=TPtVirg
1206 { let (id,fn) = d in
1207 !Data.add_type_name (P.id2name i);
1208 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1209 Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
1210 P.clt2mcode ";" pv)) }
1211 /* function pointer type */
1212 | s=ioption(storage)
1213 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1214 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1216 { let (id,fn) = d in
1219 (Ast0.FunctionPointer
1220 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1221 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1222 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1223 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
1224 { Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
1225 P.clt2mcode ")" $4,P.clt2mcode ";" $5)) }
1226 | s=ioption(storage)
1227 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1228 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1229 q=TEq e=initialize pv=TPtVirg
1230 { let (id,fn) = d in
1233 (Ast0.FunctionPointer
1234 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1235 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1236 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))}
1240 disj_ident list(array_dec)
1244 (function (l,i,r) ->
1247 (Ast0.Array(rest,P.clt2mcode "[" l,i,P.clt2mcode "]" r)))
1250 array_dec: l=TOCro i=option(eexpr) r=TCCro { (l,i,r) }
1254 { Ast0.wrap(Ast0.InitExpr($1)) }
1255 | TOBrace initialize_list TCBrace
1256 { if P.struct_initializer $2
1258 let il = P.drop_dot_commas $2 in
1259 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
1261 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) }
1263 {let (nm,pure,clt) = $1 in
1264 Ast0.wrap(Ast0.MetaInit(P.clt2mcode nm clt,pure)) }
1267 /*arithexpr and not eexpr because can have ambiguity with comma*/
1268 /*dots and nests probably not allowed at top level, haven't looked into why*/
1269 arith_expr(eexpr,invalid) { Ast0.wrap(Ast0.InitExpr($1)) }
1270 | TOBrace initialize_list TCBrace
1271 { if P.struct_initializer $2
1273 let il = P.drop_dot_commas $2 in
1274 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
1276 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) }
1277 /* gccext:, labeled elements */
1278 | list(designator) TEq initialize2 /*can we have another of these on the rhs?*/
1279 { Ast0.wrap(Ast0.InitGccExt($1,P.clt2mcode "=" $2,$3)) }
1280 | mident TDotDot initialize2
1281 { Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */
1285 { Ast0.DesignatorField (P.clt2mcode "." $1,$2) }
1287 { Ast0.DesignatorIndex (P.clt2mcode "[" $1,$2,P.clt2mcode "]" $3) }
1288 | TOCro eexpr TEllipsis eexpr TCCro
1289 { Ast0.DesignatorRange (P.clt2mcode "[" $1,$2,P.clt2mcode "..." $3,
1290 $4,P.clt2mcode "]" $5) }
1293 empty_list_start(initialize2,edots_when(TEllipsis,initialize))
1294 { Ast0.wrap(Ast0.DOTS($1 P.mkidots (fun c -> Ast0.IComma c))) }
1296 /* a statement that is part of a list */
1299 { let (nm,pure,clt) = $1 in
1300 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1305 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1307 | statement { [$1] }
1308 /* this doesn't allow expressions at top level, because the parser doesn't
1309 know whether there is one. If there is one, this is not sequencible.
1310 If there is not one, then it is. It seems complicated to get around
1311 this at the parser level. We would have to have a check afterwards to
1312 allow this. One case where this would be useful is for a when. Now
1313 we allow a sequence of whens, so one can be on only statements and
1314 one can be on only expressions. */
1315 | TOPar0 t=midzero_list(fun_start,fun_start) TCPar0
1316 { let (mids,code) = t in
1319 match Ast0.unwrap x with Ast0.DOTS([]) -> true | _ -> false)
1323 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, code, mids,
1324 P.clt2mcode ")" $3))] }
1326 /* a statement that is part of a list */
1327 decl_statement_expr:
1329 { let (nm,pure,clt) = $1 in
1330 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1335 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1337 | statement { [$1] }
1338 /* this doesn't allow expressions at top level, because the parser doesn't
1339 know whether there is one. If there is one, this is not sequencible.
1340 If there is not one, then it is. It seems complicated to get around
1341 this at the parser level. We would have to have a check afterwards to
1342 allow this. One case where this would be useful is for a when. Now
1343 we allow a sequence of whens, so one can be on only statements and
1344 one can be on only expressions. */
1345 | TOPar0 t=midzero_list(fun_after_stm,fun_after_dots_or) TCPar0
1346 { let (mids,code) = t in
1347 if List.for_all (function [] -> true | _ -> false) code
1351 List.map (function x -> Ast0.wrap(Ast0.DOTS x)) code in
1352 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, dot_code, mids,
1353 P.clt2mcode ")" $3))] }
1355 /*****************************************************************************/
1357 /* expr cannot contain <... ...> at the top level. This can only
1358 be allowed as an expression when the expression is delimited on the left
1359 by an expression-specific marker. In that case, the rule eexpr is used, which
1360 allows <... ...> anywhere. Hopefully, this will not be too much of a problem
1362 dot_expressions is the most permissive. all three kinds of expressions use
1363 this once an expression_specific token has been seen */
1364 expr: basic_expr(expr,invalid) { $1 }
1365 /* allows ... and nests */
1366 eexpr: basic_expr(eexpr,dot_expressions) { $1 }
1367 /* allows nests but not .... */
1368 dexpr: basic_expr(eexpr,nest_expressions) { $1 }
1371 eexpr { Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))) }
1374 TInvalid { raise (Semantic_cocci.Semantic "not matchable") }
1377 TEllipsis { Ast0.wrap(Ast0.Edots(P.clt2mcode "..." $1,None)) }
1378 | nest_expressions { $1 }
1380 /* not clear what whencode would mean, so just drop it */
1382 TOEllipsis e=expr_dots(TEllipsis) c=TCEllipsis
1383 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<..." $1,
1384 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1385 P.clt2mcode "...>" c, None, false)) }
1386 | TPOEllipsis e=expr_dots(TEllipsis) c=TPCEllipsis
1387 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<+..." $1,
1388 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1389 P.clt2mcode "...+>" c, None, true)) }
1390 | TMeta { tmeta_to_exp $1 }
1392 //whenexp: TWhen TNotEq w=eexpr TLineEnd { w }
1394 basic_expr(recurser,primary_extra):
1395 assign_expr(recurser,primary_extra) { $1 }
1398 cond_expr(r,pe) { $1 }
1399 | unary_expr(r,pe) TAssign assign_expr_bis
1400 { let (op,clt) = $2 in
1401 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1402 Ast0.set_arg_exp $3,false)) }
1403 | unary_expr(r,pe) TEq assign_expr_bis
1406 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1409 cond_expr(eexpr,dot_expressions) { $1 }
1410 | unary_expr(eexpr,dot_expressions) TAssign assign_expr_bis
1411 { let (op,clt) = $2 in
1412 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1413 Ast0.set_arg_exp $3,false)) }
1414 | unary_expr(eexpr,dot_expressions) TEq assign_expr_bis
1417 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1420 arith_expr(r,pe) { $1 }
1421 | l=arith_expr(r,pe) w=TWhy t=option(eexpr) dd=TDotDot r=eexpr/*see parser_c*/
1422 { Ast0.wrap(Ast0.CondExpr (l, P.clt2mcode "?" w, t,
1423 P.clt2mcode ":" dd, r)) }
1426 cast_expr(r,pe) { $1 }
1427 | arith_expr(r,pe) TMul arith_expr_bis
1428 { P.arith_op Ast.Mul $1 $2 $3 }
1429 | arith_expr(r,pe) TDmOp arith_expr_bis
1430 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1431 | arith_expr(r,pe) TPlus arith_expr_bis
1432 { P.arith_op Ast.Plus $1 $2 $3 }
1433 | arith_expr(r,pe) TMinus arith_expr_bis
1434 { P.arith_op Ast.Minus $1 $2 $3 }
1435 | arith_expr(r,pe) TShLOp arith_expr_bis
1436 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1437 | arith_expr(r,pe) TShROp arith_expr_bis
1438 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1439 | arith_expr(r,pe) TLogOp arith_expr_bis
1440 { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
1441 | arith_expr(r,pe) TEqEq arith_expr_bis
1442 { P.logic_op Ast.Eq $1 $2 $3 }
1443 | arith_expr(r,pe) TNotEq arith_expr_bis
1444 { P.logic_op Ast.NotEq $1 $2 $3 }
1445 | arith_expr(r,pe) TAnd arith_expr_bis
1446 { P.arith_op Ast.And $1 $2 $3 }
1447 | arith_expr(r,pe) TOr arith_expr_bis
1448 { P.arith_op Ast.Or $1 $2 $3 }
1449 | arith_expr(r,pe) TXor arith_expr_bis
1450 { P.arith_op Ast.Xor $1 $2 $3 }
1451 | arith_expr(r,pe) TAndLog arith_expr_bis
1452 { P.logic_op Ast.AndLog $1 $2 $3 }
1453 | arith_expr(r,pe) TOrLog arith_expr_bis
1454 { P.logic_op Ast.OrLog $1 $2 $3 }
1456 // allows dots now that an expression-specific token has been seen
1457 // need an extra rule because of recursion restrictions
1459 cast_expr(eexpr,dot_expressions) { $1 }
1460 | arith_expr_bis TMul arith_expr_bis
1461 { P.arith_op Ast.Mul $1 $2 $3 }
1462 | arith_expr_bis TDmOp arith_expr_bis
1463 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1464 | arith_expr_bis TPlus arith_expr_bis
1465 { P.arith_op Ast.Plus $1 $2 $3 }
1466 | arith_expr_bis TMinus arith_expr_bis
1467 { P.arith_op Ast.Minus $1 $2 $3 }
1468 | arith_expr_bis TShLOp arith_expr_bis
1469 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1470 | arith_expr_bis TShROp arith_expr_bis
1471 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1472 | arith_expr_bis TLogOp arith_expr_bis
1473 { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
1474 | arith_expr_bis TEqEq arith_expr_bis
1475 { P.logic_op Ast.Eq $1 $2 $3 }
1476 | arith_expr_bis TNotEq arith_expr_bis
1477 { P.logic_op Ast.NotEq $1 $2 $3 }
1478 | arith_expr_bis TAnd arith_expr_bis
1479 { P.arith_op Ast.And $1 $2 $3 }
1480 | arith_expr_bis TOr arith_expr_bis
1481 { P.arith_op Ast.Or $1 $2 $3 }
1482 | arith_expr_bis TXor arith_expr_bis
1483 { P.arith_op Ast.Xor $1 $2 $3 }
1484 | arith_expr_bis TAndLog arith_expr_bis
1485 { P.logic_op Ast.AndLog $1 $2 $3 }
1486 // no OrLog because it is left associative and this is for
1487 // a right argument, not sure why not the same problem for AndLog
1490 unary_expr(r,pe) { $1 }
1491 | lp=TOPar t=ctype rp=TCPar e=cast_expr(r,pe)
1492 { Ast0.wrap(Ast0.Cast (P.clt2mcode "(" lp, t,
1493 P.clt2mcode ")" rp, e)) }
1496 postfix_expr(r,pe) { $1 }
1497 | TInc unary_expr_bis
1498 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
1499 | TDec unary_expr_bis
1500 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
1501 | unary_op cast_expr(r,pe)
1502 { let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
1503 | TBang unary_expr_bis
1504 { let mcode = P.clt2mcode Ast.Not $1 in
1505 Ast0.wrap(Ast0.Unary($2, mcode)) }
1506 | TSizeof unary_expr_bis
1507 { Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
1508 | s=TSizeof lp=TOPar t=ctype rp=TCPar
1509 { Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
1510 P.clt2mcode "(" lp,t,
1511 P.clt2mcode ")" rp)) }
1513 // version that allows dots
1515 postfix_expr(eexpr,dot_expressions) { $1 }
1516 | TInc unary_expr_bis
1517 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
1518 | TDec unary_expr_bis
1519 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
1520 | unary_op cast_expr(eexpr,dot_expressions)
1521 { let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
1522 | TBang unary_expr_bis
1523 { let mcode = P.clt2mcode Ast.Not $1 in
1524 Ast0.wrap(Ast0.Unary($2, mcode)) }
1525 | TSizeof unary_expr_bis
1526 { Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
1527 | s=TSizeof lp=TOPar t=ctype rp=TCPar
1528 { Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
1529 P.clt2mcode "(" lp,t,
1530 P.clt2mcode ")" rp)) }
1532 unary_op: TAnd { P.clt2mcode Ast.GetRef $1 }
1533 | TMul { P.clt2mcode Ast.DeRef $1 }
1534 | TPlus { P.clt2mcode Ast.UnPlus $1 }
1535 | TMinus { P.clt2mcode Ast.UnMinus $1 }
1536 | TTilde { P.clt2mcode Ast.Tilde $1 }
1539 primary_expr(r,pe) { $1 }
1540 | postfix_expr(r,pe) TOCro eexpr TCCro
1541 { Ast0.wrap(Ast0.ArrayAccess ($1,P.clt2mcode "[" $2,$3,
1542 P.clt2mcode "]" $4)) }
1543 | postfix_expr(r,pe) TDot disj_ident
1544 { Ast0.wrap(Ast0.RecordAccess($1, P.clt2mcode "." $2, $3)) }
1545 | postfix_expr(r,pe) TPtrOp disj_ident
1546 { Ast0.wrap(Ast0.RecordPtAccess($1, P.clt2mcode "->" $2,
1548 | postfix_expr(r,pe) TInc
1549 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Inc $2)) }
1550 | postfix_expr(r,pe) TDec
1551 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Dec $2)) }
1552 | postfix_expr(r,pe) TOPar eexpr_list_option TCPar
1553 { Ast0.wrap(Ast0.FunCall($1,P.clt2mcode "(" $2,
1555 P.clt2mcode ")" $4)) }
1557 primary_expr(recurser,primary_extra):
1558 func_ident { Ast0.wrap(Ast0.Ident($1)) }
1560 { let (x,clt) = $1 in
1561 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1563 { let (x,clt) = $1 in
1564 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Float x) clt)) }
1566 { let (x,clt) = $1 in
1567 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.String x) clt)) }
1569 { let (x,clt) = $1 in
1570 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Char x) clt)) }
1572 { let (nm,constraints,pure,ty,clt) = $1 in
1574 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
1576 { let (nm,constraints,pure,clt) = $1 in
1577 Ast0.wrap(Ast0.MetaErr(P.clt2mcode nm clt,constraints,pure)) }
1579 { let (nm,constraints,pure,ty,clt) = $1 in
1581 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
1583 { let (nm,constraints,pure,ty,clt) = $1 in
1585 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
1587 { let (nm,constraints,pure,ty,clt) = $1 in
1589 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.LocalID,pure)) }
1591 { Ast0.wrap(Ast0.Paren(P.clt2mcode "(" $1,$2,
1592 P.clt2mcode ")" $3)) }
1593 | TOPar0 midzero_list(recurser,eexpr) TCPar0
1594 { let (mids,code) = $2 in
1595 Ast0.wrap(Ast0.DisjExpr(P.clt2mcode "(" $1,
1597 P.clt2mcode ")" $3)) }
1598 | primary_extra { $1 }
1601 r=no_dot_start_end(dexpr,edots_when(dotter,eexpr)) { r }
1604 no_dot_start_end(grammar,dotter):
1605 g=grammar dg=list(pair(dotter,grammar))
1606 { function dot_builder ->
1607 g :: (List.concat(List.map (function (d,g) -> [dot_builder d;g]) dg)) }
1609 /*****************************************************************************/
1615 | TIdentifier { "identifier" }
1616 | TExpression { "expression" }
1617 | TStatement { "statement" }
1618 | TFunction { "function" }
1619 | TLocal { "local" }
1621 | TParameter { "parameter" }
1622 | TIdExpression { "idexpression" }
1623 | TInitialiser { "initialiser" }
1625 | TFresh { "fresh" }
1626 | TConstant { "constant" }
1627 | TError { "error" }
1628 | TWords { "words" }
1630 | TContext { "context" }
1631 | TGenerated { "generated" }
1632 | TTypedef { "typedef" }
1633 | TDeclarer { "declarer" }
1634 | TIterator { "iterator" }
1636 | TPosition { "position" }
1639 TRuleName TDot pure_ident { (Some $1,P.id2name $3) }
1640 | TRuleName TDot pure_ident_kwd { (Some $1,$3) }
1642 pure_ident_or_meta_ident:
1643 pure_ident { (None,P.id2name $1) }
1644 | pure_ident_kwd { (None,$1) }
1647 pure_ident_or_meta_ident_with_seed:
1648 pure_ident_or_meta_ident { ($1,Ast.NoVal) }
1649 | pure_ident_or_meta_ident TEq
1650 separated_nonempty_list(TCppConcatOp,seed_elem)
1652 [Ast.SeedString s] -> ($1,Ast.StringSeed s)
1653 | _ -> ($1,Ast.ListSeed $3) }
1656 TString { let (x,_) = $1 in Ast.SeedString x }
1657 | TMetaId { let (x,_,_,_) = $1 in Ast.SeedId x }
1658 | TMeta {failwith "tmeta"}
1659 | TRuleName TDot pure_ident
1660 { let nm = ($1,P.id2name $3) in
1661 P.check_meta(Ast.MetaIdDecl(Ast.NONE,nm));
1664 pure_ident_or_meta_ident_with_x_eq(x_eq):
1665 i=pure_ident_or_meta_ident l=loption(x_eq)
1670 pure_ident_or_meta_ident_with_econstraint(x_eq):
1671 i=pure_ident_or_meta_ident optc=option(x_eq)
1674 None -> (i, Ast0.NoConstraint)
1678 pure_ident_or_meta_ident_with_idconstraint_virt(constraint_type):
1679 i=pure_ident_or_meta_ident c=option(constraint_type)
1683 None -> (i, Ast.IdNoConstraint)
1684 | Some constraint_ -> (i,constraint_))
1686 | TVirtual TDot pure_ident
1688 let nm = P.id2name $3 in
1689 Iteration.parsed_virtual_identifiers :=
1690 Common.union_set [nm]
1691 !Iteration.parsed_virtual_identifiers;
1695 pure_ident_or_meta_ident_with_idconstraint(constraint_type):
1696 i=pure_ident_or_meta_ident c=option(constraint_type)
1699 None -> (i, Ast.IdNoConstraint)
1700 | Some constraint_ -> (i,constraint_)
1704 re=regexp_eqid {Ast.IdRegExpConstraint re}
1710 then failwith "constraints not allowed in iso file");
1711 (if !Data.in_generating
1712 then failwith "constraints not allowed in a generated rule file");
1713 let (s,_) = re in Ast.IdRegExp (s,Str.regexp s)
1715 | TTildeExclEq re=TString
1717 then failwith "constraints not allowed in iso file");
1718 (if !Data.in_generating
1719 then failwith "constraints not allowed in a generated rule file");
1720 let (s,_) = re in Ast.IdNotRegExp (s,Str.regexp s)
1724 TNotEq i=pure_ident_or_meta_ident
1726 then failwith "constraints not allowed in iso file");
1727 (if !Data.in_generating
1728 (* pb: constraints not stored with metavars; too lazy to search for
1729 them in the pattern *)
1730 then failwith "constraints not allowed in a generated rule file");
1734 P.check_inherited_constraint i
1735 (function mv -> Ast.MetaIdDecl(Ast.NONE,mv)) in
1736 Ast.IdNegIdSet([],[i])
1737 | (None,i) -> Ast.IdNegIdSet([i],[])) }
1738 | TNotEq TOBrace l=comma_list(pure_ident_or_meta_ident) TCBrace
1740 then failwith "constraints not allowed in iso file");
1741 (if !Data.in_generating
1742 then failwith "constraints not allowed in a generated rule file");
1745 (function (str,meta) ->
1747 (Some rn,id) as i ->
1749 P.check_inherited_constraint i
1750 (function mv -> Ast.MetaIdDecl(Ast.NONE,mv)) in
1752 | (None,i) -> (i::str,meta))
1754 Ast.IdNegIdSet(str,meta)
1757 re_or_not_eqe_or_sub:
1758 re=regexp_eqid {Ast0.NotIdCstrt re}
1759 | ne=not_eqe {Ast0.NotExpCstrt ne}
1760 | s=sub {Ast0.SubExpCstrt s}
1763 ceq=not_ceq {Ast0.NotExpCstrt ceq}
1764 | s=sub {Ast0.SubExpCstrt s}
1769 then failwith "constraints not allowed in iso file");
1770 (if !Data.in_generating
1771 then failwith "constraints not allowed in a generated rule file");
1772 [Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))]
1774 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1776 then failwith "constraints not allowed in iso file");
1777 (if !Data.in_generating
1778 then failwith "constraints not allowed in a generated rule file");
1781 Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))))
1786 TNotEq i=ident_or_const
1788 then failwith "constraints not allowed in iso file");
1789 (if !Data.in_generating
1790 then failwith "constraints not allowed in a generated rule file");
1792 | TNotEq TOBrace l=comma_list(ident_or_const) TCBrace
1794 then failwith "constraints not allowed in iso file");
1795 (if !Data.in_generating
1796 then failwith "constraints not allowed in a generated rule file");
1800 (* has to be inherited because not clear how to check subterm constraints
1801 in the functorized CTL engine, so need the variable to be bound
1802 already when bind the subterm constrained metavariable *)
1805 then failwith "constraints not allowed in iso file");
1806 (if !Data.in_generating
1807 then failwith "constraints not allowed in a generated rule file");
1809 P.check_inherited_constraint i
1810 (function mv -> Ast.MetaExpDecl(Ast.NONE,mv,None)) in
1812 | TSub TOBrace l=comma_list(meta_ident) TCBrace
1814 then failwith "constraints not allowed in iso file");
1815 (if !Data.in_generating
1816 then failwith "constraints not allowed in a generated rule file");
1819 P.check_inherited_constraint i
1820 (function mv -> Ast.MetaExpDecl(Ast.NONE,mv,None)))
1824 i=pure_ident { Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))) }
1826 { let (x,clt) = $1 in
1827 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1832 then failwith "constraints not allowed in iso file");
1833 (if !Data.in_generating
1834 then failwith "constraints not allowed in a generated rule file");
1836 P.check_inherited_constraint i
1837 (function mv -> Ast.MetaPosDecl(Ast.NONE,mv)) in
1839 | TNotEq TOBrace l=comma_list(meta_ident) TCBrace
1841 then failwith "constraints not allowed in iso file");
1842 (if !Data.in_generating
1843 then failwith "constraints not allowed in a generated rule file");
1846 P.check_inherited_constraint i
1847 (function mv -> Ast.MetaPosDecl(Ast.NONE,mv)))
1850 func_ident: ident { $1 }
1852 { let (nm,constraints,pure,clt) = $1 in
1853 Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
1855 { let (nm,constraints,pure,clt) = $1 in
1857 (Ast0.MetaLocalFunc(P.clt2mcode nm clt,constraints,pure)) }
1859 fn_ident: disj_ident { $1 }
1861 { let (nm,constraints,pure,clt) = $1 in
1862 Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
1864 { let (nm,constraints,pure,clt) = $1 in
1866 (Ast0.MetaLocalFunc(P.clt2mcode nm clt,constraints,pure)) }
1869 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1871 { let (nm,constraints,pure,clt) = $1 in
1872 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1875 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1876 | TMeta { tmeta_to_ident $1 }
1878 { let (nm,constraints,pure,clt) = $1 in
1879 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1883 | lp=TOPar0 t=midzero_list(disj_ident,disj_ident) rp=TCPar0
1884 { let (mids,code) = t in
1886 (Ast0.DisjId(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
1888 type_ident: disj_ident { $1 }
1890 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1894 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1896 { let (nm,constraints,pure,clt) = $1 in
1897 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1901 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1903 { let (nm,constraints,pure,clt) = $1 in
1904 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1908 { Ast0.wrap(Ast0.TypeName(P.id2mcode $1)) }
1909 | TMeta { tmeta_to_type $1 }
1911 { let (nm,pure,clt) = $1 in
1912 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
1914 /*****************************************************************************/
1917 empty_list_start(one_dec(decl),TEllipsis)
1921 (fun _ d -> Ast0.wrap(Ast0.Pdots(P.clt2mcode "..." d)))
1922 (fun c -> Ast0.PComma c))) }
1927 { let (nm,lenname,pure,clt) = $1 in
1928 let nm = P.clt2mcode nm clt in
1931 Ast.AnyLen -> Ast0.AnyListLen
1932 | Ast.MetaLen nm -> Ast0.MetaListLen(P.clt2mcode nm clt)
1933 | Ast.CstLen n -> Ast0.CstListLen n in
1934 Ast0.wrap(Ast0.MetaParamList(nm,lenname,pure)) }
1936 /* ---------------------------------------------------------------------- */
1937 /* comma list parser, used for fn params, fn args, enums, initlists,
1940 /* enums: enum_decl, edots_when(TEllipsis,enum_decl_one)
1941 fun s d -> P.mkedots "..." d
1942 fun c -> Ast0.EComma c
1945 empty_list_start(elem,dotter):
1946 /* empty */ { fun build_dots build_comma -> [] }
1947 | nonempty_list_start(elem,dotter) { $1 }
1949 nonempty_list_start(elem,dotter): /* dots allowed */
1950 elem { fun build_dots build_comma -> [$1] }
1952 { fun build_dots build_comma ->
1953 $1::[Ast0.wrap(build_comma(P.clt2mcode "," $2))] }
1954 | elem TComma nonempty_list_start(elem,dotter)
1955 { fun build_dots build_comma ->
1956 $1::(Ast0.wrap(build_comma(P.clt2mcode "," $2)))::
1957 ($3 build_dots build_comma) }
1958 | TNothing nonempty_list_start(elem,dotter) { $2 }
1959 | d=dotter { fun build_dots build_comma -> [(build_dots "..." d)] }
1961 { fun build_dots build_comma ->
1962 [(build_dots "..." d);Ast0.wrap(build_comma(P.clt2mcode "," $2))] }
1963 | d=dotter TComma r=continue_list(elem,dotter)
1964 { fun build_dots build_comma ->
1965 (build_dots "..." d)::
1966 (Ast0.wrap(build_comma(P.clt2mcode "," $2)))::
1967 (r build_dots build_comma) }
1969 continue_list(elem,dotter): /* dots not allowed */
1970 elem { fun build_dots build_comma -> [$1] }
1972 { fun build_dots build_comma ->
1973 $1::[Ast0.wrap(build_comma(P.clt2mcode "," $2))] }
1974 | elem TComma nonempty_list_start(elem,dotter)
1975 { fun build_dots build_comma ->
1976 $1::(Ast0.wrap(build_comma(P.clt2mcode "," $2)))::
1977 ($3 build_dots build_comma) }
1978 | TNothing nonempty_list_start(elem,dotter) { $2 }
1980 /* ---------------------------------------------------------------------- */
1982 /* error words make it complicated to be able to use error as a metavariable
1983 name or a type in a metavariable list; for that we would like to allow TError
1984 as an ident, but that makes conflicts with this rule. To add back error words,
1985 need to find some appropriate delimiter for it, but it has not been used much
1988 TError TWords TEq TOCro cl=comma_list(dexpr) TCCro
1989 { [Ast0.wrap(Ast0.ERRORWORDS(cl))] }
1992 /* ---------------------------------------------------------------------- */
1993 /* sequences of statements and expressions */
1995 /* There are number of cases that must be considered:
1998 Dots and nests allowed at the beginning or end
1999 Expressions allowed at the beginning or end
2000 One function allowed, by itself
2002 Dots and nests allowed at the beginning or end
2003 Expressions not allowed at the beginning or end
2004 Functions not allowed
2005 3. The body of a nest:
2006 Dots and nests not allowed at the beginning or end
2007 Expressions allowed at the beginning or end
2008 Functions not allowed
2010 Dots and nests not allowed at the beginning but allowed at the end
2011 Expressions allowed at the beginning or end
2012 Functions not allowed
2014 These are implemented by the rules minus_toplevel_sequence,
2015 plus_toplevel_sequence, function_body_sequence, nest_body_sequence, and
2018 /* ------------------------------------------------------------------------ */
2019 /* Minus top level */
2021 /* doesn't allow only ... */
2023 fundecl { [Ast0.wrap(Ast0.DECL($1))] }
2024 | ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
2025 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
2026 | toplevel_seq_startne(toplevel_after_dots_init)
2027 { List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1 }
2029 toplevel_seq_startne(after_dots_init):
2030 a=stm_dots_ell b=after_dots_init { a::b }
2031 | a=stm_dots_nest b=after_dots_init { a::b }
2032 | a=stm_dots_nest { [a] }
2033 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
2034 | decl_statement_expr toplevel_after_stm { $1@$2 }
2036 toplevel_seq_start(after_dots_init):
2037 stm_dots after_dots_init { $1::$2 }
2038 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
2039 | decl_statement_expr toplevel_after_stm { $1@$2 }
2041 toplevel_after_dots_init:
2042 TNothing toplevel_after_exp {$2}
2043 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
2044 | decl_statement_expr toplevel_after_stm {$1@$2}
2048 | stm_dots toplevel_after_dots {$1::$2}
2050 toplevel_after_dots:
2052 | TNothing toplevel_after_exp {$2}
2053 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
2054 | decl_statement_expr toplevel_after_stm {$1@$2}
2058 | stm_dots toplevel_after_dots {$1::$2}
2059 | decl_statement toplevel_after_stm {$1@$2}
2062 TOInit initialize_list TCBrace
2063 { if P.struct_initializer $2
2065 let il = P.drop_dot_commas $2 in
2066 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
2068 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) }
2070 /* ------------------------------------------------------------------------ */
2071 /* Plus top level */
2073 /* does allow only ... also allows multiple top-level functions */
2075 ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
2076 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
2077 | stm_dots plus_after_dots
2078 { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
2079 | expr plus_after_exp
2080 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
2081 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
2082 | decl_statement_expr plus_after_stm
2083 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
2087 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
2091 | TNothing plus_after_exp {$2}
2092 | expr plus_after_exp
2093 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
2094 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
2095 | decl_statement_expr plus_after_stm
2096 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
2100 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
2101 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
2102 | decl_statement plus_after_stm
2103 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
2105 /* ------------------------------------------------------------------------ */
2109 fun_after_stm { Ast0.wrap(Ast0.DOTS($1)) }
2113 | stm_dots fun_after_dots {$1::$2}
2114 | decl_statement fun_after_stm {$1@$2}
2118 | TNothing fun_after_exp {$2}
2119 | expr fun_after_exp {Ast0.wrap(Ast0.Exp($1))::$2}
2120 | decl_statement_expr fun_after_stm {$1@$2}
2123 stm_dots fun_after_dots {$1::$2}
2125 /* hack to allow mixing statements and expressions in an or */
2128 | TNothing fun_after_exp_or {$2}
2129 | expr fun_after_exp_or {Ast0.wrap(Ast0.Exp($1))::$2}
2130 | decl_statement_expr fun_after_stm {$1@$2}
2134 | stm_dots fun_after_dots {$1::$2}
2136 /* ------------------------------------------------------------------------ */
2140 nest_after_dots { Ast0.wrap(Ast0.DOTS($1)) }
2143 decl_statement_expr nest_after_stm {$1@$2}
2144 | TNothing nest_after_exp {$2}
2145 | expr nest_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
2149 | stm_dots nest_after_dots {$1::$2}
2150 | decl_statement nest_after_stm {$1@$2}
2154 | stm_dots nest_after_dots {$1::$2}
2156 /* ------------------------------------------------------------------------ */
2160 expr toplevel_after_exp
2161 { Ast0.wrap(Ast0.DOTS((Ast0.wrap(Ast0.Exp($1)))::$2)) }
2162 | decl_statement toplevel_after_stm
2163 { Ast0.wrap(Ast0.DOTS($1@$2)) }
2165 /* ---------------------------------------------------------------------- */
2167 /* arg expr. may contain a type or a explist metavariable */
2169 dexpr { Ast0.set_arg_exp $1 }
2171 { let (nm,lenname,pure,clt) = $1 in
2172 let nm = P.clt2mcode nm clt in
2175 Ast.AnyLen -> Ast0.AnyListLen
2176 | Ast.MetaLen nm -> Ast0.MetaListLen(P.clt2mcode nm clt)
2177 | Ast.CstLen n -> Ast0.CstListLen n in
2178 Ast0.wrap(Ast0.MetaExprList(nm,lenname,pure)) }
2180 { Ast0.set_arg_exp(Ast0.wrap(Ast0.TypeExp($1))) }
2183 empty_list_start(aexpr,TEllipsis)
2187 (fun _ d -> Ast0.wrap(Ast0.Edots(P.clt2mcode "..." d,None)))
2188 (fun c -> Ast0.EComma c))) }
2190 /****************************************************************************/
2192 // non-empty lists - drop separator
2194 separated_nonempty_list(TComma,elem) { $1 }
2196 midzero_list(elem,aft):
2197 a=elem b=list(mzl(aft))
2198 { let (mids,code) = List.split b in (mids,(a::code)) }
2201 a=TMid0 b=elem { (P.clt2mcode "|" a, b) }
2203 edots_when(dotter,when_grammar):
2204 d=dotter { (d,None) }
2205 | d=dotter TWhen TNotEq w=when_grammar TLineEnd { (d,Some w) }
2207 whens(when_grammar,simple_when_grammar,any_strict):
2208 TWhen TNotEq w=when_grammar TLineEnd { [Ast0.WhenNot w] }
2209 | TWhen TEq w=simple_when_grammar TLineEnd { [Ast0.WhenAlways w] }
2210 | TWhen comma_list(any_strict) TLineEnd
2211 { List.map (function x -> Ast0.WhenModifier(x)) $2 }
2212 | TWhenTrue TNotEq e = eexpr TLineEnd { [Ast0.WhenNotTrue e] }
2213 | TWhenFalse TNotEq e = eexpr TLineEnd { [Ast0.WhenNotFalse e] }
2216 TAny { Ast.WhenAny }
2217 | TStrict { Ast.WhenStrict }
2218 | TForall { Ast.WhenForall }
2219 | TExists { Ast.WhenExists }
2221 /*****************************************************************************
2224 *****************************************************************************/
2227 TIsoExpression e1=eexpr el=list(iso(eexpr)) EOF
2228 { let fn x = Ast0.ExprTag x in P.iso_adjust fn fn e1 el }
2229 | TIsoArgExpression e1=eexpr el=list(iso(eexpr)) EOF
2230 { let fn x = Ast0.ArgExprTag x in P.iso_adjust fn fn e1 el }
2231 | TIsoTestExpression e1=eexpr el=list(iso(eexpr)) EOF
2232 { let fn x = Ast0.TestExprTag x in P.iso_adjust fn fn e1 el }
2233 | TIsoToTestExpression e1=eexpr el=list(iso(eexpr)) EOF
2234 { let ffn x = Ast0.ExprTag x in
2235 let fn x = Ast0.TestExprTag x in
2236 P.iso_adjust ffn fn e1 el }
2237 | TIsoStatement s1=single_statement sl=list(iso(single_statement)) EOF
2238 { let fn x = Ast0.StmtTag x in P.iso_adjust fn fn s1 sl }
2239 | TIsoType t1=ctype tl=list(iso(ctype)) EOF
2240 { let fn x = Ast0.TypeCTag x in P.iso_adjust fn fn t1 tl }
2241 | TIsoTopLevel e1=nest_start el=list(iso(nest_start)) EOF
2242 { let fn x = Ast0.DotsStmtTag x in P.iso_adjust fn fn e1 el }
2243 | TIsoDeclaration d1=decl_var dl=list(iso(decl_var)) EOF
2244 { let check_one = function
2248 (Semantic_cocci.Semantic
2249 "only one variable per declaration in an isomorphism rule") in
2250 let d1 = check_one d1 in
2254 Common.Left x -> Common.Left(check_one x)
2255 | Common.Right x -> Common.Right(check_one x))
2257 let fn x = Ast0.DeclTag x in P.iso_adjust fn fn d1 dl }
2260 TIso t=term { Common.Left t }
2261 | TRightIso t=term { Common.Right t }
2263 /*****************************************************************************
2266 *****************************************************************************/
2268 never_used: TPragma { () }
2269 | TPArob TMetaPos { () }
2270 | TScriptData { () }
2273 py=pure_ident TMPtVirg
2274 { ((Some (P.id2name py), None), None) }
2275 | py=pure_ident script_name_decl TMPtVirg
2276 { ((Some (P.id2name py), None), Some $2) }
2277 | TOPar TUnderscore TComma ast=pure_ident TCPar script_name_decl TMPtVirg
2278 { ((None, Some (P.id2name ast)), Some $6) }
2279 | TOPar str=pure_ident TComma TUnderscore TCPar script_name_decl TMPtVirg
2280 { ((Some (P.id2name str), None), Some $6) }
2281 | TOPar str=pure_ident TComma ast=pure_ident TCPar script_name_decl TMPtVirg
2282 { ((Some (P.id2name str), Some (P.id2name ast)), Some $6) }
2285 TShLOp TRuleName TDot cocci=pure_ident
2286 { let nm = P.id2name cocci in
2287 let mv = Parse_aux.lookup $2 nm in
2289 | TShLOp TVirtual TDot cocci=pure_ident
2290 { let nm = P.id2name cocci in
2291 Iteration.parsed_virtual_identifiers :=
2292 Common.union_set [nm]
2293 !Iteration.parsed_virtual_identifiers;
2294 let name = ("virtual", nm) in
2295 let mv = Ast.MetaIdDecl(Ast.NONE,name) in