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