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