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.
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.
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.
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/>.
22 * The authors reserve the right to distribute this or future versions of
23 * Coccinelle under other licenses.
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.
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.
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.
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/>.
48 * The authors reserve the right to distribute this or future versions of
49 * Coccinelle under other licenses.
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 *)
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
67 (* ---------------------------------------------------------------------- *)
68 (* support for TMeta *)
70 let print_meta (r,n) = r^"."^n
72 let meta_metatable = Hashtbl.create(101)
74 let coerce_tmeta newty name builder matcher =
76 let x = Hashtbl.find meta_metatable name in
80 (Printf.sprintf "Metavariable %s is used as %s"
81 (print_meta name) newty)
83 (if !Flag_parsing_cocci.show_SP
87 "Metavariable %s is assumed to be %s metavariable"
88 (print_meta name) newty));
89 Hashtbl.add meta_metatable name builder
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))
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)
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));
106 (Ast0.MetaExpr(P.clt2mcode name clt,Ast0.NoConstraint,None,Ast.ANY,pure))
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))
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)
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));
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))
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
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
147 %token<Data.clt> Tstatic Tauto Tregister Textern Tinline Ttypedef
148 %token<Data.clt> Tconst Tvolatile
149 %token<string * Data.clt> Tattr
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
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
167 %token TArob TArobArob
168 %token <Data.clt> TPArob
169 %token <string> TScriptData
171 %token <Data.clt> TEllipsis TOEllipsis TCEllipsis TPOEllipsis TPCEllipsis
172 %token <Data.clt> TWhen TWhenTrue TWhenFalse TAny TStrict TLineEnd
174 %token <Data.clt> TWhy TDotDot TBang TOPar TOPar0
175 %token <Data.clt> TMid0 TCPar TCPar0
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
183 %token <Data.clt> TInc TDec
185 %token <string * Data.clt> TString TChar TFloat TInt
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
199 %token <Data.clt> TOBrace TCBrace TOInit
200 %token <Data.clt> TOCro TCCro
202 %token <Data.clt> TPtrOp
204 %token TMPtVirg TCppConcatOp
205 %token <Data.clt> TEq TDot TComma TPtVirg
206 %token <Ast_cocci.assignOp * Data.clt> TAssign
208 %token TIso TRightIso TIsoExpression TIsoStatement TIsoDeclaration TIsoType
209 %token TIsoTopLevel TIsoArgExpression TIsoTestExpression TIsoToTestExpression
215 /* operator precedence */
225 %left TLogOp /* TInf TSup TInfEq TSupEq */
226 %left TShLOp TShROp /* TShl TShr */
228 %left TMul TDmOp /* TDiv TMod */
234 %type <Ast0_cocci.rule> minus_main
236 %start minus_exp_main
237 %type <Ast0_cocci.rule> minus_exp_main
240 %type <Ast0_cocci.rule> plus_main
243 %type <Ast0_cocci.rule> plus_exp_main
246 %type <Data.incl_iso list> include_main
249 %type <Ast_cocci.rulename>
253 %type <Ast_cocci.rulename>
257 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> meta_main
259 %start <(string option (*string*) * string option (*ast*)) * (Ast_cocci.meta_name * Ast_cocci.metavar) option> script_meta_main
262 %type <Ast0_cocci.anything list list> iso_main
265 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> iso_meta_main
268 %type <unit> never_used
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 "" }
284 /*****************************************************************************
287 *****************************************************************************/
291 | TContext { Ast0.Context }
292 | TPure TContext { Ast0.PureContext }
293 | TContext TPure { Ast0.PureContext }
294 | /* empty */ { Ast0.Impure }
297 nm=pure_ident TArob { P.make_iso_rule_name_result (P.id2name nm) }
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 }
317 | TExtends parent=TRuleName
318 { !Data.install_bindings (parent) }
321 /* empty */ { Ast0.NoDep }
322 | TDepends TOn parents=dep { parents }
325 TRuleName { Ast0.Dep $1 }
326 | TBang TRuleName { Ast0.AntiDep (Ast0.Dep $2) }
327 | TBang TOPar dep TCPar
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 }
336 TUsing separated_nonempty_list(TComma,TString) { List.map P.id2name $2 }
339 TDisable separated_nonempty_list(TComma,pure_ident) { List.map P.id2name $2 }
342 TExists { Ast.Exists }
343 | TForall { Ast.Forall }
344 | { Ast.Undetermined }
346 is_expression: // for more flexible parsing of top level expressions
348 | TExpression { true }
351 list(incl) TArob { $1 }
352 | list(incl) TArobArob { $1 }
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 *)
364 (function name -> Hashtbl.add Data.all_metadecls name [])
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)
374 { P.create_fresh_metadec kindfn ids }
375 | ar=arity ispure=pure
376 kindfn=metakind_atomic_maybe_virt
378 comma_list(pure_ident_or_meta_ident_with_idconstraint_virt(re_or_not_eqid))
380 { let (normal,virt) = Common.partition_either (fun x -> x) ids in
381 let (idfn,virtfn) = kindfn in
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))
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))
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))
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)
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)
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)
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)
444 | TSymbol ids=comma_list(pure_ident) TMPtVirg
446 let add_sym = fun (nm,_) -> !Data.add_symbol_meta nm in
447 List.iter add_sym ids; [])
451 pure_ident_or_meta_ident { Common.Left $1 }
452 | TInt { let (x,clt) = $1 in Common.Right (int_of_string x) }
454 %inline metakind_fresh:
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) }
460 /* metavariable kinds with no constraints, etc */
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) }
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) }
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) }
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) }
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) }
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) }
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) }
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) }
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) }
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) }
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) }
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) }
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")) }
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")) }
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")) }
530 %inline metakind_atomic_maybe_virt:
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 =
538 let vl = List.assoc name virtual_env in
539 !Data.add_virt_id_meta_found name vl; []
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
549 %inline metakind_atomic:
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) }
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;
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) }
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) }
568 %inline metakind_atomic_expi:
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 ->
577 !Data.add_idexp_meta ty name constraints pure;
578 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
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
587 !Data.add_idexp_meta ty name constraints pure;
588 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
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) }
603 m=nonempty_list(TMul) { P.ty_pointerify Type_cocci.Unknown m }
605 { P.ty_pointerify (Type_cocci.EnumName Type_cocci.NoName) m }
606 | Tstruct m=list(TMul)
608 (Type_cocci.StructUnionName (Type_cocci.Struct,Type_cocci.NoName)) m }
609 | Tunion m=list(TMul)
611 (Type_cocci.StructUnionName (Type_cocci.Union,Type_cocci.NoName)) m }
613 %inline metakind_atomic_expe:
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 ->
621 (match constraints with
622 Ast0.NotExpCstrt constraints ->
625 match Ast0.unwrap c with
630 Type_cocci.BaseType(Type_cocci.IntType) -> true
631 | Type_cocci.BaseType(Type_cocci.ShortType) -> true
632 | Type_cocci.BaseType(Type_cocci.LongType) -> true
636 failwith "metavariable with int constraint must be an int"
640 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
641 !Data.add_exp_meta ty name constraints pure; tok)
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)
651 (function x -> P.ty_pointerify (Ast0_cocci.ast0_type_to_type x) m)
654 arity: TBang0 { Ast.UNIQUE }
656 | TPlus0 { Ast.MULTI }
657 | /* empty */ { Ast.NONE }
659 /* ---------------------------------------------------------------------- */
664 { Ast0.wrap(Ast0.BaseType(Ast.CharType,[P.clt2mcode "char" ty])) }
666 { Ast0.wrap(Ast0.BaseType(Ast.ShortType,[P.clt2mcode "short" ty])) }
667 | ty1=Tshort ty2=Tint
670 (Ast.ShortIntType,[P.clt2mcode "short" ty1;P.clt2mcode "int" ty2])) }
672 { Ast0.wrap(Ast0.BaseType(Ast.IntType,[P.clt2mcode "int" ty])) }
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*))) }
684 { Ast0.wrap(Ast0.BaseType(Ast.LongType,[P.clt2mcode "long" ty1])) }
688 (Ast.LongIntType,[P.clt2mcode "long" ty1;P.clt2mcode "int" ty2])) }
689 | ty1=Tlong ty2=Tlong
693 [P.clt2mcode "long" ty1;P.clt2mcode "long" ty2])) }
694 | ty1=Tlong ty2=Tlong ty3=Tint
697 (Ast.LongLongIntType,
698 [P.clt2mcode "long" ty1;P.clt2mcode "long" ty2;
699 P.clt2mcode "int" ty3])) }
704 { Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" ty])) }
705 | ty1=Tlong ty2=Tdouble
709 [P.clt2mcode "long" ty1;P.clt2mcode "double" ty2])) }
711 { Ast0.wrap(Ast0.BaseType(Ast.DoubleType,[P.clt2mcode "double" ty])) }
713 { Ast0.wrap(Ast0.BaseType(Ast.FloatType,[P.clt2mcode "float" ty])) }
715 { Ast0.wrap(Ast0.BaseType(Ast.SizeType,[P.clt2mcode "size_t" ty])) }
717 { Ast0.wrap(Ast0.BaseType(Ast.SSizeType,[P.clt2mcode "ssize_t" ty])) }
719 { Ast0.wrap(Ast0.BaseType(Ast.PtrDiffType,[P.clt2mcode "ptrdiff_t" ty])) }
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)),
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)) }
741 { Ast0.wrap(Ast0.TypeName(P.id2mcode p)) }
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 }
753 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
754 { P.pointerify (P.make_cv cv ty) m }
756 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,None)) }
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
762 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
765 | TMeta { tmeta_to_type $1 }
768 /* signed, unsigned alone not allowed */
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
775 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
776 | TMeta { tmeta_to_type $1 }
778 /* ---------------------------------------------------------------------- */
781 s=Tstruct { P.clt2mcode Ast.Struct s }
782 | u=Tunion { P.clt2mcode Ast.Union u }
786 | struct_decl_one { [$1] }
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
795 (Ast0.DisjDecl(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
796 | t=ctype d=d_ident pv=TPtVirg
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
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
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)) }
814 struct_decl_list_start { Ast0.wrap(Ast0.DOTS($1)) }
816 struct_decl_list_start:
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 }
822 continue_struct_decl_list:
824 | struct_decl struct_decl_list_start { $1@$2 }
828 /* ---------------------------------------------------------------------- */
829 /* very restricted what kinds of expressions can appear in an enum decl */
832 | disj_ident { Ast0.wrap(Ast0.Ident($1)) }
833 | disj_ident TEq enum_val
834 { let id = Ast0.wrap(Ast0.Ident($1)) in
837 (id,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,
841 ident { Ast0.wrap(Ast0.Ident($1)) }
843 { let (x,clt) = $1 in
844 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
845 | TMeta { tmeta_to_exp $1 }
847 { let (nm,constraints,pure,ty,clt) = $1 in
849 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
851 { let (nm,constraints,pure,ty,clt) = $1 in
853 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
855 { let (nm,constraints,pure,ty,clt) = $1 in
857 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
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))) }
863 /*****************************************************************************/
865 /* have to inline everything to avoid conflicts? switch to proper
866 declarations, statements, and expressions for the subterms */
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")
878 b=loption(plus_start)
879 /*ew=loption(error_words)*/
885 /*ew=loption(error_words)*/
886 { match f@[b](*@ew*) with
887 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
893 /*ew=loption(error_words)*/
899 (Ast0.FILEINFO(P.id2mcode $1,
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) =
910 (arity,ln,lln,offset,0,strbef,straft,pos) in
912 (Ast.Local (Parse_aux.str2inc (P.id2name $1)))
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) =
921 (arity,ln,lln,offset,0,strbef,straft,pos) in
923 (Ast.NonLocal (Parse_aux.str2inc (P.id2name $1)))
926 { let (clt,ident) = $1 in
927 let aft = P.get_aft clt in (* move stuff after the define to the ident *)
930 (P.clt2mcode "#undef" (P.drop_aft clt),
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))
939 let clt = P.set_aft aft clt in
940 Ast0.wrap(Ast0.Id(P.clt2mcode nm clt))
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
954 (match Ast0.unwrap e with
956 [Ast0.rewrap e (Ast0.TopExp(Ast0.set_arg_exp (e1)))]
959 $1 (Ast0.wrap(Ast0.DOTS(body))) }
963 { let (clt,ident) = $1 in
964 let aft = P.get_aft clt in (* move stuff after the define to the ident *)
968 (P.clt2mcode "#define" (P.drop_aft clt),
970 TMetaId((nm,constraints,seed,pure,clt)) ->
971 let clt = P.set_aft aft clt in
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))
978 let clt = P.set_aft aft clt in
979 Ast0.wrap(Ast0.Id(P.clt2mcode nm clt))
982 (Semantic_cocci.Semantic
983 "unexpected name for a #define")),
984 Ast0.wrap Ast0.NoParams,
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
993 (arity,line,lline,parenoff,parencol,[],[],[]) in
997 (P.clt2mcode "#define" (P.drop_aft clt),
999 TMetaId((nm,constraints,seed,pure,clt)) ->
1001 (Ast0.MetaId(P.clt2mcode nm clt,constraints,seed,pure))
1002 | TIdent((nm,clt)) ->
1003 Ast0.wrap(Ast0.Id(P.clt2mcode nm clt))
1005 Ast0.wrap(Ast0.Id(P.clt2mcode nm clt))
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)) }
1013 /* ---------------------------------------------------------------------- */
1015 dparam: mident { Ast0.wrap(Ast0.DParam $1) }
1017 define_param_list_option:
1018 empty_list_start(dparam,TEllipsis)
1022 (fun _ d -> Ast0.wrap(Ast0.DPdots(P.clt2mcode "," d)))
1023 (fun c -> Ast0.DPComma c))) }
1025 /*****************************************************************************/
1028 s=ioption(storage) t=ctype
1029 id=fn_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
1034 (Ast0.FunctionType(Some t,
1035 P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
1036 id, P.clt2mcode ";" pt)) }
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()),
1045 P.clt2mcode "(" lp, d,
1047 P.clt2mcode "{" lb, b,
1048 P.clt2mcode "}" rb)) }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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
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)) }
1107 { let (nm,pure,clt) = $1 in
1108 Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) }
1109 | TMeta { tmeta_to_param $1 }
1113 | t=ctype lp=TOPar s=TMul rp=TCPar
1114 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
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)) }
1123 Tconst { P.clt2mcode Ast.Const $1 }
1124 | Tvolatile { P.clt2mcode Ast.Volatile $1 }
1126 /*****************************************************************************/
1129 includes { $1 } /* shouldn't be allowed to be a single_statement... */
1130 | TMeta { tmeta_to_statement $1}
1133 | option(expr) TPtVirg
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
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)) }
1169 %inline stm_dots_ell:
1170 a=TEllipsis w=list(whenppdecs)
1171 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." a, List.concat w)) }
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)) }
1181 whenppdecs: w=whens(when_start,rule_elem_statement,any_strict)
1184 /* a statement that fits into a single rule_elem. should nests be included?
1185 what about statement metavariables? */
1186 rule_elem_statement:
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
1197 (Ast0.Disj(P.clt2mcode "(" $1,
1198 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
1199 mids, P.clt2mcode ")" $3)) }
1201 /* a statement on its own */
1204 | TOPar0 midzero_list(statement,statement) TCPar0
1205 /* degenerate case, elements are single statements and thus don't
1207 { let (mids,code) = $2 in
1209 (Ast0.Disj(P.clt2mcode "(" $1,
1210 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
1211 mids, P.clt2mcode ")" $3)) }
1213 iso_statement: /* statement or declaration used in statement context */
1219 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),decl))
1220 | _ -> failwith "exactly one decl allowed in statement iso" }
1223 TDefault TDotDot fun_start
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
1231 (Ast0.DisjCase(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) } */
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 */
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
1243 (function (id,fn) ->
1244 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)))
1246 | f=funproto { [f] }
1247 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
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
1254 (function (id,fn) ->
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)))
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
1271 { let (id,fn) = d in
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
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
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
1302 Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv)))
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)) }
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
1334 { let (id,fn) = d in
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
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
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))}
1364 disj_ident list(array_dec)
1365 { ($1, function t -> P.arrayify t $2) }
1367 array_dec: l=TOCro i=option(eexpr) r=TCCro { (l,i,r) }
1371 { Ast0.wrap(Ast0.InitExpr($1)) }
1372 | TOBrace initialize_list TCBrace
1373 { if P.struct_initializer $2
1375 let il = P.drop_dot_commas $2 in
1376 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
1378 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) }
1380 {let (nm,pure,clt) = $1 in
1381 Ast0.wrap(Ast0.MetaInit(P.clt2mcode nm clt,pure)) }
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
1391 let il = P.drop_dot_commas $2 in
1392 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
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 */
1401 {let (nm,pure,clt) = $1 in
1402 Ast0.wrap(Ast0.MetaInit(P.clt2mcode nm clt,pure)) }
1404 {let (nm,lenname,pure,clt) = $1 in
1405 let nm = P.clt2mcode nm clt in
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)) }
1415 { Ast0.DesignatorField (P.clt2mcode "." $1,$2) }
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) }
1423 empty_list_start(initialize2,edots_when(TEllipsis,initialize))
1424 { Ast0.wrap(Ast0.DOTS($1 P.mkidots (fun c -> Ast0.IComma c))) }
1426 /* a statement that is part of a list */
1429 { let (nm,pure,clt) = $1 in
1430 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1435 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
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
1449 match Ast0.unwrap x with Ast0.DOTS([]) -> true | _ -> false)
1453 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, code, mids,
1454 P.clt2mcode ")" $3))] }
1456 /* a statement that is part of a list */
1457 decl_statement_expr:
1459 { let (nm,pure,clt) = $1 in
1460 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1465 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
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
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))] }
1485 /*****************************************************************************/
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
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
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 */
1506 eexpr { Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))) }
1509 TInvalid { raise (Semantic_cocci.Semantic "not matchable") }
1512 TEllipsis { Ast0.wrap(Ast0.Edots(P.clt2mcode "..." $1,None)) }
1513 | nest_expressions { $1 }
1515 /* not clear what whencode would mean, so just drop it */
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 }
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)) }
1537 //whenexp: TWhen TNotEq w=eexpr TLineEnd { w }
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)) }
1545 basic_expr(recurser,primary_extra):
1546 assign_expr(recurser,primary_extra) { $1 }
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
1557 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
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
1568 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
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)) }
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 }
1608 // allows dots now that an expression-specific token has been seen
1609 // need an extra rule because of recursion restrictions
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
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)) }
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)) }
1665 // version that allows dots
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)) }
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 }
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,
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,
1707 P.clt2mcode ")" $4)) }
1708 /*(* gccext: also called compound literals *)
1709 empty case causes conflicts */
1710 | TOPar ctype TCPar TOBrace initialize_list TCBrace
1712 if P.struct_initializer $5
1714 let il = P.drop_dot_commas $5 in
1716 (Ast0.InitList(P.clt2mcode "{" $4,il,P.clt2mcode "}" $6,false))
1719 (Ast0.InitList(P.clt2mcode "{" $4,$5,P.clt2mcode "}" $6,true)) in
1721 (Ast0.Constructor(P.clt2mcode "(" $1, $2, P.clt2mcode ")" $3, init)) }
1723 primary_expr(recurser,primary_extra):
1724 func_ident { Ast0.wrap(Ast0.Ident($1)) }
1726 { let op = P.clt2mcode Ast.GetRefLabel $1 in
1727 Ast0.wrap(Ast0.Unary(Ast0.wrap(Ast0.Ident($2)), op)) }
1729 { let (x,clt) = $1 in
1730 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1732 { let (x,clt) = $1 in
1733 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Float x) clt)) }
1735 { let (x,clt) = $1 in
1736 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.String x) clt)) }
1738 { let (x,clt) = $1 in
1739 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Char x) clt)) }
1741 { let (nm,constraints,pure,ty,clt) = $1 in
1743 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
1745 { let (nm,constraints,pure,clt) = $1 in
1746 Ast0.wrap(Ast0.MetaErr(P.clt2mcode nm clt,constraints,pure)) }
1748 { let (nm,constraints,pure,ty,clt) = $1 in
1750 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
1752 { let (nm,constraints,pure,ty,clt) = $1 in
1754 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
1756 { let (nm,constraints,pure,ty,clt) = $1 in
1758 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.LocalID,pure)) }
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,
1766 P.clt2mcode ")" $3)) }
1767 | primary_extra { $1 }
1770 r=no_dot_start_end(dexpr,edots_when(dotter,eexpr)) { r }
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)) }
1778 /*****************************************************************************/
1783 pure_ident_or_symbol:
1788 | TIdentifier { "identifier" }
1789 | TExpression { "expression" }
1790 | TStatement { "statement" }
1791 | TFunction { "function" }
1792 | TLocal { "local" }
1794 | TParameter { "parameter" }
1795 | TIdExpression { "idexpression" }
1796 | TInitialiser { "initialiser" }
1798 | TFresh { "fresh" }
1799 | TConstant { "constant" }
1800 | TError { "error" }
1801 | TWords { "words" }
1803 | TContext { "context" }
1804 | TGenerated { "generated" }
1805 | TTypedef { "typedef" }
1806 | TDeclarer { "declarer" }
1807 | TIterator { "iterator" }
1809 | TPosition { "position" }
1810 | TSymbol { "symbol" }
1813 TRuleName TDot pure_ident { (Some $1,P.id2name $3) }
1814 | TRuleName TDot pure_ident_kwd { (Some $1,$3) }
1816 pure_ident_or_meta_ident:
1817 pure_ident { (None,P.id2name $1) }
1818 | pure_ident_kwd { (None,$1) }
1822 TSymId { Ast0.wrap(Ast0.Id(P.sym2mcode $1)) }
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)
1829 [Ast.SeedString s] -> ($1,Ast.StringSeed s)
1830 | _ -> ($1,Ast.ListSeed $3) }
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));
1848 pure_ident_or_meta_ident_with_x_eq(x_eq):
1849 i=pure_ident_or_meta_ident l=loption(x_eq)
1854 pure_ident_or_meta_ident_with_econstraint(x_eq):
1855 i=pure_ident_or_meta_ident optc=option(x_eq)
1858 None -> (i, Ast0.NoConstraint)
1862 pure_ident_or_meta_ident_with_idconstraint_virt(constraint_type):
1863 i=pure_ident_or_meta_ident c=option(constraint_type)
1867 None -> (i, Ast.IdNoConstraint)
1868 | Some constraint_ -> (i,constraint_))
1870 | TVirtual TDot pure_ident
1872 let nm = P.id2name $3 in
1873 Iteration.parsed_virtual_identifiers :=
1874 Common.union_set [nm]
1875 !Iteration.parsed_virtual_identifiers;
1879 pure_ident_or_meta_ident_with_idconstraint(constraint_type):
1880 i=pure_ident_or_meta_ident c=option(constraint_type)
1883 None -> (i, Ast.IdNoConstraint)
1884 | Some constraint_ -> (i,constraint_)
1888 re=regexp_eqid {Ast.IdRegExpConstraint re}
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)
1899 | TTildeExclEq re=TString
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)
1908 TNotEq i=pure_ident_or_meta_ident
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");
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
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");
1929 (function (str,meta) ->
1931 (Some rn,id) as i ->
1933 P.check_inherited_constraint i
1934 (function mv -> Ast.MetaIdDecl(Ast.NONE,mv)) in
1936 | (None,i) -> (i::str,meta))
1938 Ast.IdNegIdSet(str,meta)
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}
1947 ceq=not_ceq {Ast0.NotExpCstrt ceq}
1948 | s=sub {Ast0.SubExpCstrt s}
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))))]
1958 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
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");
1965 Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))))
1970 TNotEq i=ident_or_const
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");
1976 | TNotEq TOBrace l=comma_list(ident_or_const) TCBrace
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");
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 *)
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");
1993 P.check_inherited_constraint i
1994 (function mv -> Ast.MetaExpDecl(Ast.NONE,mv,None)) in
1996 | TSub TOBrace l=comma_list(meta_ident) TCBrace
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");
2003 P.check_inherited_constraint i
2004 (function mv -> Ast.MetaExpDecl(Ast.NONE,mv,None)))
2008 i=pure_ident { Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))) }
2009 | wrapped_sym_ident { Ast0.wrap(Ast0.Ident($1)) }
2011 { let (x,clt) = $1 in
2012 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
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");
2021 P.check_inherited_constraint i
2022 (function mv -> Ast.MetaPosDecl(Ast.NONE,mv)) in
2024 | TNotEq TOBrace l=comma_list(meta_ident) TCBrace
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");
2031 P.check_inherited_constraint i
2032 (function mv -> Ast.MetaPosDecl(Ast.NONE,mv)))
2038 { let (nm,constraints,pure,clt) = $1 in
2039 Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
2041 { let (nm,constraints,pure,clt) = $1 in
2043 (Ast0.MetaLocalFunc(P.clt2mcode nm clt,constraints,pure)) }
2045 fn_ident: disj_ident { $1 }
2047 { let (nm,constraints,pure,clt) = $1 in
2048 Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
2050 { let (nm,constraints,pure,clt) = $1 in
2052 (Ast0.MetaLocalFunc(P.clt2mcode nm clt,constraints,pure)) }
2055 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
2056 | wrapped_sym_ident { $1 }
2058 { let (nm,constraints,seed,pure,clt) = $1 in
2059 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,seed,pure)) }
2062 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
2063 | wrapped_sym_ident { $1 }
2064 | TMeta { tmeta_to_ident $1 }
2066 { let (nm,constraints,seed,pure,clt) = $1 in
2067 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,seed,pure)) }
2071 | lp=TOPar0 t=midzero_list(disj_ident,disj_ident) rp=TCPar0
2072 { let (mids,code) = t in
2074 (Ast0.DisjId(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
2076 type_ident: disj_ident { $1 }
2078 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
2082 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
2084 { let (nm,constraints,pure,clt) = $1 in
2085 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,Ast.NoVal,pure)) }
2089 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
2091 { let (nm,constraints,pure,clt) = $1 in
2092 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,Ast.NoVal,pure)) }
2095 pure_ident_or_symbol
2096 { Ast0.wrap(Ast0.TypeName(P.id2mcode $1)) }
2097 | TMeta { tmeta_to_type $1 }
2099 { let (nm,pure,clt) = $1 in
2100 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
2102 /*****************************************************************************/
2105 empty_list_start(one_dec(decl),TEllipsis)
2109 (fun _ d -> Ast0.wrap(Ast0.Pdots(P.clt2mcode "..." d)))
2110 (fun c -> Ast0.PComma c))) }
2115 { let (nm,lenname,pure,clt) = $1 in
2116 let nm = P.clt2mcode nm clt in
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)) }
2124 /* ---------------------------------------------------------------------- */
2125 /* comma list parser, used for fn params, fn args, enums, initlists,
2128 /* enums: enum_decl, edots_when(TEllipsis,enum_decl_one)
2129 fun s d -> P.mkedots "..." d
2130 fun c -> Ast0.EComma c
2133 empty_list_start(elem,dotter):
2134 /* empty */ { fun build_dots build_comma -> [] }
2135 | nonempty_list_start(elem,dotter) { $1 }
2137 nonempty_list_start(elem,dotter): /* dots allowed */
2138 elem { fun build_dots build_comma -> [$1] }
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)] }
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) }
2157 continue_list(elem,dotter): /* dots not allowed */
2158 elem { fun build_dots build_comma -> [$1] }
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 }
2168 /* ---------------------------------------------------------------------- */
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
2176 TError TWords TEq TOCro cl=comma_list(dexpr) TCCro
2177 { [Ast0.wrap(Ast0.ERRORWORDS(cl))] }
2180 /* ---------------------------------------------------------------------- */
2181 /* sequences of statements and expressions */
2183 /* There are number of cases that must be considered:
2186 Dots and nests allowed at the beginning or end
2187 Expressions allowed at the beginning or end
2188 One function allowed, by itself
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
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
2202 These are implemented by the rules minus_toplevel_sequence,
2203 plus_toplevel_sequence, function_body_sequence, nest_body_sequence, and
2206 /* ------------------------------------------------------------------------ */
2207 /* Minus top level */
2209 /* doesn't allow only ... */
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 }
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 }
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 }
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}
2236 | stm_dots toplevel_after_dots {$1::$2}
2238 toplevel_after_dots:
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}
2246 | stm_dots toplevel_after_dots {$1::$2}
2247 | decl_statement toplevel_after_stm {$1@$2}
2250 TOInit initialize_list TCBrace
2251 { if P.struct_initializer $2
2253 let il = P.drop_dot_commas $2 in
2254 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
2256 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) }
2258 /* ------------------------------------------------------------------------ */
2259 /* Plus top level */
2261 /* does allow only ... also allows multiple top-level functions */
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 }
2275 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
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 }
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 }
2293 /* ------------------------------------------------------------------------ */
2297 fun_after_stm { Ast0.wrap(Ast0.DOTS($1)) }
2301 | stm_dots fun_after_dots {$1::$2}
2302 | decl_statement fun_after_stm {$1@$2}
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}
2311 stm_dots fun_after_dots {$1::$2}
2313 /* hack to allow mixing statements and expressions in an or */
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}
2322 | stm_dots fun_after_dots {$1::$2}
2324 /* ------------------------------------------------------------------------ */
2328 nest_after_dots { Ast0.wrap(Ast0.DOTS($1)) }
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}
2337 | stm_dots nest_after_dots {$1::$2}
2338 | decl_statement nest_after_stm {$1@$2}
2342 | stm_dots nest_after_dots {$1::$2}
2344 /* ------------------------------------------------------------------------ */
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)) }
2353 /* ---------------------------------------------------------------------- */
2355 /* arg expr. may contain a type or a explist metavariable */
2357 dargexpr { Ast0.set_arg_exp $1 }
2359 { let (nm,lenname,pure,clt) = $1 in
2360 let nm = P.clt2mcode nm clt in
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)) }
2368 { Ast0.set_arg_exp(Ast0.wrap(Ast0.TypeExp($1))) }
2371 empty_list_start(aexpr,TEllipsis)
2375 (fun _ d -> Ast0.wrap(Ast0.Edots(P.clt2mcode "..." d,None)))
2376 (fun c -> Ast0.EComma c))) }
2378 /****************************************************************************/
2380 // non-empty lists - drop separator
2382 separated_nonempty_list(TComma,elem) { $1 }
2384 midzero_list(elem,aft):
2385 a=elem b=list(mzl(aft))
2386 { let (mids,code) = List.split b in (mids,(a::code)) }
2389 a=TMid0 b=elem { (P.clt2mcode "|" a, b) }
2391 edots_when(dotter,when_grammar):
2392 d=dotter { (d,None) }
2393 | d=dotter TWhen TNotEq w=when_grammar TLineEnd { (d,Some w) }
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] }
2404 TAny { Ast.WhenAny }
2405 | TStrict { Ast.WhenStrict }
2406 | TForall { Ast.WhenForall }
2407 | TExists { Ast.WhenExists }
2409 /*****************************************************************************
2412 *****************************************************************************/
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
2436 (Semantic_cocci.Semantic
2437 "only one variable per declaration in an isomorphism rule") in
2438 let d1 = check_one d1 in
2442 Common.Left x -> Common.Left(check_one x)
2443 | Common.Right x -> Common.Right(check_one x))
2445 let fn x = Ast0.DeclTag x in P.iso_adjust fn fn d1 dl }
2448 TIso t=term { Common.Left t }
2449 | TRightIso t=term { Common.Right t }
2451 /*****************************************************************************
2454 *****************************************************************************/
2456 never_used: TPragma { () }
2457 | TPArob TMetaPos { () }
2458 | TScriptData { () }
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) }
2473 TShLOp TRuleName TDot cocci=pure_ident
2474 { let nm = P.id2name cocci in
2475 let mv = Parse_aux.lookup $2 nm in
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