Release coccinelle-0.1.11rc1
[bpt/coccinelle.git] / parsing_cocci / parser_cocci_menhir.mly
CommitLineData
34e49164 1/*
951c7801
C
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 */
34e49164
C
21
22
23%{
24
25(* Not clear how to allow function declarations to specify a return type
26and how to allow both to be specified as static, because they are in
27different rules. The rules seem to have to be combined, which would allow
28functions to be declared as local variables *)
29
30(* Not clear how to let a function have a parameter of type void. At the
31moment, void is allowed to be the type of a variable, which is wrong, and a
32parameter needs both a type and an identifier *)
33module Ast0 = Ast0_cocci
34module Ast = Ast_cocci
35module P = Parse_aux
36%}
37
38%token EOF
39
40%token TIdentifier TExpression TStatement TFunction TLocal TType TParameter
113803cf 41%token TIdExpression TInitialiser
34e49164 42%token Tlist TFresh TConstant TError TWords TWhy0 TPlus0 TBang0
faf9a90c 43%token TPure TContext TGenerated
34e49164 44%token TTypedef TDeclarer TIterator TName TPosition TPosAny
faf9a90c 45%token TUsing TDisable TExtends TDepends TOn TEver TNever TExists TForall
951c7801 46%token TScript TInitialize TFinalize TNothing TVirtual
34e49164
C
47%token<string> TRuleName
48
49%token<Data.clt> Tchar Tshort Tint Tdouble Tfloat Tlong
faf9a90c 50%token<Data.clt> Tvoid Tstruct Tunion Tenum
34e49164
C
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
0708f913 59%token <string * Data.clt> TIdent TTypeId TDeclarerId TIteratorId TPragma
34e49164 60
951c7801
C
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
34e49164
C
69
70%token TArob TArobArob TPArob
71%token <string> TScriptData
72
73%token <Data.clt> TEllipsis TOEllipsis TCEllipsis TPOEllipsis TPCEllipsis
1be43e12 74%token <Data.clt> TWhen TWhenTrue TWhenFalse TAny TStrict TLineEnd
34e49164
C
75
76%token <Data.clt> TWhy TDotDot TBang TOPar TOPar0
77%token <Data.clt> TMid0 TCPar TCPar0
78
0708f913 79%token <string> TPathIsoFile
34e49164
C
80%token <string * Data.clt> TIncludeL TIncludeNL
81%token <Data.clt * token> TDefine
708f4980 82%token <Data.clt * token * int * int> TDefineParam
34e49164
C
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
faf9a90c 93%token <Data.clt> TAnd
951c7801 94%token <Data.clt> TEqEq TNotEq TTildeEq TTildeExclEq
34e49164
C
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
1be43e12 101%token <Data.clt> TOBrace TCBrace TOInit
34e49164
C
102%token <Data.clt> TOCro TCCro
103
104%token <Data.clt> TPtrOp
105
978fd7e5 106%token TMPtVirg TCppConcatOp
34e49164
C
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
faf9a90c 123%left TAnd
34e49164
C
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
978fd7e5 146%type <Data.incl_iso list> include_main
34e49164
C
147
148%start iso_rule_name
149%type <Ast_cocci.rulename>
150iso_rule_name
151
152%start rule_name
153%type <Ast_cocci.rulename>
154rule_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
172reinit: { }
173minus_main: minus_body EOF { $1 } | m=minus_body TArobArob { m }
174| m=minus_body TArob { m }
175plus_main: plus_body EOF { $1 } | p=plus_body TArobArob { p }
176| p=plus_body TArob { p }
177minus_exp_main: minus_exp_body EOF { $1 } | m=minus_exp_body TArobArob { m }
178| m=minus_exp_body TArob { m }
179plus_exp_main: plus_exp_body EOF { $1 } | p=plus_exp_body TArobArob { p }
180| p=plus_exp_body TArob { p }
181meta_main: m=metadec { m (!Ast0.rule_name) }
182iso_meta_main: m=metadec { m "" }
183
184/*****************************************************************************
185*
186*
187*****************************************************************************/
188
189pure:
190 TPure { Ast0.Pure }
191| TContext { Ast0.Context }
192| TPure TContext { Ast0.PureContext }
193| TContext TPure { Ast0.PureContext }
194| /* empty */ { Ast0.Impure }
195
196iso_rule_name:
197 nm=pure_ident TArob { P.make_iso_rule_name_result (P.id2name nm) }
198
199rule_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 }
faf9a90c
C
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 }
1be43e12
C
208 | TScript TDotDot lang=pure_ident d=depends TArob
209 { P.make_script_rule_name_result lang d }
b1b2de81
C
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 }
34e49164
C
214
215extends:
216 /* empty */ { () }
217| TExtends parent=TRuleName
218 { !Data.install_bindings (parent) }
219
220depends:
221 /* empty */ { Ast.NoDep }
222| TDepends TOn parents=dep { parents }
223
224dep:
225 pnrule { $1 }
226| dep TAndLog dep { Ast.AndDep($1, $3) }
227| dep TOrLog dep { Ast.OrDep ($1, $3) }
228
229pnrule:
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
236choose_iso:
237 TUsing separated_nonempty_list(TComma,TString) { List.map P.id2name $2 }
238
239disable:
240 TDisable separated_nonempty_list(TComma,pure_ident) { List.map P.id2name $2 }
241
242exists:
243 TExists { Ast.Exists }
244| TForall { Ast.Forall }
34e49164
C
245| { Ast.Undetermined }
246
247is_expression: // for more flexible parsing of top level expressions
248 { false }
249| TExpression { true }
250
251include_main:
252 list(incl) TArob { $1 }
253| list(incl) TArobArob { $1 }
254
255incl:
978fd7e5
C
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) }
951c7801
C
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) }
34e49164
C
266
267metadec:
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 }
b1b2de81
C
271| kindfn=metakind_fresh ids=comma_list(pure_ident_or_meta_ident_with_seed)
272 TMPtVirg
273 { P.create_fresh_metadec kindfn ids }
34e49164
C
274| ar=arity ispure=pure
275 kindfn=metakind_atomic
951c7801
C
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 }
34e49164
C
278| ar=arity ispure=pure
279 kindfn=metakind_atomic_expi
951c7801
C
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 }
34e49164
C
282| ar=arity ispure=pure
283 kindfn=metakind_atomic_expe
951c7801
C
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 }
34e49164 286| ar=arity TPosition a=option(TPosAny)
951c7801 287 ids=comma_list(pure_ident_or_meta_ident_with_x_eq(not_pos)) TMPtVirg
faf9a90c
C
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 =
34e49164
C
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
951c7801 297 P.create_metadec_with_constraints ar false kindfn ids }
34e49164
C
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
b1b2de81 317%inline metakind_fresh:
34e49164 318 TFresh TIdentifier
b1b2de81
C
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
34e49164
C
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
faf9a90c 339 !Data.add_type_meta name pure; tok) }
113803cf
C
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) }
34e49164
C
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
34e49164
C
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
951c7801 434 !Data.add_exp_meta None name (Ast0.NotExpCstrt constraints) pure; tok) }
34e49164
C
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
faf9a90c
C
445 Type_cocci.BaseType(Type_cocci.IntType) -> true
446 | Type_cocci.BaseType(Type_cocci.ShortType) -> true
447 | Type_cocci.BaseType(Type_cocci.LongType) -> true
34e49164
C
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
951c7801
C
454 !Data.add_exp_meta ty name (Ast0.NotExpCstrt constraints) pure; tok)
455 }
34e49164
C
456
457
458meta_exp_type:
978fd7e5 459 t=typedef_ctype
34e49164
C
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
466arity: TBang0 { Ast.UNIQUE }
467 | TWhy0 { Ast.OPT }
468 | TPlus0 { Ast.MULTI }
469 | /* empty */ { Ast.NONE }
470
978fd7e5
C
471/* ---------------------------------------------------------------------- */
472
473%inline
474signable_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
500non_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
526all_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
534ctype:
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 */
547typedef_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/* ---------------------------------------------------------------------- */
34e49164
C
556
557struct_or_union:
558 s=Tstruct { P.clt2mcode Ast.Struct s }
559 | u=Tunion { P.clt2mcode Ast.Union u }
560
561struct_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))] }
978fd7e5 566 | t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
34e49164
C
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
580struct_decl_list:
581 struct_decl_list_start { Ast0.wrap(Ast0.DOTS($1)) }
582
583struct_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
589continue_struct_decl_list:
590 /* empty */ { [] }
591| struct_decl struct_decl_list_start { $1@$2 }
592| struct_decl { $1 }
593
34e49164
C
594
595/*****************************************************************************/
596
597/* have to inline everything to avoid conflicts? switch to proper
598declarations, statements, and expressions for the subterms */
599
faf9a90c 600minus_body:
34e49164
C
601 f=loption(filespec)
602 b=loption(minus_start)
978fd7e5
C
603 /*ew=loption(error_words)*/
604 { match f@b(*@ew*) with
34e49164
C
605 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
606 | code -> Top_level.top_level code }
607
faf9a90c 608plus_body:
34e49164
C
609 f=loption(filespec)
610 b=loption(plus_start)
978fd7e5
C
611 /*ew=loption(error_words)*/
612 { Top_level.top_level (f@b(*@ew*)) }
34e49164
C
613
614minus_exp_body:
615 f=loption(filespec)
616 b=top_eexpr
978fd7e5
C
617 /*ew=loption(error_words)*/
618 { match f@[b](*@ew*) with
34e49164
C
619 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
620 | code -> Top_level.top_level code }
621
622plus_exp_body:
623 f=loption(filespec)
624 b=top_eexpr
978fd7e5
C
625 /*ew=loption(error_words)*/
626 { Top_level.top_level (f@[b](*@ew*)) }
34e49164
C
627
628filespec:
629 TMinusFile TPlusFile
630 { [Ast0.wrap
631 (Ast0.FILEINFO(P.id2mcode $1,
632 P.id2mcode $2))] }
633
634includes:
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
669defineop:
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
708f4980
C
688 { let (clt,ident,parenoff,parencol) = $1 in
689 (* clt is the start of the #define itself *)
34e49164
C
690 let (arity,line,lline,offset,col,strbef,straft,pos) = clt in
691 let lp =
0708f913 692 P.clt2mcode "("
708f4980 693 (arity,line,lline,parenoff,parencol,[],[],Ast0.NoMetaPos) in
34e49164
C
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
711define_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
718define_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
727dp_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
736define_param_list_option: define_param_list { $1 }
737 | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
738
739/*****************************************************************************/
740
741funproto:
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)) }
34e49164
C
751
752fundecl:
753 f=fninfo
754 TFunDecl i=func_ident lp=TOPar d=decl_list(decl) rp=TCPar
755 lb=TOBrace b=fun_start rb=TCBrace
978fd7e5
C
756 { P.verify_parameter_declarations (Ast0.undots d);
757 Ast0.wrap(Ast0.FunDecl((Ast0.default_info(),Ast0.context_befaft()),
34e49164
C
758 f, i,
759 P.clt2mcode "(" lp, d,
760 P.clt2mcode ")" rp,
761 P.clt2mcode "{" lb, b,
762 P.clt2mcode "}" rb)) }
763
764fninfo:
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 }
978fd7e5 772 | t=ctype r=fninfo_nt { (Ast0.FType(t))::r }
34e49164
C
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
784fninfo_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
803storage:
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
809decl: t=ctype i=ident
810 { Ast0.wrap(Ast0.Param(t, Some i)) }
978fd7e5
C
811 | t=ctype { (*verify in FunDecl*) Ast0.wrap(Ast0.Param(t, None)) }
812 | t=ctype lp=TOPar s=TMul i=ident rp=TCPar
34e49164
C
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)) }
34e49164
C
820 | TMetaParam
821 { let (nm,pure,clt) = $1 in
822 Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) }
823
824name_opt_decl:
825 decl { $1 }
978fd7e5 826 | t=ctype lp=TOPar s=TMul rp=TCPar
34e49164
C
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
835const_vol:
836 Tconst { P.clt2mcode Ast.Const $1 }
837 | Tvolatile { P.clt2mcode Ast.Volatile $1 }
838
839/*****************************************************************************/
840
841statement:
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 }
fc1ad971
C
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 }
34e49164
C
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
871stm_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
faf9a90c
C
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
708f4980 893whenppdecs: w=whens(when_start,rule_elem_statement,any_strict)
34e49164
C
894 { w }
895
896/* a statement that fits into a single rule_elem. should nests be included?
897what about statement metavariables? */
898rule_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 */
914single_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
925case_line:
926 TDefault TDotDot fun_start
fc1ad971
C
927 { Ast0.wrap
928 (Ast0.Default(P.clt2mcode "default" $1,P.clt2mcode ":" $2,$3)) }
34e49164
C
929 | TCase eexpr TDotDot fun_start
930 { Ast0.wrap(Ast0.Case(P.clt2mcode "case" $1,$2,P.clt2mcode ":" $3,$4)) }
fc1ad971
C
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)) } */
34e49164
C
935
936/* In the following, an identifier as a type is not fully supported. Indeed,
937the language is ambiguous: what is foo * bar; */
938/* The AST DisjDecl cannot be generated because it would be ambiguous with
939a disjunction on a statement with a declaration in each branch */
940decl_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)
978fd7e5 970 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
34e49164
C
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,
faf9a90c 982 P.clt2mcode ")" $4,P.clt2mcode ";" $5))] }
34e49164 983 | s=ioption(storage)
978fd7e5 984 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
34e49164
C
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))]}
002099fc 994 | s=Ttypedef t=typedef_ctype id=comma_list(typedef_ident) pv=TPtVirg
34e49164 995 { let s = P.clt2mcode "typedef" s in
002099fc
C
996 List.map
997 (function id ->
998 Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv)))
999 id }
34e49164
C
1000
1001one_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)
978fd7e5 1026 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
34e49164
C
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,
faf9a90c 1038 P.clt2mcode ")" $4,P.clt2mcode ";" $5)) }
34e49164 1039 | s=ioption(storage)
978fd7e5 1040 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
34e49164
C
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
1052d_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
1063array_dec: l=TOCro i=option(eexpr) r=TCCro { (l,i,r) }
1064
1065initialize:
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)) }
113803cf
C
1074 | TMetaInit
1075 {let (nm,pure,clt) = $1 in
1076 Ast0.wrap(Ast0.MetaInit(P.clt2mcode nm clt,pure)) }
34e49164
C
1077
1078initialize2:
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 */
113803cf
C
1089| list(designator) TEq initialize2
1090 { Ast0.wrap(Ast0.InitGccExt($1,P.clt2mcode "=" $2,$3)) }
34e49164
C
1091| ident TDotDot initialize2
1092 { Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */
113803cf 1093
951c7801
C
1094designator:
1095 | TDot ident
1096 { Ast0.DesignatorField (P.clt2mcode "." $1,$2) }
1097 | TOCro eexpr TCCro
113803cf 1098 { Ast0.DesignatorIndex (P.clt2mcode "[" $1,$2,P.clt2mcode "]" $3) }
951c7801 1099 | TOCro eexpr TEllipsis eexpr TCCro
113803cf
C
1100 { Ast0.DesignatorRange (P.clt2mcode "[" $1,$2,P.clt2mcode "..." $3,
1101 $4,P.clt2mcode "]" $5) }
34e49164
C
1102
1103initialize_list:
1104 initialize_list_start { Ast0.wrap(Ast0.DOTS($1)) }
1105
1106initialize_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
1115comma_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
1123comma_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 */
1130decl_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 */
1160decl_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
1191be allowed as an expression when the expression is delimited on both sides
1192by expression-specific markers. In that case, the rule eexpr is used, which
1193allows <... ...> anywhere. Hopefully, this will not be too much of a problem
1194in practice. */
1195expr: basic_expr(expr,invalid) { $1 }
1196/* allows ... and nests */
1197eexpr: basic_expr(eexpr,dot_expressions) { $1 }
1198/* allows nests but not .... */
1199dexpr: basic_expr(eexpr,nest_expressions) { $1 }
1200
1201top_eexpr:
1202 eexpr { Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))) }
1203
1204invalid:
1205 TInvalid { raise (Semantic_cocci.Semantic "not matchable") }
1206
1207dot_expressions:
1208 TEllipsis { Ast0.wrap(Ast0.Edots(P.clt2mcode "..." $1,None)) }
1209| nest_expressions { $1 }
1210
485bce71 1211/* not clear what whencode would mean, so just drop it */
34e49164 1212nest_expressions:
485bce71 1213 TOEllipsis e=expr_dots(TEllipsis) c=TCEllipsis
34e49164
C
1214 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<..." $1,
1215 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
485bce71
C
1216 P.clt2mcode "...>" c, None, false)) }
1217| TPOEllipsis e=expr_dots(TEllipsis) c=TPCEllipsis
34e49164
C
1218 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<+..." $1,
1219 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
485bce71 1220 P.clt2mcode "...+>" c, None, true)) }
34e49164 1221
485bce71 1222//whenexp: TWhen TNotEq w=eexpr TLineEnd { w }
34e49164
C
1223
1224basic_expr(recurser,primary_extra):
1225 assign_expr(recurser,primary_extra) { $1 }
1226
1227assign_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
1238assign_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
1249cond_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
1255arith_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
1284cast_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
1290unary_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)) }
0708f913 1296 | unary_op cast_expr(r,pe)
34e49164
C
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
1308unary_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
1314postfix_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
1333primary_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
1376expr_dots(dotter):
1377 r=no_dot_start_end(dexpr,edots_when(dotter,eexpr)) { r }
1378
1379// used in NEST
1380no_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
1387pure_ident:
1388 TIdent { $1 }
1389
1390meta_ident:
1391 TRuleName TDot pure_ident { (Some $1,P.id2name $3) }
1392
1393pure_ident_or_meta_ident:
1394 pure_ident { (None,P.id2name $1) }
1395 | meta_ident { $1 }
978fd7e5
C
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") }
34e49164 1418
b1b2de81 1419pure_ident_or_meta_ident_with_seed:
978fd7e5
C
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
1427seed_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 }
b1b2de81 1434
951c7801
C
1435pure_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
1441pure_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
1449pure_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
1457re_or_not_eqid:
1458 re=regexp_eqid {re}
1459 | ne=not_eqid {ne}
1460
1461regexp_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 }
34e49164 1476
951c7801 1477not_eqid:
34e49164
C
1478 TNotEq i=pure_ident
1479 { (if !Data.in_iso
1480 then failwith "constraints not allowed in iso file");
faf9a90c
C
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");
951c7801 1485 Ast.IdNegIdSet([fst i]) }
34e49164
C
1486 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1487 { (if !Data.in_iso
1488 then failwith "constraints not allowed in iso file");
faf9a90c
C
1489 (if !Data.in_generating
1490 then failwith "constraints not allowed in a generated rule file");
951c7801
C
1491 Ast.IdNegIdSet(List.map fst l)
1492 }
1493
1494re_or_not_eqe:
1495 re=regexp_eqid {Ast0.NotIdCstrt (re)}
1496 | ne=not_eqe {Ast0.NotExpCstrt (ne)}
34e49164
C
1497
1498not_eqe:
1499 TNotEq i=pure_ident
1500 { (if !Data.in_iso
1501 then failwith "constraints not allowed in iso file");
faf9a90c
C
1502 (if !Data.in_generating
1503 then failwith "constraints not allowed in a generated rule file");
951c7801
C
1504 [Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))]
1505 }
34e49164
C
1506 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1507 { (if !Data.in_iso
1508 then failwith "constraints not allowed in iso file");
faf9a90c
C
1509 (if !Data.in_generating
1510 then failwith "constraints not allowed in a generated rule file");
34e49164
C
1511 List.map
1512 (function i ->
951c7801
C
1513 Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))))
1514 l
1515 }
34e49164
C
1516
1517not_ceq:
1518 TNotEq i=ident_or_const
1519 { (if !Data.in_iso
1520 then failwith "constraints not allowed in iso file");
faf9a90c
C
1521 (if !Data.in_generating
1522 then failwith "constraints not allowed in a generated rule file");
34e49164
C
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");
faf9a90c
C
1527 (if !Data.in_generating
1528 then failwith "constraints not allowed in a generated rule file");
34e49164
C
1529 l }
1530
1531ident_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
1537not_pos:
1538 TNotEq i=meta_ident
1539 { (if !Data.in_iso
1540 then failwith "constraints not allowed in iso file");
faf9a90c
C
1541 (if !Data.in_generating
1542 then failwith "constraints not allowed in a generated rule file");
34e49164
C
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");
faf9a90c
C
1552 (if !Data.in_generating
1553 then failwith "constraints not allowed in a generated rule file");
34e49164
C
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
1564func_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
1577ident: 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
1583decl_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
1590iter_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
1597typedef_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
1606decl_list(decl):
113803cf
C
1607 /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
1608| decl_list_start(decl)
34e49164
C
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
1615decl_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
1623one_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)) }
faf9a90c 1633
34e49164
C
1634comma_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
978fd7e5
C
1645/* error words make it complicated to be able to use error as a metavariable
1646name or a type in a metavariable list; for that we would like to allow TError
1647as an ident, but that makes conflicts with this rule. To add back error words,
1648need to find some appropriate delimiter for it, but it has not been used much
1649so just drop it */
1650/*error_words:
34e49164
C
1651 TError TWords TEq TOCro cl=comma_list(dexpr) TCCro
1652 { [Ast0.wrap(Ast0.ERRORWORDS(cl))] }
978fd7e5 1653*/
34e49164
C
1654
1655/* ---------------------------------------------------------------------- */
1656/* sequences of statements and expressions */
1657
1658/* There are number of cases that must be considered:
1659
16601. 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
16642. 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
16683. 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
16724. 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
1677These are implemented by the rules minus_toplevel_sequence,
1678plus_toplevel_sequence, function_body_sequence, nest_body_sequence, and
1679when_body_sequence.
1680*/
1681/* ------------------------------------------------------------------------ */
1682/* Minus top level */
1683
1684/* doesn't allow only ... */
1685minus_start:
1686 fundecl { [Ast0.wrap(Ast0.DECL($1))] }
1687| ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1be43e12 1688| top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
faf9a90c 1689| toplevel_seq_startne(toplevel_after_dots_init)
34e49164
C
1690 { List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1 }
1691
faf9a90c
C
1692toplevel_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
34e49164
C
1699toplevel_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
1704toplevel_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
1709toplevel_after_exp:
1710 /* empty */ {[]}
1711| stm_dots toplevel_after_dots {$1::$2}
1712
1713toplevel_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
1719toplevel_after_stm:
1720 /* empty */ {[]}
1721| stm_dots toplevel_after_dots {$1::$2}
1722| decl_statement toplevel_after_stm {$1@$2}
1723
1be43e12
C
1724top_init:
1725 TOInit initialize_list TCBrace
1726 { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
1727
34e49164
C
1728/* ------------------------------------------------------------------------ */
1729/* Plus top level */
1730
1731/* does allow only ... also allows multiple top-level functions */
1732plus_start:
1733 ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
1be43e12 1734| top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
34e49164
C
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
1743plus_after_exp:
1744 /* empty */ {[]}
1745| stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
1746
1747plus_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
1756plus_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
1766fun_start:
1767 fun_after_stm { Ast0.wrap(Ast0.DOTS($1)) }
1768
1769fun_after_stm:
1770 /* empty */ {[]}
1771| stm_dots fun_after_dots {$1::$2}
1772| decl_statement fun_after_stm {$1@$2}
1773
1774fun_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
1780fun_after_exp:
1781 stm_dots fun_after_dots {$1::$2}
1782
1783/* hack to allow mixing statements and expressions in an or */
1784fun_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
1790fun_after_exp_or:
1791 /* empty */ {[]}
1792| stm_dots fun_after_dots {$1::$2}
1793
1794/* ------------------------------------------------------------------------ */
1795/* Nest body */
1796
1797nest_start:
1798 nest_after_dots { Ast0.wrap(Ast0.DOTS($1)) }
1799
1800nest_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
1805nest_after_stm:
1806 /* empty */ {[]}
1807| stm_dots nest_after_dots {$1::$2}
1808| decl_statement nest_after_stm {$1@$2}
1809
1810nest_after_exp:
1811 /* empty */ {[]}
1812| stm_dots nest_after_dots {$1::$2}
1813
1814/* ------------------------------------------------------------------------ */
1815/*Whencode*/
1816
1817when_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
1825eexpr_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 */
1839aexpr:
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
1853eexpr_list_start:
1854 aexpr { [$1] }
1855 | aexpr TComma eexpr_list_start
1856 { $1::Ast0.wrap(Ast0.EComma(P.clt2mcode "," $2))::$3 }
1857
1858comma_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
1866eexpr_list_option: eexpr_list { $1 }
1867 | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
1868
1869/****************************************************************************/
1870
1871// non-empty lists - drop separator
1872comma_list(elem):
1873 separated_nonempty_list(TComma,elem) { $1 }
1874
1875midzero_list(elem,aft):
1876 a=elem b=list(mzl(aft))
1877 { let (mids,code) = List.split b in (mids,(a::code)) }
1878
1879mzl(elem):
1880 a=TMid0 b=elem { (P.clt2mcode "|" a, b) }
1881
1882edots_when(dotter,when_grammar):
1883 d=dotter { (d,None) }
1884 | d=dotter TWhen TNotEq w=when_grammar TLineEnd { (d,Some w) }
1885
708f4980 1886whens(when_grammar,simple_when_grammar,any_strict):
34e49164
C
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 }
1be43e12
C
1891 | TWhenTrue TNotEq e = eexpr TLineEnd { [Ast0.WhenNotTrue e] }
1892 | TWhenFalse TNotEq e = eexpr TLineEnd { [Ast0.WhenNotFalse e] }
34e49164
C
1893
1894any_strict:
1895 TAny { Ast.WhenAny }
1896 | TStrict { Ast.WhenStrict }
1897 | TForall { Ast.WhenForall }
1898 | TExists { Ast.WhenExists }
1899
1900/*****************************************************************************
1901*
1902*
1903*****************************************************************************/
1904
1905iso_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
1934iso(term):
1935 TIso t=term { Common.Left t }
1936 | TRightIso t=term { Common.Right t }
1937
1938/*****************************************************************************
1939*
1940*
1941*****************************************************************************/
1942
1943never_used: TPragma { () }
1944 | TPArob TMetaPos { () }
1945 | TScriptData { () }
1946
1947script_meta_main: py=pure_ident TShOp TRuleName TDot cocci=pure_ident TMPtVirg
1948 { (P.id2name py, ($3, P.id2name cocci)) }