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