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