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