Release coccinelle-0.2.0
[bpt/coccinelle.git] / parsing_cocci / parser_cocci_menhir.mly
1 /*
2 * Copyright 2005-2009, 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.
5 *
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.
9 *
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.
14 *
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/>.
17 *
18 * The authors reserve the right to distribute this or future versions of
19 * Coccinelle under other licenses.
20 */
21
22
23 %{
24
25 (* Not clear how to allow function declarations to specify a return type
26 and how to allow both to be specified as static, because they are in
27 different rules. The rules seem to have to be combined, which would allow
28 functions to be declared as local variables *)
29
30 (* Not clear how to let a function have a parameter of type void. At the
31 moment, void is allowed to be the type of a variable, which is wrong, and a
32 parameter needs both a type and an identifier *)
33 module Ast0 = Ast0_cocci
34 module Ast = Ast_cocci
35 module P = Parse_aux
36 %}
37
38 %token EOF
39
40 %token TIdentifier TExpression TStatement TFunction TLocal TType TParameter
41 %token TIdExpression TInitialiser
42 %token Tlist TFresh TConstant TError TWords TWhy0 TPlus0 TBang0
43 %token TPure TContext TGenerated
44 %token TTypedef TDeclarer TIterator TName TPosition TPosAny
45 %token TUsing TDisable TExtends TDepends TOn TEver TNever TExists TForall
46 %token TScript TInitialize TFinalize TNothing TVirtual
47 %token<string> TRuleName
48
49 %token<Data.clt> Tchar Tshort Tint Tdouble Tfloat Tlong
50 %token<Data.clt> Tvoid Tstruct Tunion Tenum
51 %token<Data.clt> Tunsigned Tsigned
52
53 %token<Data.clt> Tstatic Tauto Tregister Textern Tinline Ttypedef
54 %token<Data.clt> Tconst Tvolatile
55 %token<string * Data.clt> Tattr
56
57 %token <Data.clt> TIf TElse TWhile TFor TDo TSwitch TCase TDefault TReturn
58 %token <Data.clt> TBreak TContinue TGoto TSizeof TFunDecl
59 %token <string * Data.clt> TIdent TTypeId TDeclarerId TIteratorId TPragma
60
61 %token <Parse_aux.idinfo> TMetaId TMetaFunc TMetaLocalFunc
62 %token <Parse_aux.idinfo> TMetaIterator TMetaDeclarer
63 %token <Parse_aux.expinfo> TMetaErr
64 %token <Parse_aux.info> TMetaParam TMetaStm TMetaStmList TMetaType
65 %token <Parse_aux.info> TMetaInit
66 %token <Parse_aux.list_info> TMetaParamList TMetaExpList
67 %token <Parse_aux.typed_expinfo> TMetaExp TMetaIdExp TMetaLocalIdExp TMetaConst
68 %token <Parse_aux.pos_info> TMetaPos
69
70 %token TArob TArobArob TPArob
71 %token <string> TScriptData
72
73 %token <Data.clt> TEllipsis TOEllipsis TCEllipsis TPOEllipsis TPCEllipsis
74 %token <Data.clt> TWhen TWhenTrue TWhenFalse TAny TStrict TLineEnd
75
76 %token <Data.clt> TWhy TDotDot TBang TOPar TOPar0
77 %token <Data.clt> TMid0 TCPar TCPar0
78
79 %token <string> TPathIsoFile
80 %token <string * Data.clt> TIncludeL TIncludeNL
81 %token <Data.clt * token> TDefine
82 %token <Data.clt * token * int * int> TDefineParam
83 %token <string * Data.clt> TMinusFile TPlusFile
84
85 %token <Data.clt> TInc TDec
86
87 %token <string * Data.clt> TString TChar TFloat TInt
88
89 %token <Data.clt> TOrLog
90 %token <Data.clt> TAndLog
91 %token <Data.clt> TOr
92 %token <Data.clt> TXor
93 %token <Data.clt> TAnd
94 %token <Data.clt> TEqEq TNotEq TTildeEq TTildeExclEq
95 %token <Ast_cocci.logicalOp * Data.clt> TLogOp /* TInf TSup TInfEq TSupEq */
96 %token <Ast_cocci.arithOp * Data.clt> TShOp /* TShl TShr */
97 %token <Ast_cocci.arithOp * Data.clt> TDmOp /* TDiv TMod */
98 %token <Data.clt> TPlus TMinus
99 %token <Data.clt> TMul TTilde
100
101 %token <Data.clt> TOBrace TCBrace TOInit
102 %token <Data.clt> TOCro TCCro
103
104 %token <Data.clt> TPtrOp
105
106 %token TMPtVirg TCppConcatOp
107 %token <Data.clt> TEq TDot TComma TPtVirg
108 %token <Ast_cocci.assignOp * Data.clt> TAssign
109
110 %token TIso TRightIso TIsoExpression TIsoStatement TIsoDeclaration TIsoType
111 %token TIsoTopLevel TIsoArgExpression TIsoTestExpression
112
113 %token TInvalid
114
115 /* operator precedence */
116 %nonassoc TIf
117 %nonassoc TElse
118
119 %left TOrLog
120 %left TAndLog
121 %left TOr
122 %left TXor
123 %left TAnd
124 %left TEqEq TNotEq
125 %left TLogOp /* TInf TSup TInfEq TSupEq */
126 %left TShOp /* TShl TShr */
127 %left TPlus TMinus
128 %left TMul TDmOp /* TDiv TMod */
129
130 %start reinit
131 %type <unit> reinit
132
133 %start minus_main
134 %type <Ast0_cocci.rule> minus_main
135
136 %start minus_exp_main
137 %type <Ast0_cocci.rule> minus_exp_main
138
139 %start plus_main
140 %type <Ast0_cocci.rule> plus_main
141
142 %start plus_exp_main
143 %type <Ast0_cocci.rule> plus_exp_main
144
145 %start include_main
146 %type <Data.incl_iso list> include_main
147
148 %start iso_rule_name
149 %type <Ast_cocci.rulename>
150 iso_rule_name
151
152 %start rule_name
153 %type <Ast_cocci.rulename>
154 rule_name
155
156 %start meta_main
157 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> meta_main
158
159 %start <string * (string * string)> script_meta_main
160
161 %start iso_main
162 %type <Ast0_cocci.anything list list> iso_main
163
164 %start iso_meta_main
165 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> iso_meta_main
166
167 %start never_used
168 %type <unit> never_used
169
170 %%
171
172 reinit: { }
173 minus_main: minus_body EOF { $1 } | m=minus_body TArobArob { m }
174 | m=minus_body TArob { m }
175 plus_main: plus_body EOF { $1 } | p=plus_body TArobArob { p }
176 | p=plus_body TArob { p }
177 minus_exp_main: minus_exp_body EOF { $1 } | m=minus_exp_body TArobArob { m }
178 | m=minus_exp_body TArob { m }
179 plus_exp_main: plus_exp_body EOF { $1 } | p=plus_exp_body TArobArob { p }
180 | p=plus_exp_body TArob { p }
181 meta_main: m=metadec { m (!Ast0.rule_name) }
182 iso_meta_main: m=metadec { m "" }
183
184 /*****************************************************************************
185 *
186 *
187 *****************************************************************************/
188
189 pure:
190 TPure { Ast0.Pure }
191 | TContext { Ast0.Context }
192 | TPure TContext { Ast0.PureContext }
193 | TContext TPure { Ast0.PureContext }
194 | /* empty */ { Ast0.Impure }
195
196 iso_rule_name:
197 nm=pure_ident TArob { P.make_iso_rule_name_result (P.id2name nm) }
198
199 rule_name:
200 nm=ioption(pure_ident) extends d=depends i=loption(choose_iso)
201 a=loption(disable) e=exists ee=is_expression TArob
202 { P.make_cocci_rule_name_result nm d i a e ee }
203 | TGenerated extends d=depends i=loption(choose_iso)
204 a=loption(disable) e=exists ee=is_expression TArob
205 /* these rules have no name as a cheap way to ensure that no normal
206 rule inherits their metavariables or depends on them */
207 { P.make_generated_rule_name_result None d i a e ee }
208 | TScript TDotDot lang=pure_ident d=depends TArob
209 { P.make_script_rule_name_result lang d }
210 | TInitialize TDotDot lang=pure_ident TArob
211 { P.make_initial_script_rule_name_result lang }
212 | TFinalize TDotDot lang=pure_ident TArob
213 { P.make_final_script_rule_name_result lang }
214
215 extends:
216 /* empty */ { () }
217 | TExtends parent=TRuleName
218 { !Data.install_bindings (parent) }
219
220 depends:
221 /* empty */ { Ast.NoDep }
222 | TDepends TOn parents=dep { parents }
223
224 dep:
225 pnrule { $1 }
226 | dep TAndLog dep { Ast.AndDep($1, $3) }
227 | dep TOrLog dep { Ast.OrDep ($1, $3) }
228
229 pnrule:
230 TRuleName { Ast.Dep $1 }
231 | TBang TRuleName { Ast.AntiDep $2 }
232 | TEver TRuleName { Ast.EverDep $2 }
233 | TNever TRuleName { Ast.NeverDep $2 }
234 | TOPar dep TCPar { $2 }
235
236 choose_iso:
237 TUsing separated_nonempty_list(TComma,TString) { List.map P.id2name $2 }
238
239 disable:
240 TDisable separated_nonempty_list(TComma,pure_ident) { List.map P.id2name $2 }
241
242 exists:
243 TExists { Ast.Exists }
244 | TForall { Ast.Forall }
245 | { Ast.Undetermined }
246
247 is_expression: // for more flexible parsing of top level expressions
248 { false }
249 | TExpression { true }
250
251 include_main:
252 list(incl) TArob { $1 }
253 | list(incl) TArobArob { $1 }
254
255 incl:
256 TIncludeL { let (x,_) = $1 in Data.Include(x) }
257 | TUsing TString { Data.Iso(Common.Left(P.id2name $2)) }
258 | TUsing TPathIsoFile { Data.Iso(Common.Right $2) }
259 | TVirtual comma_list(pure_ident)
260 { let names = List.map P.id2name $2 in
261 (* ensure that the names of virtual and real rules don't overlap *)
262 List.iter
263 (function name -> Hashtbl.add Data.all_metadecls name [])
264 names;
265 Data.Virt(names) }
266
267 metadec:
268 ar=arity ispure=pure
269 kindfn=metakind ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
270 { P.create_metadec ar ispure kindfn ids }
271 | kindfn=metakind_fresh ids=comma_list(pure_ident_or_meta_ident_with_seed)
272 TMPtVirg
273 { P.create_fresh_metadec kindfn ids }
274 | ar=arity ispure=pure
275 kindfn=metakind_atomic
276 ids=comma_list(pure_ident_or_meta_ident_with_idconstraint(re_or_not_eqid))
277 TMPtVirg
278 { P.create_metadec_with_constraints ar ispure kindfn ids }
279 | ar=arity ispure=pure
280 kindfn=metakind_atomic_expi
281 ids=comma_list(pure_ident_or_meta_ident_with_econstraint(re_or_not_eqe))
282 TMPtVirg
283 { P.create_metadec_with_constraints ar ispure kindfn ids }
284 | ar=arity ispure=pure
285 kindfn=metakind_atomic_expe
286 ids=comma_list(pure_ident_or_meta_ident_with_x_eq(not_ceq)) TMPtVirg
287 { P.create_metadec_with_constraints ar ispure kindfn ids }
288 | ar=arity TPosition a=option(TPosAny)
289 ids=comma_list(pure_ident_or_meta_ident_with_x_eq(not_pos)) TMPtVirg
290 (* pb: position variables can't be inherited from normal rules, and then
291 there is no way to inherit from a generated rule, so there is no point
292 to have a position variable *)
293 { (if !Data.in_generating
294 then failwith "position variables not allowed in a generated rule file");
295 let kindfn arity name pure check_meta constraints =
296 let tok = check_meta(Ast.MetaPosDecl(arity,name)) in
297 let any = match a with None -> Ast.PER | Some _ -> Ast.ALL in
298 !Data.add_pos_meta name constraints any; tok in
299 P.create_metadec_with_constraints ar false kindfn ids }
300 | ar=arity ispure=pure
301 TParameter Tlist TOCro id=pure_ident_or_meta_ident TCCro
302 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
303 { P.create_len_metadec ar ispure
304 (fun lenname arity name pure check_meta ->
305 let tok =
306 check_meta(Ast.MetaParamListDecl(arity,name,Some lenname)) in
307 !Data.add_paramlist_meta name (Some lenname) pure; tok)
308 id ids }
309 | ar=arity ispure=pure
310 TExpression Tlist TOCro id=pure_ident_or_meta_ident TCCro
311 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
312 { P.create_len_metadec ar ispure
313 (fun lenname arity name pure check_meta ->
314 let tok =
315 check_meta(Ast.MetaExpListDecl(arity,name,Some lenname)) in
316 !Data.add_explist_meta name (Some lenname) pure; tok)
317 id ids }
318
319 %inline metakind_fresh:
320 TFresh TIdentifier
321 { (fun name check_meta seed ->
322 let tok = check_meta(Ast.MetaFreshIdDecl(name,seed)) in
323 !Data.add_fresh_id_meta name; tok) }
324
325 %inline metakind:
326 TParameter
327 { (fun arity name pure check_meta ->
328 let tok = check_meta(Ast.MetaParamDecl(arity,name)) in
329 !Data.add_param_meta name pure; tok) }
330 | TParameter Tlist
331 { (fun arity name pure check_meta ->
332 let tok = check_meta(Ast.MetaParamListDecl(arity,name,None)) in
333 !Data.add_paramlist_meta name None pure; tok) }
334 | TExpression Tlist
335 { (fun arity name pure check_meta ->
336 let tok = check_meta(Ast.MetaExpListDecl(arity,name,None)) in
337 !Data.add_explist_meta name None pure; tok) }
338 | TType
339 { (fun arity name pure check_meta ->
340 let tok = check_meta(Ast.MetaTypeDecl(arity,name)) in
341 !Data.add_type_meta name pure; tok) }
342 | TInitialiser
343 { (fun arity name pure check_meta ->
344 let tok = check_meta(Ast.MetaInitDecl(arity,name)) in
345 !Data.add_init_meta name pure; tok) }
346 | TStatement
347 { (fun arity name pure check_meta ->
348 let tok = check_meta(Ast.MetaStmDecl(arity,name)) in
349 !Data.add_stm_meta name pure; tok) }
350 | TStatement Tlist
351 { (fun arity name pure check_meta ->
352 let tok = check_meta(Ast.MetaStmListDecl(arity,name)) in
353 !Data.add_stmlist_meta name pure; tok) }
354 | TTypedef
355 { (fun arity (_,name) pure check_meta ->
356 if arity = Ast.NONE && pure = Ast0.Impure
357 then (!Data.add_type_name name; [])
358 else raise (Semantic_cocci.Semantic "bad typedef")) }
359 | TDeclarer TName
360 { (fun arity (_,name) pure check_meta ->
361 if arity = Ast.NONE && pure = Ast0.Impure
362 then (!Data.add_declarer_name name; [])
363 else raise (Semantic_cocci.Semantic "bad declarer")) }
364 | TIterator TName
365 { (fun arity (_,name) pure check_meta ->
366 if arity = Ast.NONE && pure = Ast0.Impure
367 then (!Data.add_iterator_name name; [])
368 else raise (Semantic_cocci.Semantic "bad iterator")) }
369
370 %inline metakind_atomic:
371 TIdentifier
372 { (fun arity name pure check_meta constraints ->
373 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
374 !Data.add_id_meta name constraints pure; tok) }
375 | TFunction
376 { (fun arity name pure check_meta constraints ->
377 let tok = check_meta(Ast.MetaFuncDecl(arity,name)) in
378 !Data.add_func_meta name constraints pure; tok) }
379 | TLocal TFunction
380 { (fun arity name pure check_meta constraints ->
381 let tok = check_meta(Ast.MetaLocalFuncDecl(arity,name)) in
382 !Data.add_local_func_meta name constraints pure;
383 tok) }
384 | TDeclarer
385 { (fun arity name pure check_meta constraints ->
386 let tok = check_meta(Ast.MetaDeclarerDecl(arity,name)) in
387 !Data.add_declarer_meta name constraints pure; tok) }
388 | TIterator
389 { (fun arity name pure check_meta constraints ->
390 let tok = check_meta(Ast.MetaIteratorDecl(arity,name)) in
391 !Data.add_iterator_meta name constraints pure; tok) }
392
393 %inline metakind_atomic_expi:
394 TError
395 { (fun arity name pure check_meta constraints ->
396 let tok = check_meta(Ast.MetaErrDecl(arity,name)) in
397 !Data.add_err_meta name constraints pure; tok) }
398 | l=option(TLocal) TIdExpression ty=ioption(meta_exp_type)
399 { (fun arity name pure check_meta constraints ->
400 match l with
401 None ->
402 !Data.add_idexp_meta ty name constraints pure;
403 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
404 | Some _ ->
405 !Data.add_local_idexp_meta ty name constraints pure;
406 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
407 | l=option(TLocal) TIdExpression m=nonempty_list(TMul)
408 { (fun arity name pure check_meta constraints ->
409 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
410 match l with
411 None ->
412 !Data.add_idexp_meta ty name constraints pure;
413 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
414 | Some _ ->
415 !Data.add_local_idexp_meta ty name constraints pure;
416 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
417 | TExpression m=nonempty_list(TMul)
418 { (fun arity name pure check_meta constraints ->
419 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
420 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
421 !Data.add_exp_meta ty name constraints pure; tok) }
422 | vl=meta_exp_type TOCro TCCro
423 { (fun arity name pure check_meta constraints ->
424 let ty = Some (List.map (function x -> Type_cocci.Array x) vl) in
425 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
426 !Data.add_exp_meta ty name constraints pure; tok) }
427 | TConstant ty=ioption(meta_exp_type)
428 { (fun arity name pure check_meta constraints ->
429 let tok = check_meta(Ast.MetaConstDecl(arity,name,ty)) in
430 !Data.add_const_meta ty name constraints pure; tok) }
431
432 %inline metakind_atomic_expe:
433 TExpression
434 { (fun arity name pure check_meta constraints ->
435 let tok = check_meta(Ast.MetaExpDecl(arity,name,None)) in
436 !Data.add_exp_meta None name (Ast0.NotExpCstrt constraints) pure; tok) }
437 | vl=meta_exp_type // no error if use $1 but doesn't type check
438 { (fun arity name pure check_meta constraints ->
439 let ty = Some vl in
440 List.iter
441 (function c ->
442 match Ast0.unwrap c with
443 Ast0.Constant(_) ->
444 if not
445 (List.exists
446 (function
447 Type_cocci.BaseType(Type_cocci.IntType) -> true
448 | Type_cocci.BaseType(Type_cocci.ShortType) -> true
449 | Type_cocci.BaseType(Type_cocci.LongType) -> true
450 | _ -> false)
451 vl)
452 then failwith "metavariable with int constraint must be an int"
453 | _ -> ())
454 constraints;
455 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
456 !Data.add_exp_meta ty name (Ast0.NotExpCstrt constraints) pure; tok)
457 }
458
459
460 meta_exp_type:
461 t=typedef_ctype
462 { [Ast0_cocci.ast0_type_to_type t] }
463 | TOBrace t=comma_list(ctype) TCBrace m=list(TMul)
464 { List.map
465 (function x -> P.ty_pointerify (Ast0_cocci.ast0_type_to_type x) m)
466 t }
467
468 arity: TBang0 { Ast.UNIQUE }
469 | TWhy0 { Ast.OPT }
470 | TPlus0 { Ast.MULTI }
471 | /* empty */ { Ast.NONE }
472
473 /* ---------------------------------------------------------------------- */
474
475 %inline
476 signable_types:
477 ty=Tchar
478 { Ast0.wrap(Ast0.BaseType(Ast.CharType,[P.clt2mcode "char" ty])) }
479 | ty=Tshort
480 { Ast0.wrap(Ast0.BaseType(Ast.ShortType,[P.clt2mcode "short" ty])) }
481 | ty=Tint
482 { Ast0.wrap(Ast0.BaseType(Ast.IntType,[P.clt2mcode "int" ty])) }
483 | p=TMetaType
484 { let (nm,pure,clt) = p in
485 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
486 | r=TRuleName TDot p=TIdent
487 { let nm = (r,P.id2name p) in
488 (* this is only possible when we are in a metavar decl. Otherwise,
489 it will be represented already as a MetaType *)
490 let _ = P.check_meta(Ast.MetaTypeDecl(Ast.NONE,nm)) in
491 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm (P.id2clt p),
492 Ast0.Impure (*will be ignored*))) }
493 | ty=Tlong
494 { Ast0.wrap(Ast0.BaseType(Ast.LongType,[P.clt2mcode "long" ty])) }
495 | ty1=Tlong ty2=Tlong
496 { Ast0.wrap
497 (Ast0.BaseType
498 (Ast.LongLongType,
499 [P.clt2mcode "long" ty1;P.clt2mcode "long" ty2])) }
500
501 %inline
502 non_signable_types:
503 ty=Tvoid
504 { Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" ty])) }
505 | ty=Tdouble
506 { Ast0.wrap(Ast0.BaseType(Ast.DoubleType,[P.clt2mcode "double" ty])) }
507 | ty=Tfloat
508 { Ast0.wrap(Ast0.BaseType(Ast.FloatType,[P.clt2mcode "float" ty])) }
509 | s=Tenum i=ident
510 { Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, i)) }
511 | s=struct_or_union i=ident
512 { Ast0.wrap(Ast0.StructUnionName(s, Some i)) }
513 | s=struct_or_union i=ioption(ident)
514 l=TOBrace d=struct_decl_list r=TCBrace
515 { (if i = None && !Data.in_iso
516 then failwith "structures must be named in the iso file");
517 Ast0.wrap(Ast0.StructUnionDef(Ast0.wrap(Ast0.StructUnionName(s, i)),
518 P.clt2mcode "{" l,
519 d, P.clt2mcode "}" r)) }
520 | s=TMetaType l=TOBrace d=struct_decl_list r=TCBrace
521 { let (nm,pure,clt) = s in
522 let ty = Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) in
523 Ast0.wrap(Ast0.StructUnionDef(ty,P.clt2mcode "{" l,d,P.clt2mcode "}" r)) }
524 | p=TTypeId
525 { Ast0.wrap(Ast0.TypeName(P.id2mcode p)) }
526
527 %inline
528 all_basic_types:
529 r=Tsigned ty=signable_types
530 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,Some ty)) }
531 | r=Tunsigned ty=signable_types
532 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,Some ty)) }
533 | ty=signable_types { ty }
534 | ty=non_signable_types { ty }
535
536 ctype:
537 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
538 { P.pointerify (P.make_cv cv ty) m }
539 | r=Tsigned
540 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,None)) }
541 | r=Tunsigned
542 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,None)) }
543 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
544 { let (mids,code) = t in
545 Ast0.wrap
546 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
547
548 /* signed, unsigned alone not allowed */
549 typedef_ctype:
550 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
551 { P.pointerify (P.make_cv cv ty) m }
552 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
553 { let (mids,code) = t in
554 Ast0.wrap
555 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
556
557 /* ---------------------------------------------------------------------- */
558
559 struct_or_union:
560 s=Tstruct { P.clt2mcode Ast.Struct s }
561 | u=Tunion { P.clt2mcode Ast.Union u }
562
563 struct_decl:
564 TNothing { [] }
565 | t=ctype d=d_ident pv=TPtVirg
566 { let (id,fn) = d in
567 [Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] }
568 | t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
569 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar pv=TPtVirg
570 { let (id,fn) = d in
571 let t =
572 Ast0.wrap
573 (Ast0.FunctionPointer
574 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
575 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
576 [Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] }
577 | cv=ioption(const_vol) i=pure_ident d=d_ident pv=TPtVirg
578 { let (id,fn) = d in
579 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
580 [Ast0.wrap(Ast0.UnInit(None,fn idtype,id,P.clt2mcode ";" pv))] }
581
582 struct_decl_list:
583 struct_decl_list_start { Ast0.wrap(Ast0.DOTS($1)) }
584
585 struct_decl_list_start:
586 struct_decl { $1 }
587 | struct_decl struct_decl_list_start { $1@$2 }
588 | d=edots_when(TEllipsis,struct_decl) r=continue_struct_decl_list
589 { (P.mkddots "..." d)::r }
590
591 continue_struct_decl_list:
592 /* empty */ { [] }
593 | struct_decl struct_decl_list_start { $1@$2 }
594 | struct_decl { $1 }
595
596
597 /*****************************************************************************/
598
599 /* have to inline everything to avoid conflicts? switch to proper
600 declarations, statements, and expressions for the subterms */
601
602 minus_body:
603 f=loption(filespec)
604 b=loption(minus_start)
605 /*ew=loption(error_words)*/
606 { match f@b(*@ew*) with
607 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
608 | code -> Top_level.top_level code }
609
610 plus_body:
611 f=loption(filespec)
612 b=loption(plus_start)
613 /*ew=loption(error_words)*/
614 { Top_level.top_level (f@b(*@ew*)) }
615
616 minus_exp_body:
617 f=loption(filespec)
618 b=top_eexpr
619 /*ew=loption(error_words)*/
620 { match f@[b](*@ew*) with
621 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
622 | code -> Top_level.top_level code }
623
624 plus_exp_body:
625 f=loption(filespec)
626 b=top_eexpr
627 /*ew=loption(error_words)*/
628 { Top_level.top_level (f@[b](*@ew*)) }
629
630 filespec:
631 TMinusFile TPlusFile
632 { [Ast0.wrap
633 (Ast0.FILEINFO(P.id2mcode $1,
634 P.id2mcode $2))] }
635
636 includes:
637 TIncludeL
638 { Ast0.wrap
639 (Ast0.Include(P.clt2mcode "#include"
640 (P.drop_pos (P.drop_aft (P.id2clt $1))),
641 let (arity,ln,lln,offset,col,strbef,straft,pos) =
642 P.id2clt $1 in
643 let clt =
644 (arity,ln,lln,offset,0,strbef,straft,pos) in
645 P.clt2mcode
646 (Ast.Local (Parse_aux.str2inc (P.id2name $1)))
647 (P.drop_bef clt))) }
648 | TIncludeNL
649 { Ast0.wrap
650 (Ast0.Include(P.clt2mcode "#include"
651 (P.drop_pos (P.drop_aft (P.id2clt $1))),
652 let (arity,ln,lln,offset,col,strbef,straft,pos) =
653 P.id2clt $1 in
654 let clt =
655 (arity,ln,lln,offset,0,strbef,straft,pos) in
656 P.clt2mcode
657 (Ast.NonLocal (Parse_aux.str2inc (P.id2name $1)))
658 (P.drop_bef clt))) }
659 | d=defineop t=ctype TLineEnd
660 { let ty = Ast0.wrap(Ast0.TopExp(Ast0.wrap(Ast0.TypeExp(t)))) in
661 d (Ast0.wrap(Ast0.DOTS([ty]))) }
662 | defineop b=toplevel_seq_start(toplevel_after_dots) TLineEnd
663 { let body =
664 match b with
665 [e] ->
666 (match Ast0.unwrap e with
667 Ast0.Exp(e1) ->
668 [Ast0.rewrap e (Ast0.TopExp(Ast0.set_arg_exp (e1)))]
669 | _ -> b)
670 | _ -> b in
671 $1 (Ast0.wrap(Ast0.DOTS(body))) }
672
673 defineop:
674 TDefine
675 { let (clt,ident) = $1 in
676 function body ->
677 Ast0.wrap
678 (Ast0.Define
679 (P.clt2mcode "#define" clt,
680 (match ident with
681 TMetaId((nm,constraints,pure,clt)) ->
682 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
683 | TIdent(nm_pure) ->
684 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
685 | _ ->
686 raise
687 (Semantic_cocci.Semantic
688 "unexpected name for a #define")),
689 Ast0.wrap Ast0.NoParams,
690 body)) }
691 | TDefineParam define_param_list_option TCPar
692 { let (clt,ident,parenoff,parencol) = $1 in
693 (* clt is the start of the #define itself *)
694 let (arity,line,lline,offset,col,strbef,straft,pos) = clt in
695 let lp =
696 P.clt2mcode "("
697 (arity,line,lline,parenoff,parencol,[],[],Ast0.NoMetaPos) in
698 function body ->
699 Ast0.wrap
700 (Ast0.Define
701 (P.clt2mcode "#define" clt,
702 (match ident with
703 TMetaId((nm,constraints,pure,clt)) ->
704 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
705 | TIdent(nm_pure) ->
706 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
707 | _ ->
708 raise
709 (Semantic_cocci.Semantic
710 "unexpected name for a #define")),
711 Ast0.wrap (Ast0.DParams (lp,$2,P.clt2mcode ")" $3)),body)) }
712
713 /* ---------------------------------------------------------------------- */
714
715 define_param_list: define_param_list_start
716 {let circle x =
717 match Ast0.unwrap x with Ast0.DPcircles(_) -> true | _ -> false in
718 if List.exists circle $1
719 then Ast0.wrap(Ast0.CIRCLES($1))
720 else Ast0.wrap(Ast0.DOTS($1)) }
721
722 define_param_list_start:
723 ident { [Ast0.wrap(Ast0.DParam $1)] }
724 | ident TComma define_param_list_start
725 { Ast0.wrap(Ast0.DParam $1)::
726 Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $2))::$3 }
727 | d=TEllipsis r=list(dp_comma_args(TEllipsis))
728 { (P.mkdpdots "..." d)::
729 (List.concat (List.map (function x -> x (P.mkdpdots "...")) r)) }
730
731 dp_comma_args(dotter):
732 c=TComma d=dotter
733 { function dot_builder ->
734 [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," c)); dot_builder d] }
735 | TComma ident
736 { function dot_builder ->
737 [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $1));
738 Ast0.wrap(Ast0.DParam $2)] }
739
740 define_param_list_option: define_param_list { $1 }
741 | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
742
743 /*****************************************************************************/
744
745 funproto:
746 s=ioption(storage) t=ctype
747 id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
748 { Ast0.wrap
749 (Ast0.UnInit
750 (s,
751 Ast0.wrap
752 (Ast0.FunctionType(Some t,
753 P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
754 id, P.clt2mcode ";" pt)) }
755
756 fundecl:
757 f=fninfo
758 TFunDecl i=func_ident lp=TOPar d=decl_list(decl) rp=TCPar
759 lb=TOBrace b=fun_start rb=TCBrace
760 { P.verify_parameter_declarations (Ast0.undots d);
761 Ast0.wrap(Ast0.FunDecl((Ast0.default_info(),Ast0.context_befaft()),
762 f, i,
763 P.clt2mcode "(" lp, d,
764 P.clt2mcode ")" rp,
765 P.clt2mcode "{" lb, b,
766 P.clt2mcode "}" rb)) }
767
768 fninfo:
769 /* empty */ { [] }
770 | storage fninfo
771 { try
772 let _ =
773 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
774 raise (Semantic_cocci.Semantic "duplicate storage")
775 with Not_found -> (Ast0.FStorage($1))::$2 }
776 | t=ctype r=fninfo_nt { (Ast0.FType(t))::r }
777 | Tinline fninfo
778 { try
779 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
780 raise (Semantic_cocci.Semantic "duplicate inline")
781 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
782 | Tattr fninfo
783 { try
784 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
785 raise (Semantic_cocci.Semantic "multiple attributes")
786 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
787
788 fninfo_nt:
789 /* empty */ { [] }
790 | storage fninfo_nt
791 { try
792 let _ =
793 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
794 raise (Semantic_cocci.Semantic "duplicate storage")
795 with Not_found -> (Ast0.FStorage($1))::$2 }
796 | Tinline fninfo_nt
797 { try
798 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
799 raise (Semantic_cocci.Semantic "duplicate inline")
800 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
801 | Tattr fninfo_nt
802 { try
803 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
804 raise (Semantic_cocci.Semantic "duplicate init")
805 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
806
807 storage:
808 s=Tstatic { P.clt2mcode Ast.Static s }
809 | s=Tauto { P.clt2mcode Ast.Auto s }
810 | s=Tregister { P.clt2mcode Ast.Register s }
811 | s=Textern { P.clt2mcode Ast.Extern s }
812
813 decl: t=ctype i=ident
814 { Ast0.wrap(Ast0.Param(t, Some i)) }
815 | t=ctype { (*verify in FunDecl*) Ast0.wrap(Ast0.Param(t, None)) }
816 | t=ctype lp=TOPar s=TMul i=ident rp=TCPar
817 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
818 { let fnptr =
819 Ast0.wrap
820 (Ast0.FunctionPointer
821 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
822 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
823 Ast0.wrap(Ast0.Param(fnptr, Some i)) }
824 | TMetaParam
825 { let (nm,pure,clt) = $1 in
826 Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) }
827
828 name_opt_decl:
829 decl { $1 }
830 | t=ctype lp=TOPar s=TMul rp=TCPar
831 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
832 { let fnptr =
833 Ast0.wrap
834 (Ast0.FunctionPointer
835 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
836 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
837 Ast0.wrap(Ast0.Param(fnptr, None)) }
838
839 const_vol:
840 Tconst { P.clt2mcode Ast.Const $1 }
841 | Tvolatile { P.clt2mcode Ast.Volatile $1 }
842
843 /*****************************************************************************/
844
845 statement:
846 includes { $1 } /* shouldn't be allowed to be a single_statement... */
847 | TMetaStm
848 { P.meta_stm $1 }
849 | expr TPtVirg
850 { P.exp_stm $1 $2 }
851 | TIf TOPar eexpr TCPar single_statement %prec TIf
852 { P.ifthen $1 $2 $3 $4 $5 }
853 | TIf TOPar eexpr TCPar single_statement TElse single_statement
854 { P.ifthenelse $1 $2 $3 $4 $5 $6 $7 }
855 | TFor TOPar option(eexpr) TPtVirg option(eexpr) TPtVirg
856 option(eexpr) TCPar single_statement
857 { P.forloop $1 $2 $3 $4 $5 $6 $7 $8 $9 }
858 | TWhile TOPar eexpr TCPar single_statement
859 { P.whileloop $1 $2 $3 $4 $5 }
860 | TDo single_statement TWhile TOPar eexpr TCPar TPtVirg
861 { P.doloop $1 $2 $3 $4 $5 $6 $7 }
862 | iter_ident TOPar eexpr_list_option TCPar single_statement
863 { P.iterator $1 $2 $3 $4 $5 }
864 | TSwitch TOPar eexpr TCPar TOBrace list(decl_var) list(case_line) TCBrace
865 { P.switch $1 $2 $3 $4 $5 (List.concat $6) $7 $8 }
866 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
867 | TReturn TPtVirg { P.ret $1 $2 }
868 | TBreak TPtVirg { P.break $1 $2 }
869 | TContinue TPtVirg { P.cont $1 $2 }
870 | ident TDotDot { P.label $1 $2 }
871 | TGoto ident TPtVirg { P.goto $1 $2 $3 }
872 | TOBrace fun_start TCBrace
873 { P.seq $1 $2 $3 }
874
875 stm_dots:
876 TEllipsis w=list(whenppdecs)
877 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." $1, List.concat w)) }
878 | TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
879 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." $1, b,
880 P.clt2mcode "...>" c, List.concat w, false)) }
881 | TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
882 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." $1, b,
883 P.clt2mcode "...+>" c, List.concat w, true)) }
884
885 %inline stm_dots_ell:
886 a=TEllipsis w=list(whenppdecs)
887 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." a, List.concat w)) }
888
889 %inline stm_dots_nest:
890 a=TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
891 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." a, b,
892 P.clt2mcode "...>" c, List.concat w, false)) }
893 | a=TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
894 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." a, b,
895 P.clt2mcode "...+>" c, List.concat w, true)) }
896
897 whenppdecs: w=whens(when_start,rule_elem_statement,any_strict)
898 { w }
899
900 /* a statement that fits into a single rule_elem. should nests be included?
901 what about statement metavariables? */
902 rule_elem_statement:
903 one_decl_var
904 { Ast0.wrap(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),$1)) }
905 | expr TPtVirg { P.exp_stm $1 $2 }
906 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
907 | TReturn TPtVirg { P.ret $1 $2 }
908 | TBreak TPtVirg { P.break $1 $2 }
909 | TContinue TPtVirg { P.cont $1 $2 }
910 | TOPar0 midzero_list(rule_elem_statement,rule_elem_statement) TCPar0
911 { let (mids,code) = $2 in
912 Ast0.wrap
913 (Ast0.Disj(P.clt2mcode "(" $1,
914 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
915 mids, P.clt2mcode ")" $3)) }
916
917 /* a statement on its own */
918 single_statement:
919 statement { $1 }
920 | TOPar0 midzero_list(statement,statement) TCPar0
921 /* degenerate case, elements are single statements and thus don't
922 contain dots */
923 { let (mids,code) = $2 in
924 Ast0.wrap
925 (Ast0.Disj(P.clt2mcode "(" $1,
926 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
927 mids, P.clt2mcode ")" $3)) }
928
929 case_line:
930 TDefault TDotDot fun_start
931 { Ast0.wrap
932 (Ast0.Default(P.clt2mcode "default" $1,P.clt2mcode ":" $2,$3)) }
933 | TCase eexpr TDotDot fun_start
934 { Ast0.wrap(Ast0.Case(P.clt2mcode "case" $1,$2,P.clt2mcode ":" $3,$4)) }
935 /* | lp=TOPar0 t=midzero_list(case_line,case_line) rp=TCPar0
936 { let (mids,code) = ([],[t]) in
937 Ast0.wrap
938 (Ast0.DisjCase(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) } */
939
940 /* In the following, an identifier as a type is not fully supported. Indeed,
941 the language is ambiguous: what is foo * bar; */
942 /* The AST DisjDecl cannot be generated because it would be ambiguous with
943 a disjunction on a statement with a declaration in each branch */
944 decl_var:
945 t=ctype pv=TPtVirg
946 { [Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv))] }
947 | s=ioption(storage) t=ctype d=comma_list(d_ident) pv=TPtVirg
948 { List.map
949 (function (id,fn) ->
950 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)))
951 d }
952 | f=funproto { [f] }
953 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
954 {let (id,fn) = d in
955 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
956 /* type is a typedef name */
957 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
958 d=comma_list(d_ident) pv=TPtVirg
959 { List.map
960 (function (id,fn) ->
961 let idtype =
962 P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
963 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)))
964 d }
965 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
966 e=initialize pv=TPtVirg
967 { let (id,fn) = d in
968 !Data.add_type_name (P.id2name i);
969 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
970 [Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
971 P.clt2mcode ";" pv))] }
972 /* function pointer type */
973 | s=ioption(storage)
974 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
975 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
976 pv=TPtVirg
977 { let (id,fn) = d in
978 let t =
979 Ast0.wrap
980 (Ast0.FunctionPointer
981 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
982 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
983 [Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv))] }
984 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
985 { [Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
986 P.clt2mcode ")" $4,P.clt2mcode ";" $5))] }
987 | s=ioption(storage)
988 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
989 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
990 q=TEq e=initialize pv=TPtVirg
991 { let (id,fn) = d in
992 let t =
993 Ast0.wrap
994 (Ast0.FunctionPointer
995 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
996 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
997 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
998 | s=Ttypedef t=typedef_ctype id=comma_list(typedef_ident) pv=TPtVirg
999 { let s = P.clt2mcode "typedef" s in
1000 List.map
1001 (function id ->
1002 Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv)))
1003 id }
1004
1005 one_decl_var:
1006 t=ctype pv=TPtVirg
1007 { Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv)) }
1008 | s=ioption(storage) t=ctype d=d_ident pv=TPtVirg
1009 { let (id,fn) = d in
1010 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1011 | f=funproto { f }
1012 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
1013 { let (id,fn) = d in
1014 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv)) }
1015 /* type is a typedef name */
1016 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
1017 d=d_ident pv=TPtVirg
1018 { let (id,fn) = d in
1019 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1020 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)) }
1021 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
1022 e=initialize pv=TPtVirg
1023 { let (id,fn) = d in
1024 !Data.add_type_name (P.id2name i);
1025 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1026 Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
1027 P.clt2mcode ";" pv)) }
1028 /* function pointer type */
1029 | s=ioption(storage)
1030 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1031 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1032 pv=TPtVirg
1033 { let (id,fn) = d in
1034 let t =
1035 Ast0.wrap
1036 (Ast0.FunctionPointer
1037 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1038 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1039 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1040 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
1041 { Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
1042 P.clt2mcode ")" $4,P.clt2mcode ";" $5)) }
1043 | s=ioption(storage)
1044 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1045 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1046 q=TEq e=initialize pv=TPtVirg
1047 { let (id,fn) = d in
1048 let t =
1049 Ast0.wrap
1050 (Ast0.FunctionPointer
1051 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1052 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1053 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))}
1054
1055
1056 d_ident:
1057 ident list(array_dec)
1058 { ($1,
1059 function t ->
1060 List.fold_right
1061 (function (l,i,r) ->
1062 function rest ->
1063 Ast0.wrap
1064 (Ast0.Array(rest,P.clt2mcode "[" l,i,P.clt2mcode "]" r)))
1065 $2 t) }
1066
1067 array_dec: l=TOCro i=option(eexpr) r=TCCro { (l,i,r) }
1068
1069 initialize:
1070 eexpr
1071 { Ast0.wrap(Ast0.InitExpr($1)) }
1072 | TOBrace initialize_list TCBrace
1073 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1074 | TOBrace TCBrace
1075 { Ast0.wrap
1076 (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []),
1077 P.clt2mcode "}" $2)) }
1078 | TMetaInit
1079 {let (nm,pure,clt) = $1 in
1080 Ast0.wrap(Ast0.MetaInit(P.clt2mcode nm clt,pure)) }
1081
1082 initialize2:
1083 /*arithexpr and not eexpr because can have ambiguity with comma*/
1084 /*dots and nests probably not allowed at top level, haven't looked into why*/
1085 arith_expr(eexpr,invalid) { Ast0.wrap(Ast0.InitExpr($1)) }
1086 | TOBrace initialize_list TCBrace
1087 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1088 | TOBrace TCBrace
1089 { Ast0.wrap
1090 (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []),
1091 P.clt2mcode "}" $2)) }
1092 /* gccext:, labeled elements */
1093 | list(designator) TEq initialize2
1094 { Ast0.wrap(Ast0.InitGccExt($1,P.clt2mcode "=" $2,$3)) }
1095 | ident TDotDot initialize2
1096 { Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */
1097
1098 designator:
1099 | TDot ident
1100 { Ast0.DesignatorField (P.clt2mcode "." $1,$2) }
1101 | TOCro eexpr TCCro
1102 { Ast0.DesignatorIndex (P.clt2mcode "[" $1,$2,P.clt2mcode "]" $3) }
1103 | TOCro eexpr TEllipsis eexpr TCCro
1104 { Ast0.DesignatorRange (P.clt2mcode "[" $1,$2,P.clt2mcode "..." $3,
1105 $4,P.clt2mcode "]" $5) }
1106
1107 initialize_list:
1108 initialize_list_start { Ast0.wrap(Ast0.DOTS($1)) }
1109
1110 initialize_list_start:
1111 initialize2 TComma { [$1;Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))] }
1112 | initialize2 TComma initialize_list_start
1113 { $1::Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))::$3 }
1114 | d=edots_when(TEllipsis,initialize)
1115 r=comma_initializers(edots_when(TEllipsis,initialize))
1116 { (P.mkidots "..." d)::
1117 (List.concat(List.map (function x -> x (P.mkidots "...")) r)) }
1118
1119 comma_initializers(dotter):
1120 /* empty */ { [] }
1121 | d=dotter r=comma_initializers2(dotter)
1122 { (function dot_builder -> [dot_builder d])::r }
1123 | i=initialize2 c=TComma r=comma_initializers(dotter)
1124 { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
1125 r }
1126
1127 comma_initializers2(dotter):
1128 /* empty */ { [] }
1129 | i=initialize2 c=TComma r=comma_initializers(dotter)
1130 { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
1131 r }
1132
1133 /* a statement that is part of a list */
1134 decl_statement:
1135 TMetaStmList
1136 { let (nm,pure,clt) = $1 in
1137 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1138 | decl_var
1139 { List.map
1140 (function x ->
1141 Ast0.wrap
1142 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1143 $1 }
1144 | statement { [$1] }
1145 /* this doesn't allow expressions at top level, because the parser doesn't
1146 know whether there is one. If there is one, this is not sequencible.
1147 If there is not one, then it is. It seems complicated to get around
1148 this at the parser level. We would have to have a check afterwards to
1149 allow this. One case where this would be useful is for a when. Now
1150 we allow a sequence of whens, so one can be on only statements and
1151 one can be on only expressions. */
1152 | TOPar0 t=midzero_list(fun_start,fun_start) TCPar0
1153 { let (mids,code) = t in
1154 if List.for_all
1155 (function x ->
1156 match Ast0.unwrap x with Ast0.DOTS([]) -> true | _ -> false)
1157 code
1158 then []
1159 else
1160 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, code, mids,
1161 P.clt2mcode ")" $3))] }
1162
1163 /* a statement that is part of a list */
1164 decl_statement_expr:
1165 TMetaStmList
1166 { let (nm,pure,clt) = $1 in
1167 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1168 | decl_var
1169 { List.map
1170 (function x ->
1171 Ast0.wrap
1172 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1173 $1 }
1174 | statement { [$1] }
1175 /* this doesn't allow expressions at top level, because the parser doesn't
1176 know whether there is one. If there is one, this is not sequencible.
1177 If there is not one, then it is. It seems complicated to get around
1178 this at the parser level. We would have to have a check afterwards to
1179 allow this. One case where this would be useful is for a when. Now
1180 we allow a sequence of whens, so one can be on only statements and
1181 one can be on only expressions. */
1182 | TOPar0 t=midzero_list(fun_after_stm,fun_after_dots_or) TCPar0
1183 { let (mids,code) = t in
1184 if List.for_all (function [] -> true | _ -> false) code
1185 then []
1186 else
1187 let dot_code =
1188 List.map (function x -> Ast0.wrap(Ast0.DOTS x)) code in
1189 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, dot_code, mids,
1190 P.clt2mcode ")" $3))] }
1191
1192 /*****************************************************************************/
1193
1194 /* The following cannot contain <... ...> at the top level. This can only
1195 be allowed as an expression when the expression is delimited on both sides
1196 by expression-specific markers. In that case, the rule eexpr is used, which
1197 allows <... ...> anywhere. Hopefully, this will not be too much of a problem
1198 in practice. */
1199 expr: basic_expr(expr,invalid) { $1 }
1200 /* allows ... and nests */
1201 eexpr: basic_expr(eexpr,dot_expressions) { $1 }
1202 /* allows nests but not .... */
1203 dexpr: basic_expr(eexpr,nest_expressions) { $1 }
1204
1205 top_eexpr:
1206 eexpr { Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))) }
1207
1208 invalid:
1209 TInvalid { raise (Semantic_cocci.Semantic "not matchable") }
1210
1211 dot_expressions:
1212 TEllipsis { Ast0.wrap(Ast0.Edots(P.clt2mcode "..." $1,None)) }
1213 | nest_expressions { $1 }
1214
1215 /* not clear what whencode would mean, so just drop it */
1216 nest_expressions:
1217 TOEllipsis e=expr_dots(TEllipsis) c=TCEllipsis
1218 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<..." $1,
1219 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1220 P.clt2mcode "...>" c, None, false)) }
1221 | TPOEllipsis e=expr_dots(TEllipsis) c=TPCEllipsis
1222 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<+..." $1,
1223 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1224 P.clt2mcode "...+>" c, None, true)) }
1225
1226 //whenexp: TWhen TNotEq w=eexpr TLineEnd { w }
1227
1228 basic_expr(recurser,primary_extra):
1229 assign_expr(recurser,primary_extra) { $1 }
1230
1231 assign_expr(r,pe):
1232 cond_expr(r,pe) { $1 }
1233 | unary_expr(r,pe) TAssign assign_expr_bis
1234 { let (op,clt) = $2 in
1235 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1236 Ast0.set_arg_exp $3,false)) }
1237 | unary_expr(r,pe) TEq assign_expr_bis
1238 { Ast0.wrap
1239 (Ast0.Assignment
1240 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1241
1242 assign_expr_bis:
1243 cond_expr(eexpr,dot_expressions) { $1 }
1244 | unary_expr(eexpr,dot_expressions) TAssign assign_expr_bis
1245 { let (op,clt) = $2 in
1246 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1247 Ast0.set_arg_exp $3,false)) }
1248 | unary_expr(eexpr,dot_expressions) TEq assign_expr_bis
1249 { Ast0.wrap
1250 (Ast0.Assignment
1251 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1252
1253 cond_expr(r,pe):
1254 arith_expr(r,pe) { $1 }
1255 | l=arith_expr(r,pe) w=TWhy t=option(eexpr) dd=TDotDot r=cond_expr(r,pe)
1256 { Ast0.wrap(Ast0.CondExpr (l, P.clt2mcode "?" w, t,
1257 P.clt2mcode ":" dd, r)) }
1258
1259 arith_expr(r,pe):
1260 cast_expr(r,pe) { $1 }
1261 | arith_expr(r,pe) TMul arith_expr(r,pe)
1262 { P.arith_op Ast.Mul $1 $2 $3 }
1263 | arith_expr(r,pe) TDmOp arith_expr(r,pe)
1264 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1265 | arith_expr(r,pe) TPlus arith_expr(r,pe)
1266 { P.arith_op Ast.Plus $1 $2 $3 }
1267 | arith_expr(r,pe) TMinus arith_expr(r,pe)
1268 { P.arith_op Ast.Minus $1 $2 $3 }
1269 | arith_expr(r,pe) TShOp arith_expr(r,pe)
1270 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1271 | arith_expr(r,pe) TLogOp arith_expr(r,pe)
1272 { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
1273 | arith_expr(r,pe) TEqEq arith_expr(r,pe)
1274 { P.logic_op Ast.Eq $1 $2 $3 }
1275 | arith_expr(r,pe) TNotEq arith_expr(r,pe)
1276 { P.logic_op Ast.NotEq $1 $2 $3 }
1277 | arith_expr(r,pe) TAnd arith_expr(r,pe)
1278 { P.arith_op Ast.And $1 $2 $3 }
1279 | arith_expr(r,pe) TOr arith_expr(r,pe)
1280 { P.arith_op Ast.Or $1 $2 $3 }
1281 | arith_expr(r,pe) TXor arith_expr(r,pe)
1282 { P.arith_op Ast.Xor $1 $2 $3 }
1283 | arith_expr(r,pe) TAndLog arith_expr(r,pe)
1284 { P.logic_op Ast.AndLog $1 $2 $3 }
1285 | arith_expr(r,pe) TOrLog arith_expr(r,pe)
1286 { P.logic_op Ast.OrLog $1 $2 $3 }
1287
1288 cast_expr(r,pe):
1289 unary_expr(r,pe) { $1 }
1290 | lp=TOPar t=ctype rp=TCPar e=cast_expr(r,pe)
1291 { Ast0.wrap(Ast0.Cast (P.clt2mcode "(" lp, t,
1292 P.clt2mcode ")" rp, e)) }
1293
1294 unary_expr(r,pe):
1295 postfix_expr(r,pe) { $1 }
1296 | TInc unary_expr(r,pe)
1297 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
1298 | TDec unary_expr(r,pe)
1299 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
1300 | unary_op cast_expr(r,pe)
1301 { let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
1302 | TBang unary_expr(r,pe)
1303 { let mcode = P.clt2mcode Ast.Not $1 in
1304 Ast0.wrap(Ast0.Unary($2, mcode)) }
1305 | TSizeof unary_expr(r,pe)
1306 { Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
1307 | s=TSizeof lp=TOPar t=ctype rp=TCPar
1308 { Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
1309 P.clt2mcode "(" lp,t,
1310 P.clt2mcode ")" rp)) }
1311
1312 unary_op: TAnd { P.clt2mcode Ast.GetRef $1 }
1313 | TMul { P.clt2mcode Ast.DeRef $1 }
1314 | TPlus { P.clt2mcode Ast.UnPlus $1 }
1315 | TMinus { P.clt2mcode Ast.UnMinus $1 }
1316 | TTilde { P.clt2mcode Ast.Tilde $1 }
1317
1318 postfix_expr(r,pe):
1319 primary_expr(r,pe) { $1 }
1320 | postfix_expr(r,pe) TOCro eexpr TCCro
1321 { Ast0.wrap(Ast0.ArrayAccess ($1,P.clt2mcode "[" $2,$3,
1322 P.clt2mcode "]" $4)) }
1323 | postfix_expr(r,pe) TDot ident
1324 { Ast0.wrap(Ast0.RecordAccess($1, P.clt2mcode "." $2, $3)) }
1325 | postfix_expr(r,pe) TPtrOp ident
1326 { Ast0.wrap(Ast0.RecordPtAccess($1, P.clt2mcode "->" $2,
1327 $3)) }
1328 | postfix_expr(r,pe) TInc
1329 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Inc $2)) }
1330 | postfix_expr(r,pe) TDec
1331 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Dec $2)) }
1332 | postfix_expr(r,pe) TOPar eexpr_list_option TCPar
1333 { Ast0.wrap(Ast0.FunCall($1,P.clt2mcode "(" $2,
1334 $3,
1335 P.clt2mcode ")" $4)) }
1336
1337 primary_expr(recurser,primary_extra):
1338 func_ident { Ast0.wrap(Ast0.Ident($1)) }
1339 | TInt
1340 { let (x,clt) = $1 in
1341 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1342 | TFloat
1343 { let (x,clt) = $1 in
1344 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Float x) clt)) }
1345 | TString
1346 { let (x,clt) = $1 in
1347 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.String x) clt)) }
1348 | TChar
1349 { let (x,clt) = $1 in
1350 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Char x) clt)) }
1351 | TMetaConst
1352 { let (nm,constraints,pure,ty,clt) = $1 in
1353 Ast0.wrap
1354 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
1355 | TMetaErr
1356 { let (nm,constraints,pure,clt) = $1 in
1357 Ast0.wrap(Ast0.MetaErr(P.clt2mcode nm clt,constraints,pure)) }
1358 | TMetaExp
1359 { let (nm,constraints,pure,ty,clt) = $1 in
1360 Ast0.wrap
1361 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
1362 | TMetaIdExp
1363 { let (nm,constraints,pure,ty,clt) = $1 in
1364 Ast0.wrap
1365 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
1366 | TMetaLocalIdExp
1367 { let (nm,constraints,pure,ty,clt) = $1 in
1368 Ast0.wrap
1369 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.LocalID,pure)) }
1370 | TOPar eexpr TCPar
1371 { Ast0.wrap(Ast0.Paren(P.clt2mcode "(" $1,$2,
1372 P.clt2mcode ")" $3)) }
1373 | TOPar0 midzero_list(recurser,eexpr) TCPar0
1374 { let (mids,code) = $2 in
1375 Ast0.wrap(Ast0.DisjExpr(P.clt2mcode "(" $1,
1376 code, mids,
1377 P.clt2mcode ")" $3)) }
1378 | primary_extra { $1 }
1379
1380 expr_dots(dotter):
1381 r=no_dot_start_end(dexpr,edots_when(dotter,eexpr)) { r }
1382
1383 // used in NEST
1384 no_dot_start_end(grammar,dotter):
1385 g=grammar dg=list(pair(dotter,grammar))
1386 { function dot_builder ->
1387 g :: (List.concat(List.map (function (d,g) -> [dot_builder d;g]) dg)) }
1388
1389 /*****************************************************************************/
1390
1391 pure_ident:
1392 TIdent { $1 }
1393
1394 meta_ident:
1395 TRuleName TDot pure_ident { (Some $1,P.id2name $3) }
1396
1397 pure_ident_or_meta_ident:
1398 pure_ident { (None,P.id2name $1) }
1399 | meta_ident { $1 }
1400 | TIdentifier { (None, "identifier") }
1401 | TExpression { (None, "expression") }
1402 | TStatement { (None, "statement") }
1403 | TFunction { (None, "function") }
1404 | TLocal { (None, "local") }
1405 | TType { (None, "type") }
1406 | TParameter { (None, "parameter") }
1407 | TIdExpression { (None, "idexpression") }
1408 | TInitialiser { (None, "initialiser") }
1409 | Tlist { (None, "list") }
1410 | TFresh { (None, "fresh") }
1411 | TConstant { (None, "constant") }
1412 | TError { (None, "error") }
1413 | TWords { (None, "words") }
1414 | TPure { (None, "pure") }
1415 | TContext { (None, "context") }
1416 | TGenerated { (None, "generated") }
1417 | TTypedef { (None, "typedef") }
1418 | TDeclarer { (None, "declarer") }
1419 | TIterator { (None, "iterator") }
1420 | TName { (None, "name") }
1421 | TPosition { (None, "position") }
1422
1423 pure_ident_or_meta_ident_with_seed:
1424 pure_ident_or_meta_ident { ($1,Ast.NoVal) }
1425 | pure_ident_or_meta_ident TEq
1426 separated_nonempty_list(TCppConcatOp,seed_elem)
1427 { match $3 with
1428 [Ast.SeedString s] -> ($1,Ast.StringSeed s)
1429 | _ -> ($1,Ast.ListSeed $3) }
1430
1431 seed_elem:
1432 TString { let (x,_) = $1 in Ast.SeedString x }
1433 | TMetaId { let (x,_,_,_) = $1 in Ast.SeedId x }
1434 | TRuleName TDot pure_ident
1435 { let nm = ($1,P.id2name $3) in
1436 P.check_meta(Ast.MetaIdDecl(Ast.NONE,nm));
1437 Ast.SeedId nm }
1438
1439 pure_ident_or_meta_ident_with_x_eq(x_eq):
1440 i=pure_ident_or_meta_ident l=loption(x_eq)
1441 {
1442 (i, l)
1443 }
1444
1445 pure_ident_or_meta_ident_with_econstraint(x_eq):
1446 i=pure_ident_or_meta_ident optc=option(x_eq)
1447 {
1448 match optc with
1449 None -> (i, Ast0.NoConstraint)
1450 | Some c -> (i, c)
1451 }
1452
1453 pure_ident_or_meta_ident_with_idconstraint(constraint_type):
1454 i=pure_ident_or_meta_ident c=option(constraint_type)
1455 {
1456 match c with
1457 None -> (i, Ast.IdNoConstraint)
1458 | Some constraint_ -> (i,constraint_)
1459 }
1460
1461 re_or_not_eqid:
1462 re=regexp_eqid {re}
1463 | ne=not_eqid {ne}
1464
1465 regexp_eqid:
1466 TTildeEq re=TString
1467 { (if !Data.in_iso
1468 then failwith "constraints not allowed in iso file");
1469 (if !Data.in_generating
1470 then failwith "constraints not allowed in a generated rule file");
1471 let (s,_) = re in Ast.IdRegExp (s,Str.regexp s)
1472 }
1473 | TTildeExclEq re=TString
1474 { (if !Data.in_iso
1475 then failwith "constraints not allowed in iso file");
1476 (if !Data.in_generating
1477 then failwith "constraints not allowed in a generated rule file");
1478 let (s,_) = re in Ast.IdNotRegExp (s,Str.regexp s)
1479 }
1480
1481 not_eqid:
1482 TNotEq i=pure_ident
1483 { (if !Data.in_iso
1484 then failwith "constraints not allowed in iso file");
1485 (if !Data.in_generating
1486 (* pb: constraints not stored with metavars; too lazy to search for
1487 them in the pattern *)
1488 then failwith "constraints not allowed in a generated rule file");
1489 Ast.IdNegIdSet([fst i]) }
1490 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1491 { (if !Data.in_iso
1492 then failwith "constraints not allowed in iso file");
1493 (if !Data.in_generating
1494 then failwith "constraints not allowed in a generated rule file");
1495 Ast.IdNegIdSet(List.map fst l)
1496 }
1497
1498 re_or_not_eqe:
1499 re=regexp_eqid {Ast0.NotIdCstrt (re)}
1500 | ne=not_eqe {Ast0.NotExpCstrt (ne)}
1501
1502 not_eqe:
1503 TNotEq i=pure_ident
1504 { (if !Data.in_iso
1505 then failwith "constraints not allowed in iso file");
1506 (if !Data.in_generating
1507 then failwith "constraints not allowed in a generated rule file");
1508 [Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))]
1509 }
1510 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1511 { (if !Data.in_iso
1512 then failwith "constraints not allowed in iso file");
1513 (if !Data.in_generating
1514 then failwith "constraints not allowed in a generated rule file");
1515 List.map
1516 (function i ->
1517 Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))))
1518 l
1519 }
1520
1521 not_ceq:
1522 TNotEq i=ident_or_const
1523 { (if !Data.in_iso
1524 then failwith "constraints not allowed in iso file");
1525 (if !Data.in_generating
1526 then failwith "constraints not allowed in a generated rule file");
1527 [i] }
1528 | TNotEq TOBrace l=comma_list(ident_or_const) TCBrace
1529 { (if !Data.in_iso
1530 then failwith "constraints not allowed in iso file");
1531 (if !Data.in_generating
1532 then failwith "constraints not allowed in a generated rule file");
1533 l }
1534
1535 ident_or_const:
1536 i=pure_ident { Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))) }
1537 | TInt
1538 { let (x,clt) = $1 in
1539 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1540
1541 not_pos:
1542 TNotEq i=meta_ident
1543 { (if !Data.in_iso
1544 then failwith "constraints not allowed in iso file");
1545 (if !Data.in_generating
1546 then failwith "constraints not allowed in a generated rule file");
1547 match i with
1548 (None,_) -> failwith "constraint must be an inherited variable"
1549 | (Some rule,name) ->
1550 let i = (rule,name) in
1551 P.check_meta(Ast.MetaPosDecl(Ast.NONE,i));
1552 [i] }
1553 | TNotEq TOBrace l=comma_list(meta_ident) TCBrace
1554 { (if !Data.in_iso
1555 then failwith "constraints not allowed in iso file");
1556 (if !Data.in_generating
1557 then failwith "constraints not allowed in a generated rule file");
1558 List.map
1559 (function
1560 (None,_) ->
1561 failwith "constraint must be an inherited variable"
1562 | (Some rule,name) ->
1563 let i = (rule,name) in
1564 P.check_meta(Ast.MetaPosDecl(Ast.NONE,i));
1565 i)
1566 l }
1567
1568 func_ident: pure_ident
1569 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1570 | TMetaId
1571 { let (nm,constraints,pure,clt) = $1 in
1572 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1573 | TMetaFunc
1574 { let (nm,constraints,pure,clt) = $1 in
1575 Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
1576 | TMetaLocalFunc
1577 { let (nm,constraints,pure,clt) = $1 in
1578 Ast0.wrap
1579 (Ast0.MetaLocalFunc(P.clt2mcode nm clt,constraints,pure)) }
1580
1581 ident: pure_ident
1582 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1583 | TMetaId
1584 { let (nm,constraints,pure,clt) = $1 in
1585 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1586
1587 decl_ident:
1588 TDeclarerId
1589 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1590 | TMetaDeclarer
1591 { let (nm,constraints,pure,clt) = $1 in
1592 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1593
1594 iter_ident:
1595 TIteratorId
1596 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
1597 | TMetaIterator
1598 { let (nm,constraints,pure,clt) = $1 in
1599 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
1600
1601 typedef_ident:
1602 pure_ident
1603 { Ast0.wrap(Ast0.TypeName(P.id2mcode $1)) }
1604 | TMetaType
1605 { let (nm,pure,clt) = $1 in
1606 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
1607
1608 /*****************************************************************************/
1609
1610 decl_list(decl):
1611 /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
1612 | decl_list_start(decl)
1613 {let circle x =
1614 match Ast0.unwrap x with Ast0.Pcircles(_) -> true | _ -> false in
1615 if List.exists circle $1
1616 then Ast0.wrap(Ast0.CIRCLES($1))
1617 else Ast0.wrap(Ast0.DOTS($1)) }
1618
1619 decl_list_start(decl):
1620 one_dec(decl) { [$1] }
1621 | one_dec(decl) TComma decl_list_start(decl)
1622 { $1::Ast0.wrap(Ast0.PComma(P.clt2mcode "," $2))::$3 }
1623 | TEllipsis list(comma_decls(TEllipsis,decl))
1624 { Ast0.wrap(Ast0.Pdots(P.clt2mcode "..." $1))::
1625 (List.concat(List.map (function x -> x (P.mkpdots "...")) $2)) }
1626
1627 one_dec(decl):
1628 decl { $1 }
1629 | TMetaParamList
1630 { let (nm,lenname,pure,clt) = $1 in
1631 let nm = P.clt2mcode nm clt in
1632 let lenname =
1633 match lenname with
1634 Some nm -> Some(P.clt2mcode nm clt)
1635 | None -> None in
1636 Ast0.wrap(Ast0.MetaParamList(nm,lenname,pure)) }
1637
1638 comma_decls(dotter,decl):
1639 TComma dotter
1640 { function dot_builder ->
1641 [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1));
1642 dot_builder $2] }
1643 | TComma one_dec(decl)
1644 { function dot_builder ->
1645 [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1)); $2] }
1646
1647 /* ---------------------------------------------------------------------- */
1648
1649 /* error words make it complicated to be able to use error as a metavariable
1650 name or a type in a metavariable list; for that we would like to allow TError
1651 as an ident, but that makes conflicts with this rule. To add back error words,
1652 need to find some appropriate delimiter for it, but it has not been used much
1653 so just drop it */
1654 /*error_words:
1655 TError TWords TEq TOCro cl=comma_list(dexpr) TCCro
1656 { [Ast0.wrap(Ast0.ERRORWORDS(cl))] }
1657 */
1658
1659 /* ---------------------------------------------------------------------- */
1660 /* sequences of statements and expressions */
1661
1662 /* There are number of cases that must be considered:
1663
1664 1. Top level:
1665 Dots and nests allowed at the beginning or end
1666 Expressions allowed at the beginning or end
1667 One function allowed, by itself
1668 2. A function body:
1669 Dots and nests allowed at the beginning or end
1670 Expressions not allowed at the beginning or end
1671 Functions not allowed
1672 3. The body of a nest:
1673 Dots and nests not allowed at the beginning or end
1674 Expressions allowed at the beginning or end
1675 Functions not allowed
1676 4. Whencode:
1677 Dots and nests not allowed at the beginning but allowed at the end
1678 Expressions allowed at the beginning or end
1679 Functions not allowed
1680
1681 These are implemented by the rules minus_toplevel_sequence,
1682 plus_toplevel_sequence, function_body_sequence, nest_body_sequence, and
1683 when_body_sequence.
1684 */
1685 /* ------------------------------------------------------------------------ */
1686 /* Minus top level */
1687
1688 /* doesn't allow only ... */
1689 minus_start:
1690 fundecl { [Ast0.wrap(Ast0.DECL($1))] }
1691 | ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1692 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1693 | toplevel_seq_startne(toplevel_after_dots_init)
1694 { List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1 }
1695
1696 toplevel_seq_startne(after_dots_init):
1697 a=stm_dots_ell b=after_dots_init { a::b }
1698 | a=stm_dots_nest b=after_dots_init { a::b }
1699 | a=stm_dots_nest { [a] }
1700 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1701 | decl_statement_expr toplevel_after_stm { $1@$2 }
1702
1703 toplevel_seq_start(after_dots_init):
1704 stm_dots after_dots_init { $1::$2 }
1705 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
1706 | decl_statement_expr toplevel_after_stm { $1@$2 }
1707
1708 toplevel_after_dots_init:
1709 TNothing toplevel_after_exp {$2}
1710 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1711 | decl_statement_expr toplevel_after_stm {$1@$2}
1712
1713 toplevel_after_exp:
1714 /* empty */ {[]}
1715 | stm_dots toplevel_after_dots {$1::$2}
1716
1717 toplevel_after_dots:
1718 /* empty */ {[]}
1719 | TNothing toplevel_after_exp {$2}
1720 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1721 | decl_statement_expr toplevel_after_stm {$1@$2}
1722
1723 toplevel_after_stm:
1724 /* empty */ {[]}
1725 | stm_dots toplevel_after_dots {$1::$2}
1726 | decl_statement toplevel_after_stm {$1@$2}
1727
1728 top_init:
1729 TOInit initialize_list TCBrace
1730 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1731
1732 /* ------------------------------------------------------------------------ */
1733 /* Plus top level */
1734
1735 /* does allow only ... also allows multiple top-level functions */
1736 plus_start:
1737 ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1738 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
1739 | stm_dots plus_after_dots
1740 { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1741 | expr plus_after_exp
1742 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1743 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1744 | decl_statement_expr plus_after_stm
1745 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1746
1747 plus_after_exp:
1748 /* empty */ {[]}
1749 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1750
1751 plus_after_dots:
1752 /* empty */ {[]}
1753 | TNothing plus_after_exp {$2}
1754 | expr plus_after_exp
1755 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
1756 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1757 | decl_statement_expr plus_after_stm
1758 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1759
1760 plus_after_stm:
1761 /* empty */ {[]}
1762 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1763 | fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
1764 | decl_statement plus_after_stm
1765 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
1766
1767 /* ------------------------------------------------------------------------ */
1768 /* Function body */
1769
1770 fun_start:
1771 fun_after_stm { Ast0.wrap(Ast0.DOTS($1)) }
1772
1773 fun_after_stm:
1774 /* empty */ {[]}
1775 | stm_dots fun_after_dots {$1::$2}
1776 | decl_statement fun_after_stm {$1@$2}
1777
1778 fun_after_dots:
1779 /* empty */ {[]}
1780 | TNothing fun_after_exp {$2}
1781 | expr fun_after_exp {Ast0.wrap(Ast0.Exp($1))::$2}
1782 | decl_statement_expr fun_after_stm {$1@$2}
1783
1784 fun_after_exp:
1785 stm_dots fun_after_dots {$1::$2}
1786
1787 /* hack to allow mixing statements and expressions in an or */
1788 fun_after_dots_or:
1789 /* empty */ {[]}
1790 | TNothing fun_after_exp_or {$2}
1791 | expr fun_after_exp_or {Ast0.wrap(Ast0.Exp($1))::$2}
1792 | decl_statement_expr fun_after_stm {$1@$2}
1793
1794 fun_after_exp_or:
1795 /* empty */ {[]}
1796 | stm_dots fun_after_dots {$1::$2}
1797
1798 /* ------------------------------------------------------------------------ */
1799 /* Nest body */
1800
1801 nest_start:
1802 nest_after_dots { Ast0.wrap(Ast0.DOTS($1)) }
1803
1804 nest_after_dots:
1805 decl_statement_expr nest_after_stm {$1@$2}
1806 | TNothing nest_after_exp {$2}
1807 | expr nest_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
1808
1809 nest_after_stm:
1810 /* empty */ {[]}
1811 | stm_dots nest_after_dots {$1::$2}
1812 | decl_statement nest_after_stm {$1@$2}
1813
1814 nest_after_exp:
1815 /* empty */ {[]}
1816 | stm_dots nest_after_dots {$1::$2}
1817
1818 /* ------------------------------------------------------------------------ */
1819 /*Whencode*/
1820
1821 when_start:
1822 expr toplevel_after_exp
1823 { Ast0.wrap(Ast0.DOTS((Ast0.wrap(Ast0.Exp($1)))::$2)) }
1824 | decl_statement toplevel_after_stm
1825 { Ast0.wrap(Ast0.DOTS($1@$2)) }
1826
1827 /* ---------------------------------------------------------------------- */
1828
1829 eexpr_list:
1830 eexpr_list_start
1831 {let circle x =
1832 match Ast0.unwrap x with Ast0.Ecircles(_) -> true | _ -> false in
1833 let star x =
1834 match Ast0.unwrap x with Ast0.Estars(_) -> true | _ -> false in
1835 if List.exists circle $1
1836 then Ast0.wrap(Ast0.CIRCLES($1))
1837 else
1838 if List.exists star $1
1839 then Ast0.wrap(Ast0.STARS($1))
1840 else Ast0.wrap(Ast0.DOTS($1)) }
1841
1842 /* arg expr. may contain a type or a explist metavariable */
1843 aexpr:
1844 eexpr
1845 { Ast0.set_arg_exp $1 }
1846 | TMetaExpList
1847 { let (nm,lenname,pure,clt) = $1 in
1848 let nm = P.clt2mcode nm clt in
1849 let lenname =
1850 match lenname with
1851 Some nm -> Some(P.clt2mcode nm clt)
1852 | None -> None in
1853 Ast0.wrap(Ast0.MetaExprList(nm,lenname,pure)) }
1854 | ctype
1855 { Ast0.set_arg_exp(Ast0.wrap(Ast0.TypeExp($1))) }
1856
1857 eexpr_list_start:
1858 aexpr { [$1] }
1859 | aexpr TComma eexpr_list_start
1860 { $1::Ast0.wrap(Ast0.EComma(P.clt2mcode "," $2))::$3 }
1861
1862 comma_args(dotter):
1863 c=TComma d=dotter
1864 { function dot_builder ->
1865 [Ast0.wrap(Ast0.EComma(P.clt2mcode "," c)); dot_builder d] }
1866 | TComma aexpr
1867 { function dot_builder ->
1868 [Ast0.wrap(Ast0.EComma(P.clt2mcode "," $1)); $2] }
1869
1870 eexpr_list_option: eexpr_list { $1 }
1871 | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
1872
1873 /****************************************************************************/
1874
1875 // non-empty lists - drop separator
1876 comma_list(elem):
1877 separated_nonempty_list(TComma,elem) { $1 }
1878
1879 midzero_list(elem,aft):
1880 a=elem b=list(mzl(aft))
1881 { let (mids,code) = List.split b in (mids,(a::code)) }
1882
1883 mzl(elem):
1884 a=TMid0 b=elem { (P.clt2mcode "|" a, b) }
1885
1886 edots_when(dotter,when_grammar):
1887 d=dotter { (d,None) }
1888 | d=dotter TWhen TNotEq w=when_grammar TLineEnd { (d,Some w) }
1889
1890 whens(when_grammar,simple_when_grammar,any_strict):
1891 TWhen TNotEq w=when_grammar TLineEnd { [Ast0.WhenNot w] }
1892 | TWhen TEq w=simple_when_grammar TLineEnd { [Ast0.WhenAlways w] }
1893 | TWhen comma_list(any_strict) TLineEnd
1894 { List.map (function x -> Ast0.WhenModifier(x)) $2 }
1895 | TWhenTrue TNotEq e = eexpr TLineEnd { [Ast0.WhenNotTrue e] }
1896 | TWhenFalse TNotEq e = eexpr TLineEnd { [Ast0.WhenNotFalse e] }
1897
1898 any_strict:
1899 TAny { Ast.WhenAny }
1900 | TStrict { Ast.WhenStrict }
1901 | TForall { Ast.WhenForall }
1902 | TExists { Ast.WhenExists }
1903
1904 /*****************************************************************************
1905 *
1906 *
1907 *****************************************************************************/
1908
1909 iso_main:
1910 TIsoExpression e1=dexpr el=list(iso(dexpr)) EOF
1911 { P.iso_adjust (function x -> Ast0.ExprTag x) e1 el }
1912 | TIsoArgExpression e1=dexpr el=list(iso(dexpr)) EOF
1913 { P.iso_adjust (function x -> Ast0.ArgExprTag x) e1 el }
1914 | TIsoTestExpression e1=dexpr el=list(iso(dexpr)) EOF
1915 { P.iso_adjust (function x -> Ast0.TestExprTag x) e1 el }
1916 | TIsoStatement s1=single_statement sl=list(iso(single_statement)) EOF
1917 { P.iso_adjust (function x -> Ast0.StmtTag x) s1 sl }
1918 | TIsoType t1=ctype tl=list(iso(ctype)) EOF
1919 { P.iso_adjust (function x -> Ast0.TypeCTag x) t1 tl }
1920 | TIsoTopLevel e1=nest_start el=list(iso(nest_start)) EOF
1921 { P.iso_adjust (function x -> Ast0.DotsStmtTag x) e1 el }
1922 | TIsoDeclaration d1=decl_var dl=list(iso(decl_var)) EOF
1923 { let check_one = function
1924 [x] -> x
1925 | _ ->
1926 raise
1927 (Semantic_cocci.Semantic
1928 "only one variable per declaration in an isomorphism rule") in
1929 let d1 = check_one d1 in
1930 let dl =
1931 List.map
1932 (function
1933 Common.Left x -> Common.Left(check_one x)
1934 | Common.Right x -> Common.Right(check_one x))
1935 dl in
1936 P.iso_adjust (function x -> Ast0.DeclTag x) d1 dl }
1937
1938 iso(term):
1939 TIso t=term { Common.Left t }
1940 | TRightIso t=term { Common.Right t }
1941
1942 /*****************************************************************************
1943 *
1944 *
1945 *****************************************************************************/
1946
1947 never_used: TPragma { () }
1948 | TPArob TMetaPos { () }
1949 | TScriptData { () }
1950
1951 script_meta_main: py=pure_ident TShOp TRuleName TDot cocci=pure_ident TMPtVirg
1952 { (P.id2name py, ($3, P.id2name cocci)) }