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