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