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