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.
29 (* Not clear how to allow function declarations to specify a return type
30 and how to allow both to be specified as static, because they are in
31 different rules. The rules seem to have to be combined, which would allow
32 functions to be declared as local variables *)
34 (* Not clear how to let a function have a parameter of type void. At the
35 moment, void is allowed to be the type of a variable, which is wrong, and a
36 parameter needs both a type and an identifier *)
37 module Ast0 = Ast0_cocci
38 module Ast = Ast_cocci
41 (* ---------------------------------------------------------------------- *)
42 (* support for TMeta *)
44 let print_meta (r,n) = r^"."^n
46 let meta_metatable = Hashtbl.create(101)
48 let coerce_tmeta newty name builder matcher =
50 let x = Hashtbl.find meta_metatable name in
54 (Printf.sprintf "Metavariable %s is used as %s"
55 (print_meta name) newty)
57 (if !Flag_parsing_cocci.show_SP
61 "Metavariable %s is assumed to be %s metavariable"
62 (print_meta name) newty));
63 Hashtbl.add meta_metatable name builder
65 let tmeta_to_type (name,pure,clt) =
66 (coerce_tmeta "a type" name (TMetaType(name,pure,clt))
67 (function TMetaType(_,_,_) -> true | _ -> false));
68 Ast0.wrap(Ast0.MetaType(P.clt2mcode name clt,pure))
70 let tmeta_to_field (name,pure,clt) =
71 (coerce_tmeta "a field" name (TMetaField(name,pure,clt))
72 (function TMetaField(_,_,_) -> true | _ -> false));
73 P.meta_field (name,pure,clt)
75 let tmeta_to_exp (name,pure,clt) =
76 (coerce_tmeta "an expression" name
77 (TMetaExp(name,Ast0.NoConstraint,pure,None,clt))
78 (function TMetaExp(_,_,_,_,_) -> true | _ -> false));
80 (Ast0.MetaExpr(P.clt2mcode name clt,Ast0.NoConstraint,None,Ast.ANY,pure))
82 let tmeta_to_param (name,pure,clt) =
83 (coerce_tmeta "a parameter" name (TMetaParam(name,pure,clt))
84 (function TMetaParam(_,_,_) -> true | _ -> false));
85 Ast0.wrap(Ast0.MetaParam(P.clt2mcode name clt,pure))
87 let tmeta_to_statement (name,pure,clt) =
88 (coerce_tmeta "a statement" name (TMetaType(name,pure,clt))
89 (function TMetaType(_,_,_) -> true | _ -> false));
90 P.meta_stm (name,pure,clt)
92 let tmeta_to_seed_id (name,pure,clt) =
93 (coerce_tmeta "an identifier" name
94 (TMetaId(name,Ast.IdNoConstraint,Ast.NoVal,pure,clt))
95 (function TMetaId(_,_,_,_,_) -> true | _ -> false));
98 let tmeta_to_ident (name,pure,clt) =
99 (coerce_tmeta "an identifier" name
100 (TMetaId(name,Ast.IdNoConstraint,Ast.NoVal,pure,clt))
101 (function TMetaId(_,_,_,_,_) -> true | _ -> false));
102 Ast0.wrap(Ast0.MetaId(P.clt2mcode name clt,Ast.IdNoConstraint,Ast.NoVal,pure))
107 %token TIdentifier TExpression TStatement TFunction TLocal TType TParameter
108 %token TIdExpression TInitialiser TDeclaration TField TMetavariable TSymbol
109 %token Tlist TFresh TConstant TError TWords TWhy0 TPlus0 TBang0
110 %token TPure TContext TGenerated
111 %token TTypedef TDeclarer TIterator TName TPosition TPosAny
112 %token TUsing TDisable TExtends TDepends TOn TEver TNever TExists TForall
113 %token TScript TInitialize TFinalize TNothing TVirtual
114 %token<string> TRuleName
116 %token<Data.clt> Tchar Tshort Tint Tdouble Tfloat Tlong
117 %token<Data.clt> Tsize_t Tssize_t Tptrdiff_t
118 %token<Data.clt> Tvoid Tstruct Tunion Tenum
119 %token<Data.clt> Tunsigned Tsigned
121 %token<Data.clt> Tstatic Tauto Tregister Textern Tinline Ttypedef
122 %token<Data.clt> Tconst Tvolatile
123 %token<string * Data.clt> Tattr
125 %token <Data.clt> TIf TElse TWhile TFor TDo TSwitch TCase TDefault TReturn
126 %token <Data.clt> TBreak TContinue TGoto TSizeof TFunDecl
127 %token <string * Data.clt> TIdent TTypeId TDeclarerId TIteratorId TSymId
128 %token <Ast_cocci.added_string * Data.clt> TPragma
130 %token <Parse_aux.midinfo> TMetaId
131 %token <Parse_aux.idinfo> TMetaFunc TMetaLocalFunc
132 %token <Parse_aux.idinfo> TMetaIterator TMetaDeclarer
133 %token <Parse_aux.expinfo> TMetaErr
134 %token <Parse_aux.info> TMetaParam TMetaStm TMetaStmList TMetaType
135 %token <Parse_aux.info> TMetaInit TMetaDecl TMetaField TMeta
136 %token <Parse_aux.list_info> TMetaParamList TMetaExpList TMetaInitList
137 %token <Parse_aux.list_info> TMetaFieldList
138 %token <Parse_aux.typed_expinfo> TMetaExp TMetaIdExp TMetaLocalIdExp TMetaConst
139 %token <Parse_aux.pos_info> TMetaPos
141 %token TArob TArobArob
142 %token <Data.clt> TPArob
143 %token <string> TScriptData
145 %token <Data.clt> TEllipsis TOEllipsis TCEllipsis TPOEllipsis TPCEllipsis
146 %token <Data.clt> TWhen TWhenTrue TWhenFalse TAny TStrict TLineEnd
148 %token <Data.clt> TWhy TDotDot TBang TOPar TOPar0
149 %token <Data.clt> TMid0 TCPar TCPar0
151 %token <string> TPathIsoFile
152 %token <string * Data.clt> TIncludeL TIncludeNL
153 %token <Data.clt * token> TDefine TUndef
154 %token <Data.clt * token * int * int> TDefineParam
155 %token <string * Data.clt> TMinusFile TPlusFile
157 %token <Data.clt> TInc TDec
159 %token <string * Data.clt> TString TChar TFloat TInt
161 %token <Data.clt> TOrLog
162 %token <Data.clt> TAndLog
163 %token <Data.clt> TOr
164 %token <Data.clt> TXor
165 %token <Data.clt> TAnd
166 %token <Data.clt> TEqEq TNotEq TTildeEq TTildeExclEq TSub
167 %token <Ast_cocci.logicalOp * Data.clt> TLogOp /* TInf TSup TInfEq TSupEq */
168 %token <Ast_cocci.arithOp * Data.clt> TShLOp TShROp /* TShl TShr */
169 %token <Ast_cocci.arithOp * Data.clt> TDmOp /* TDiv TMod */
170 %token <Data.clt> TPlus TMinus
171 %token <Data.clt> TMul TTilde
173 %token <Data.clt> TOBrace TCBrace TOInit
174 %token <Data.clt> TOCro TCCro
176 %token <Data.clt> TPtrOp
178 %token TMPtVirg TCppConcatOp
179 %token <Data.clt> TEq TDot TComma TPtVirg
180 %token <Ast_cocci.assignOp * Data.clt> TAssign
182 %token TIso TRightIso TIsoExpression TIsoStatement TIsoDeclaration TIsoType
183 %token TIsoTopLevel TIsoArgExpression TIsoTestExpression TIsoToTestExpression
189 /* operator precedence */
199 %left TLogOp /* TInf TSup TInfEq TSupEq */
200 %left TShLOp TShROp /* TShl TShr */
202 %left TMul TDmOp /* TDiv TMod */
208 %type <Ast0_cocci.rule> minus_main
210 %start minus_exp_main
211 %type <Ast0_cocci.rule> minus_exp_main
214 %type <Ast0_cocci.rule> plus_main
217 %type <Ast0_cocci.rule> plus_exp_main
220 %type <Data.incl_iso list> include_main
223 %type <Ast_cocci.rulename>
227 %type <Ast_cocci.rulename>
231 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> meta_main
233 %start <(string option (*string*) * string option (*ast*)) * (Ast_cocci.meta_name * Ast_cocci.metavar) option> script_meta_main
236 %type <Ast0_cocci.anything list list> iso_main
239 %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> iso_meta_main
242 %type <unit> never_used
247 minus_main: minus_body EOF { $1 } | m=minus_body TArobArob { m }
248 | m=minus_body TArob { m }
249 plus_main: plus_body EOF { $1 } | p=plus_body TArobArob { p }
250 | p=plus_body TArob { p }
251 minus_exp_main: minus_exp_body EOF { $1 } | m=minus_exp_body TArobArob { m }
252 | m=minus_exp_body TArob { m }
253 plus_exp_main: plus_exp_body EOF { $1 } | p=plus_exp_body TArobArob { p }
254 | p=plus_exp_body TArob { p }
255 meta_main: m=metadec { m (!Ast0.rule_name) }
256 iso_meta_main: m=metadec { m "" }
258 /*****************************************************************************
261 *****************************************************************************/
265 | TContext { Ast0.Context }
266 | TPure TContext { Ast0.PureContext }
267 | TContext TPure { Ast0.PureContext }
268 | /* empty */ { Ast0.Impure }
271 nm=pure_ident TArob { P.make_iso_rule_name_result (P.id2name nm) }
274 nm=ioption(pure_ident) extends d=depends i=loption(choose_iso)
275 a=loption(disable) e=exists ee=is_expression TArob
276 { P.make_cocci_rule_name_result nm d i a e ee }
277 | TGenerated extends d=depends i=loption(choose_iso)
278 a=loption(disable) e=exists ee=is_expression TArob
279 /* these rules have no name as a cheap way to ensure that no normal
280 rule inherits their metavariables or depends on them */
281 { P.make_generated_rule_name_result None d i a e ee }
282 | TScript TDotDot lang=pure_ident nm=ioption(pure_ident) d=depends TArob
283 { P.make_script_rule_name_result lang nm d }
284 | TInitialize TDotDot lang=pure_ident d=depends TArob
285 { P.make_initial_script_rule_name_result lang d }
286 | TFinalize TDotDot lang=pure_ident d=depends TArob
287 { P.make_final_script_rule_name_result lang d }
291 | TExtends parent=TRuleName
292 { !Data.install_bindings (parent) }
295 /* empty */ { Ast0.NoDep }
296 | TDepends TOn parents=dep { parents }
299 TRuleName { Ast0.Dep $1 }
300 | TBang TRuleName { Ast0.AntiDep (Ast0.Dep $2) }
301 | TBang TOPar dep TCPar
303 | TEver TRuleName { Ast0.EverDep $2 }
304 | TNever TRuleName { Ast0.NeverDep $2 }
305 | dep TAndLog dep { Ast0.AndDep($1, $3) }
306 | dep TOrLog dep { Ast0.OrDep ($1, $3) }
307 | TOPar dep TCPar { $2 }
310 TUsing separated_nonempty_list(TComma,TString) { List.map P.id2name $2 }
313 TDisable separated_nonempty_list(TComma,pure_ident) { List.map P.id2name $2 }
316 TExists { Ast.Exists }
317 | TForall { Ast.Forall }
318 | { Ast.Undetermined }
320 is_expression: // for more flexible parsing of top level expressions
322 | TExpression { true }
325 list(incl) TArob { $1 }
326 | list(incl) TArobArob { $1 }
329 TIncludeL { let (x,_) = $1 in Data.Include(x) }
330 | TUsing TString { Data.Iso(Common.Left(P.id2name $2)) }
331 | TUsing TPathIsoFile { Data.Iso(Common.Right $2) }
332 | TVirtual comma_list(pure_ident)
333 { let names = List.map P.id2name $2 in
334 Iteration.parsed_virtual_rules :=
335 Common.union_set names !Iteration.parsed_virtual_rules;
336 (* ensure that the names of virtual and real rules don't overlap *)
338 (function name -> Hashtbl.add Data.all_metadecls name [])
344 kindfn=metakind ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
345 { P.create_metadec ar ispure kindfn ids }
346 | kindfn=metakind_fresh ids=comma_list(pure_ident_or_meta_ident_with_seed)
348 { P.create_fresh_metadec kindfn ids }
349 | ar=arity ispure=pure
350 kindfn=metakind_atomic_maybe_virt
352 comma_list(pure_ident_or_meta_ident_with_idconstraint_virt(re_or_not_eqid))
354 { let (normal,virt) = Common.partition_either (fun x -> x) ids in
355 let (idfn,virtfn) = kindfn in
357 (P.create_metadec_with_constraints ar ispure idfn normal cr) @
358 (P.create_metadec_virt ar ispure virtfn virt cr) }
359 | ar=arity ispure=pure
360 kindfn=metakind_atomic
361 ids=comma_list(pure_ident_or_meta_ident_with_idconstraint(re_or_not_eqid))
363 { P.create_metadec_with_constraints ar ispure kindfn ids }
364 | ar=arity ispure=pure
365 kindfn=metakind_atomic_expi
366 ids=comma_list(pure_ident_or_meta_ident_with_econstraint(re_or_not_eqe_or_sub))
368 { P.create_metadec_with_constraints ar ispure kindfn ids }
369 | ar=arity ispure=pure
370 kindfn=metakind_atomic_expe
371 ids=comma_list(pure_ident_or_meta_ident_with_econstraint(not_ceq_or_sub))
373 { P.create_metadec_with_constraints ar ispure kindfn ids }
374 | ar=arity TPosition a=option(TPosAny)
375 ids=comma_list(pure_ident_or_meta_ident_with_x_eq(not_pos)) TMPtVirg
376 (* pb: position variables can't be inherited from normal rules, and then
377 there is no way to inherit from a generated rule, so there is no point
378 to have a position variable *)
379 { (if !Data.in_generating
380 then failwith "position variables not allowed in a generated rule file");
381 let kindfn arity name pure check_meta constraints =
382 let tok = check_meta(Ast.MetaPosDecl(arity,name)) in
383 let any = match a with None -> Ast.PER | Some _ -> Ast.ALL in
384 !Data.add_pos_meta name constraints any; tok in
385 P.create_metadec_with_constraints ar false kindfn ids }
386 | ar=arity ispure=pure
387 TParameter Tlist TOCro len=list_len TCCro
388 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
389 { P.create_len_metadec ar ispure
390 (fun lenname arity name pure check_meta ->
391 let tok = check_meta(Ast.MetaParamListDecl(arity,name,lenname)) in
392 !Data.add_paramlist_meta name lenname pure; tok)
394 | ar=arity ispure=pure
395 TExpression Tlist TOCro len=list_len TCCro
396 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
397 { P.create_len_metadec ar ispure
398 (fun lenname arity name pure check_meta ->
399 let tok = check_meta(Ast.MetaExpListDecl(arity,name,lenname)) in
400 !Data.add_explist_meta name lenname pure; tok)
402 | ar=arity ispure=pure
403 TField Tlist TOCro len=list_len TCCro
404 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
405 { P.create_len_metadec ar ispure
406 (fun lenname arity name pure check_meta ->
407 let tok = check_meta(Ast.MetaFieldListDecl(arity,name,lenname)) in
408 !Data.add_field_list_meta name lenname pure; tok)
410 | ar=arity ispure=pure
411 TInitialiser Tlist TOCro len=list_len TCCro
412 ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
413 { P.create_len_metadec ar ispure
414 (fun lenname arity name pure check_meta ->
415 let tok = check_meta(Ast.MetaInitListDecl(arity,name,lenname)) in
416 !Data.add_initlist_meta name lenname pure; tok)
418 | TSymbol ids=comma_list(pure_ident) TMPtVirg
420 let add_sym = fun (nm,_) -> !Data.add_symbol_meta nm in
421 List.iter add_sym ids; [])
425 pure_ident_or_meta_ident { Common.Left $1 }
426 | TInt { let (x,clt) = $1 in Common.Right (int_of_string x) }
428 %inline metakind_fresh:
430 { (fun name check_meta seed ->
431 let tok = check_meta(Ast.MetaFreshIdDecl(name,seed)) in
432 !Data.add_fresh_id_meta name seed; tok) }
434 /* metavariable kinds with no constraints, etc */
437 { (fun arity name pure check_meta ->
438 let tok = check_meta(Ast.MetaMetaDecl(arity,name)) in
439 !Data.add_meta_meta name pure; tok) }
441 { (fun arity name pure check_meta ->
442 let tok = check_meta(Ast.MetaParamDecl(arity,name)) in
443 !Data.add_param_meta name pure; tok) }
445 { (fun arity name pure check_meta ->
446 let len = Ast.AnyLen in
447 let tok = check_meta(Ast.MetaParamListDecl(arity,name,len)) in
448 !Data.add_paramlist_meta name len pure; tok) }
450 { (fun arity name pure check_meta ->
451 let len = Ast.AnyLen in
452 let tok = check_meta(Ast.MetaExpListDecl(arity,name,len)) in
453 !Data.add_explist_meta name len pure; tok) }
455 { (fun arity name pure check_meta ->
456 let tok = check_meta(Ast.MetaTypeDecl(arity,name)) in
457 !Data.add_type_meta name pure; tok) }
459 { (fun arity name pure check_meta ->
460 let tok = check_meta(Ast.MetaInitDecl(arity,name)) in
461 !Data.add_init_meta name pure; tok) }
463 { (fun arity name pure check_meta ->
464 let len = Ast.AnyLen in
465 let tok = check_meta(Ast.MetaInitListDecl(arity,name,len)) in
466 !Data.add_initlist_meta name len pure; tok) }
468 { (fun arity name pure check_meta ->
469 let tok = check_meta(Ast.MetaStmDecl(arity,name)) in
470 !Data.add_stm_meta name pure; tok) }
472 { (fun arity name pure check_meta ->
473 let tok = check_meta(Ast.MetaDeclDecl(arity,name)) in
474 !Data.add_decl_meta name pure; tok) }
476 { (fun arity name pure check_meta ->
477 let tok = check_meta(Ast.MetaFieldDecl(arity,name)) in
478 !Data.add_field_meta name pure; tok) }
480 { (fun arity name pure check_meta ->
481 let len = Ast.AnyLen in
482 let tok = check_meta(Ast.MetaFieldListDecl(arity,name,len)) in
483 !Data.add_field_list_meta name len pure; tok) }
485 { (fun arity name pure check_meta ->
486 let tok = check_meta(Ast.MetaStmListDecl(arity,name)) in
487 !Data.add_stmlist_meta name pure; tok) }
489 { (fun arity (_,name) pure check_meta ->
490 if arity = Ast.NONE && pure = Ast0.Impure
491 then (!Data.add_type_name name; [])
492 else raise (Semantic_cocci.Semantic "bad typedef")) }
494 { (fun arity (_,name) pure check_meta ->
495 if arity = Ast.NONE && pure = Ast0.Impure
496 then (!Data.add_declarer_name name; [])
497 else raise (Semantic_cocci.Semantic "bad declarer")) }
499 { (fun arity (_,name) pure check_meta ->
500 if arity = Ast.NONE && pure = Ast0.Impure
501 then (!Data.add_iterator_name name; [])
502 else raise (Semantic_cocci.Semantic "bad iterator")) }
504 %inline metakind_atomic_maybe_virt:
507 let idfn arity name pure check_meta constraints =
508 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
509 !Data.add_id_meta name constraints pure; tok in
510 let virtfn arity name pure check_meta virtual_env =
512 let vl = List.assoc name virtual_env in
513 !Data.add_virt_id_meta_found name vl; []
515 Iteration.parsed_virtual_identifiers :=
516 Common.union_set [name]
517 !Iteration.parsed_virtual_identifiers;
518 let name = ("virtual",name) in
519 let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
520 !Data.add_virt_id_meta_not_found name pure; tok in
523 %inline metakind_atomic:
525 { (fun arity name pure check_meta constraints ->
526 let tok = check_meta(Ast.MetaFuncDecl(arity,name)) in
527 !Data.add_func_meta name constraints pure; tok) }
529 { (fun arity name pure check_meta constraints ->
530 let tok = check_meta(Ast.MetaLocalFuncDecl(arity,name)) in
531 !Data.add_local_func_meta name constraints pure;
534 { (fun arity name pure check_meta constraints ->
535 let tok = check_meta(Ast.MetaDeclarerDecl(arity,name)) in
536 !Data.add_declarer_meta name constraints pure; tok) }
538 { (fun arity name pure check_meta constraints ->
539 let tok = check_meta(Ast.MetaIteratorDecl(arity,name)) in
540 !Data.add_iterator_meta name constraints pure; tok) }
542 %inline metakind_atomic_expi:
544 { (fun arity name pure check_meta constraints ->
545 let tok = check_meta(Ast.MetaErrDecl(arity,name)) in
546 !Data.add_err_meta name constraints pure; tok) }
547 | l=option(TLocal) TIdExpression ty=ioption(meta_exp_type)
548 { (fun arity name pure check_meta constraints ->
551 !Data.add_idexp_meta ty name constraints pure;
552 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
554 !Data.add_local_idexp_meta ty name constraints pure;
555 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
556 | l=option(TLocal) TIdExpression m=nonempty_list(TMul)
557 { (fun arity name pure check_meta constraints ->
558 let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
561 !Data.add_idexp_meta ty name constraints pure;
562 check_meta(Ast.MetaIdExpDecl(arity,name,ty))
564 !Data.add_local_idexp_meta ty name constraints pure;
565 check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
566 | TExpression ty=expression_type
567 { (fun arity name pure check_meta constraints ->
568 let ty = Some [ty] in
569 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
570 !Data.add_exp_meta ty name constraints pure; tok) }
571 | TConstant ty=ioption(meta_exp_type)
572 { (fun arity name pure check_meta constraints ->
573 let tok = check_meta(Ast.MetaConstDecl(arity,name,ty)) in
574 !Data.add_const_meta ty name constraints pure; tok) }
577 m=nonempty_list(TMul) { P.ty_pointerify Type_cocci.Unknown m }
579 { P.ty_pointerify (Type_cocci.EnumName Type_cocci.NoName) m }
580 | Tstruct m=list(TMul)
582 (Type_cocci.StructUnionName (Type_cocci.Struct,Type_cocci.NoName)) m }
583 | Tunion m=list(TMul)
585 (Type_cocci.StructUnionName (Type_cocci.Union,Type_cocci.NoName)) m }
588 metakind_atomic_expe:
590 { (fun arity name pure check_meta constraints ->
591 let tok = check_meta(Ast.MetaExpDecl(arity,name,None)) in
592 !Data.add_exp_meta None name constraints pure; tok) }
593 | vl=meta_exp_type // no error if use $1 but doesn't type check
594 { (fun arity name pure check_meta constraints ->
596 (match constraints with
597 Ast0.NotExpCstrt constraints ->
600 match Ast0.unwrap c with
605 Type_cocci.BaseType(Type_cocci.IntType) -> true
606 | Type_cocci.BaseType(Type_cocci.ShortType) -> true
607 | Type_cocci.BaseType(Type_cocci.LongType) -> true
611 failwith "metavariable with int constraint must be an int"
615 let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
616 !Data.add_exp_meta ty name constraints pure; tok)
621 { [Ast0_cocci.ast0_type_to_type t] }
622 | t=typedef_ctype TOCro TCCro
623 { [Type_cocci.Array (Ast0_cocci.ast0_type_to_type t)] }
624 | TOBrace t=comma_list(ctype) TCBrace m=list(TMul)
626 (function x -> P.ty_pointerify (Ast0_cocci.ast0_type_to_type x) m)
629 arity: TBang0 { Ast.UNIQUE }
631 | TPlus0 { Ast.MULTI }
632 | /* empty */ { Ast.NONE }
634 /* ---------------------------------------------------------------------- */
638 { Ast0.wrap(Ast0.BaseType(Ast.CharType,[P.clt2mcode "char" ty])) }
640 { Ast0.wrap(Ast0.BaseType(Ast.ShortType,[P.clt2mcode "short" ty])) }
641 | ty1=Tshort ty2=Tint
644 (Ast.ShortIntType,[P.clt2mcode "short" ty1;P.clt2mcode "int" ty2])) }
646 { Ast0.wrap(Ast0.BaseType(Ast.IntType,[P.clt2mcode "int" ty])) }
648 { let (nm,pure,clt) = p in
649 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
650 | r=TRuleName TDot p=TIdent
651 { let nm = (r,P.id2name p) in
652 (* this is only possible when we are in a metavar decl. Otherwise,
653 it will be represented already as a MetaType *)
654 let _ = P.check_meta(Ast.MetaTypeDecl(Ast.NONE,nm)) in
655 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm (P.id2clt p),
656 Ast0.Impure (*will be ignored*))) }
658 { Ast0.wrap(Ast0.BaseType(Ast.LongType,[P.clt2mcode "long" ty1])) }
662 (Ast.LongIntType,[P.clt2mcode "long" ty1;P.clt2mcode "int" ty2])) }
663 | ty1=Tlong ty2=Tlong
667 [P.clt2mcode "long" ty1;P.clt2mcode "long" ty2])) }
668 | ty1=Tlong ty2=Tlong ty3=Tint
671 (Ast.LongLongIntType,
672 [P.clt2mcode "long" ty1;P.clt2mcode "long" ty2;
673 P.clt2mcode "int" ty3])) }
677 { Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" ty])) }
678 | ty1=Tlong ty2=Tdouble
682 [P.clt2mcode "long" ty1;P.clt2mcode "double" ty2])) }
684 { Ast0.wrap(Ast0.BaseType(Ast.DoubleType,[P.clt2mcode "double" ty])) }
686 { Ast0.wrap(Ast0.BaseType(Ast.FloatType,[P.clt2mcode "float" ty])) }
688 { Ast0.wrap(Ast0.BaseType(Ast.SizeType,[P.clt2mcode "size_t" ty])) }
690 { Ast0.wrap(Ast0.BaseType(Ast.SSizeType,[P.clt2mcode "ssize_t" ty])) }
692 { Ast0.wrap(Ast0.BaseType(Ast.PtrDiffType,[P.clt2mcode "ptrdiff_t" ty])) }
694 { Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, Some i)) }
695 | s=Tenum i=ioption(ident) l=TOBrace ids=enum_decl_list r=TCBrace
696 { (if i = None && !Data.in_iso
697 then failwith "enums must be named in the iso file");
698 Ast0.wrap(Ast0.EnumDef(Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, i)),
699 P.clt2mcode "{" l, ids, P.clt2mcode "}" r)) }
700 | s=struct_or_union i=type_ident // allow typedef name
701 { Ast0.wrap(Ast0.StructUnionName(s, Some i)) }
702 | s=struct_or_union i=ioption(type_ident)
703 l=TOBrace d=struct_decl_list r=TCBrace
704 { (if i = None && !Data.in_iso
705 then failwith "structures must be named in the iso file");
706 Ast0.wrap(Ast0.StructUnionDef(Ast0.wrap(Ast0.StructUnionName(s, i)),
708 d, P.clt2mcode "}" r)) }
709 | s=TMetaType l=TOBrace d=struct_decl_list r=TCBrace
710 { let (nm,pure,clt) = s in
711 let ty = Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) in
712 Ast0.wrap(Ast0.StructUnionDef(ty,P.clt2mcode "{" l,d,P.clt2mcode "}" r)) }
714 { Ast0.wrap(Ast0.TypeName(P.id2mcode p)) }
717 r=Tsigned ty=signable_types
718 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,Some ty)) }
719 | r=Tunsigned ty=signable_types
720 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,Some ty)) }
721 | ty=signable_types { ty }
722 | ty=non_signable_types { ty }
725 cv=ioption(const_vol) ty=all_basic_types m=list(mul)
728 function (star,cv) ->
729 P.make_cv cv (P.pointerify prev [star]))
730 (P.make_cv cv ty) m }
732 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,None)) }
734 { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,None)) }
735 | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
736 { let (mids,code) = t in
738 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
740 mul: a=TMul b=ioption(const_vol) { (a,b) }
743 | TMeta { tmeta_to_type $1 }
746 /* signed, unsigned alone not allowed */
748 cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
749 { P.pointerify (P.make_cv cv ty) m }
750 | lp=TOPar0 t=midzero_list(mctype,mctype) rp=TCPar0
751 { let (mids,code) = t in
753 (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
754 | TMeta { tmeta_to_type $1 }
756 /* ---------------------------------------------------------------------- */
759 s=Tstruct { P.clt2mcode Ast.Struct s }
760 | u=Tunion { P.clt2mcode Ast.Union u }
764 | struct_decl_one { [$1] }
767 | TMetaField { P.meta_field $1 }
768 | TMetaFieldList { P.meta_field_list $1 }
769 | TMeta { tmeta_to_field $1 }
770 | lp=TOPar0 t=midzero_list(struct_decl_one,struct_decl_one) rp=TCPar0
771 { let (mids,code) = t in
773 (Ast0.DisjDecl(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
774 | t=ctype d=d_ident pv=TPtVirg
776 Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv)) }
777 | t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
778 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar pv=TPtVirg
782 (Ast0.FunctionPointer
783 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
784 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
785 Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv)) }
786 | cv=ioption(const_vol) i=pure_ident_or_symbol d=d_ident pv=TPtVirg
788 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
789 Ast0.wrap(Ast0.UnInit(None,fn idtype,id,P.clt2mcode ";" pv)) }
792 struct_decl_list_start { Ast0.wrap(Ast0.DOTS($1)) }
794 struct_decl_list_start:
796 | struct_decl struct_decl_list_start { $1@$2 }
797 | d=edots_when(TEllipsis,struct_decl_one) r=continue_struct_decl_list
798 { (P.mkddots_one "..." d)::r }
800 continue_struct_decl_list:
802 | struct_decl struct_decl_list_start { $1@$2 }
806 /* ---------------------------------------------------------------------- */
807 /* very restricted what kinds of expressions can appear in an enum decl */
810 | disj_ident { Ast0.wrap(Ast0.Ident($1)) }
811 | disj_ident TEq enum_val
812 { let id = Ast0.wrap(Ast0.Ident($1)) in
815 (id,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,
819 ident { Ast0.wrap(Ast0.Ident($1)) }
821 { let (x,clt) = $1 in
822 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
823 | TMeta { tmeta_to_exp $1 }
825 { let (nm,constraints,pure,ty,clt) = $1 in
827 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
829 { let (nm,constraints,pure,ty,clt) = $1 in
831 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
833 { let (nm,constraints,pure,ty,clt) = $1 in
835 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
838 nonempty_list_start(enum_decl_one,edots_when(TEllipsis,enum_decl_one))
839 { Ast0.wrap(Ast0.DOTS($1 P.mkedots (fun c -> Ast0.EComma c))) }
841 /*****************************************************************************/
843 /* have to inline everything to avoid conflicts? switch to proper
844 declarations, statements, and expressions for the subterms */
848 b=loption(minus_start)
849 /*ew=loption(error_words)*/
850 { match f@b(*@ew*) with
851 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
856 b=loption(plus_start)
857 /*ew=loption(error_words)*/
863 /*ew=loption(error_words)*/
864 { match f@[b](*@ew*) with
865 [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
871 /*ew=loption(error_words)*/
877 (Ast0.FILEINFO(P.id2mcode $1,
883 (Ast0.Include(P.clt2mcode "#include"
884 (P.drop_pos (P.drop_aft (P.id2clt $1))),
885 let (arity,ln,lln,offset,col,strbef,straft,pos) =
888 (arity,ln,lln,offset,0,strbef,straft,pos) in
890 (Ast.Local (Parse_aux.str2inc (P.id2name $1)))
894 (Ast0.Include(P.clt2mcode "#include"
895 (P.drop_pos (P.drop_aft (P.id2clt $1))),
896 let (arity,ln,lln,offset,col,strbef,straft,pos) =
899 (arity,ln,lln,offset,0,strbef,straft,pos) in
901 (Ast.NonLocal (Parse_aux.str2inc (P.id2name $1)))
904 { let (clt,ident) = $1 in
905 let aft = P.get_aft clt in (* move stuff after the define to the ident *)
908 (P.clt2mcode "#undef" (P.drop_aft clt),
910 TMetaId((nm,constraints,seed,pure,clt)) ->
911 let clt = P.set_aft aft clt in
912 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,seed,pure))
913 | TIdent((nm,clt)) ->
914 let clt = P.set_aft aft clt in
915 Ast0.wrap(Ast0.Id(P.clt2mcode nm clt))
917 let clt = P.set_aft aft clt in
918 Ast0.wrap(Ast0.Id(P.clt2mcode nm clt))
921 (Semantic_cocci.Semantic
922 "unexpected name for a #define")))) }
923 | d=defineop TLineEnd
924 { d (Ast0.wrap(Ast0.DOTS([]))) }
925 | d=defineop t=ctype TLineEnd
926 { let ty = Ast0.wrap(Ast0.TopExp(Ast0.wrap(Ast0.TypeExp(t)))) in
927 d (Ast0.wrap(Ast0.DOTS([ty]))) }
928 | defineop b=toplevel_seq_start(toplevel_after_dots) TLineEnd
932 (match Ast0.unwrap e with
934 [Ast0.rewrap e (Ast0.TopExp(Ast0.set_arg_exp (e1)))]
937 $1 (Ast0.wrap(Ast0.DOTS(body))) }
941 { let (clt,ident) = $1 in
942 let aft = P.get_aft clt in (* move stuff after the define to the ident *)
946 (P.clt2mcode "#define" (P.drop_aft clt),
948 TMetaId((nm,constraints,seed,pure,clt)) ->
949 let clt = P.set_aft aft clt in
951 (Ast0.MetaId(P.clt2mcode nm clt,constraints,seed,pure))
952 | TIdent((nm,clt)) ->
953 let clt = P.set_aft aft clt in
954 Ast0.wrap(Ast0.Id(P.clt2mcode nm clt))
956 let clt = P.set_aft aft clt in
957 Ast0.wrap(Ast0.Id(P.clt2mcode nm clt))
960 (Semantic_cocci.Semantic
961 "unexpected name for a #define")),
962 Ast0.wrap Ast0.NoParams,
964 | TDefineParam define_param_list_option TCPar
965 { let (clt,ident,parenoff,parencol) = $1 in
966 let aft = P.get_aft clt in (* move stuff after the define to the ( *)
967 (* clt is the start of the #define itself *)
968 let (arity,line,lline,offset,col,strbef,straft,pos) = clt in
971 (arity,line,lline,parenoff,parencol,[],[],[]) in
975 (P.clt2mcode "#define" (P.drop_aft clt),
977 TMetaId((nm,constraints,seed,pure,clt)) ->
979 (Ast0.MetaId(P.clt2mcode nm clt,constraints,seed,pure))
980 | TIdent((nm,clt)) ->
981 Ast0.wrap(Ast0.Id(P.clt2mcode nm clt))
983 Ast0.wrap(Ast0.Id(P.clt2mcode nm clt))
986 (Semantic_cocci.Semantic
987 "unexpected name for a #define")),
988 (let clt = P.set_aft aft $3 in
989 Ast0.wrap (Ast0.DParams (lp,$2,P.clt2mcode ")" clt))),body)) }
991 /* ---------------------------------------------------------------------- */
993 dparam: mident { Ast0.wrap(Ast0.DParam $1) }
995 define_param_list_option:
996 empty_list_start(dparam,TEllipsis)
1000 (fun _ d -> Ast0.wrap(Ast0.DPdots(P.clt2mcode "," d)))
1001 (fun c -> Ast0.DPComma c))) }
1003 /*****************************************************************************/
1006 s=ioption(storage) t=ctype
1007 id=fn_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
1012 (Ast0.FunctionType(Some t,
1013 P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
1014 id, P.clt2mcode ";" pt)) }
1018 TFunDecl i=fn_ident lp=TOPar d=decl_list(decl) rp=TCPar
1019 lb=TOBrace b=fun_start rb=TCBrace
1020 { P.verify_parameter_declarations (Ast0.undots d);
1021 Ast0.wrap(Ast0.FunDecl((Ast0.default_info(),Ast0.context_befaft()),
1023 P.clt2mcode "(" lp, d,
1025 P.clt2mcode "{" lb, b,
1026 P.clt2mcode "}" rb)) }
1033 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
1034 raise (Semantic_cocci.Semantic "duplicate storage")
1035 with Not_found -> (Ast0.FStorage($1))::$2 }
1036 | t=ctype r=fninfo_nt { (Ast0.FType(t))::r }
1039 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
1040 raise (Semantic_cocci.Semantic "duplicate inline")
1041 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
1044 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
1045 raise (Semantic_cocci.Semantic "multiple attributes")
1046 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
1053 List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
1054 raise (Semantic_cocci.Semantic "duplicate storage")
1055 with Not_found -> (Ast0.FStorage($1))::$2 }
1058 let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
1059 raise (Semantic_cocci.Semantic "duplicate inline")
1060 with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
1063 let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
1064 raise (Semantic_cocci.Semantic "duplicate init")
1065 with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
1068 s=Tstatic { P.clt2mcode Ast.Static s }
1069 | s=Tauto { P.clt2mcode Ast.Auto s }
1070 | s=Tregister { P.clt2mcode Ast.Register s }
1071 | s=Textern { P.clt2mcode Ast.Extern s }
1073 decl: t=ctype i=disj_ident a=list(array_dec)
1074 { let t = P.arrayify t a in Ast0.wrap(Ast0.Param(t, Some i)) }
1075 | t=ctype { (*verify in FunDecl*) Ast0.wrap(Ast0.Param(t, None)) }
1076 | t=ctype lp=TOPar s=TMul i=disj_ident rp=TCPar
1077 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
1080 (Ast0.FunctionPointer
1081 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
1082 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
1083 Ast0.wrap(Ast0.Param(fnptr, Some i)) }
1085 { let (nm,pure,clt) = $1 in
1086 Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) }
1087 | TMeta { tmeta_to_param $1 }
1091 | t=ctype lp=TOPar s=TMul rp=TCPar
1092 lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
1095 (Ast0.FunctionPointer
1096 (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
1097 P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
1098 Ast0.wrap(Ast0.Param(fnptr, None)) }
1101 Tconst { P.clt2mcode Ast.Const $1 }
1102 | Tvolatile { P.clt2mcode Ast.Volatile $1 }
1104 /*****************************************************************************/
1107 includes { $1 } /* shouldn't be allowed to be a single_statement... */
1108 | TMeta { tmeta_to_statement $1}
1111 | option(expr) TPtVirg
1113 | TIf TOPar eexpr TCPar single_statement %prec TIf
1114 { P.ifthen $1 $2 $3 $4 $5 }
1115 | TIf TOPar eexpr TCPar single_statement TElse single_statement
1116 { P.ifthenelse $1 $2 $3 $4 $5 $6 $7 }
1117 | TFor TOPar option(eexpr) TPtVirg option(eexpr) TPtVirg
1118 option(eexpr) TCPar single_statement
1119 { P.forloop $1 $2 $3 $4 $5 $6 $7 $8 $9 }
1120 | TFor TOPar one_decl_var option(eexpr) TPtVirg
1121 option(eexpr) TCPar single_statement
1122 { P.forloop2 $1 $2 $3 $4 $5 $6 $7 $8 }
1123 | TWhile TOPar eexpr TCPar single_statement
1124 { P.whileloop $1 $2 $3 $4 $5 }
1125 | TDo single_statement TWhile TOPar eexpr TCPar TPtVirg
1126 { P.doloop $1 $2 $3 $4 $5 $6 $7 }
1127 | iter_ident TOPar eexpr_list_option TCPar single_statement
1128 { P.iterator $1 $2 $3 $4 $5 }
1129 | TSwitch TOPar eexpr TCPar TOBrace list(decl_var) list(case_line) TCBrace
1130 { P.switch $1 $2 $3 $4 $5 (List.concat $6) $7 $8 }
1131 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
1132 | TReturn TPtVirg { P.ret $1 $2 }
1133 | TBreak TPtVirg { P.break $1 $2 }
1134 | TContinue TPtVirg { P.cont $1 $2 }
1135 | mident TDotDot { P.label $1 $2 }
1136 | TGoto disj_ident TPtVirg { P.goto $1 $2 $3 }
1137 | TOBrace fun_start TCBrace
1141 TEllipsis w=list(whenppdecs)
1142 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." $1, List.concat w)) }
1143 | TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
1144 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." $1, b,
1145 P.clt2mcode "...>" c, List.concat w, false)) }
1146 | TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
1147 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." $1, b,
1148 P.clt2mcode "...+>" c, List.concat w, true)) }
1150 %inline stm_dots_ell:
1151 a=TEllipsis w=list(whenppdecs)
1152 { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." a, List.concat w)) }
1154 %inline stm_dots_nest:
1155 a=TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
1156 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." a, b,
1157 P.clt2mcode "...>" c, List.concat w, false)) }
1158 | a=TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
1159 { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." a, b,
1160 P.clt2mcode "...+>" c, List.concat w, true)) }
1162 whenppdecs: w=whens(when_start,rule_elem_statement,any_strict)
1165 /* a statement that fits into a single rule_elem. should nests be included?
1166 what about statement metavariables? */
1167 rule_elem_statement:
1169 { Ast0.wrap(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),$1)) }
1170 | option(expr) TPtVirg { P.exp_stm $1 $2 }
1171 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
1172 | TReturn TPtVirg { P.ret $1 $2 }
1173 | TBreak TPtVirg { P.break $1 $2 }
1174 | TContinue TPtVirg { P.cont $1 $2 }
1175 | TOPar0 midzero_list(rule_elem_statement,rule_elem_statement) TCPar0
1176 { let (mids,code) = $2 in
1178 (Ast0.Disj(P.clt2mcode "(" $1,
1179 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
1180 mids, P.clt2mcode ")" $3)) }
1182 /* a statement on its own */
1185 | TOPar0 midzero_list(statement,statement) TCPar0
1186 /* degenerate case, elements are single statements and thus don't
1188 { let (mids,code) = $2 in
1190 (Ast0.Disj(P.clt2mcode "(" $1,
1191 List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
1192 mids, P.clt2mcode ")" $3)) }
1194 iso_statement: /* statement or declaration used in statement context */
1200 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),decl))
1201 | _ -> failwith "exactly one decl allowed in statement iso" }
1204 TDefault TDotDot fun_start
1206 (Ast0.Default(P.clt2mcode "default" $1,P.clt2mcode ":" $2,$3)) }
1207 | TCase eexpr TDotDot fun_start
1208 { Ast0.wrap(Ast0.Case(P.clt2mcode "case" $1,$2,P.clt2mcode ":" $3,$4)) }
1209 /* | lp=TOPar0 t=midzero_list(case_line,case_line) rp=TCPar0
1210 { let (mids,code) = ([],[t]) in
1212 (Ast0.DisjCase(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) } */
1214 /* In the following, an identifier as a type is not fully supported. Indeed,
1215 the language is ambiguous: what is foo * bar; */
1216 /* The AST DisjDecl cannot be generated because it would be ambiguous with
1217 a disjunction on a statement with a declaration in each branch */
1220 { [Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv))] }
1221 | TMetaDecl { [P.meta_decl $1] }
1222 | s=ioption(storage) t=ctype d=comma_list(d_ident) pv=TPtVirg
1224 (function (id,fn) ->
1225 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)))
1227 | f=funproto { [f] }
1228 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
1230 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
1231 /* type is a typedef name */
1232 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident_or_symbol
1233 d=comma_list(d_ident) pv=TPtVirg
1235 (function (id,fn) ->
1237 P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1238 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)))
1240 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident_or_symbol
1241 d=d_ident q=TEq e=initialize pv=TPtVirg
1242 { let (id,fn) = d in
1243 !Data.add_type_name (P.id2name i);
1244 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1245 [Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
1246 P.clt2mcode ";" pv))] }
1247 /* function pointer type */
1248 | s=ioption(storage)
1249 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1250 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1252 { let (id,fn) = d in
1255 (Ast0.FunctionPointer
1256 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1257 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1258 [Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv))] }
1259 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
1260 { [Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
1261 P.clt2mcode ")" $4,P.clt2mcode ";" $5))] }
1262 | decl_ident TOPar eexpr_list_option TCPar q=TEq e=initialize TPtVirg
1265 ($1,P.clt2mcode "(" $2,$3,
1266 P.clt2mcode ")" $4,P.clt2mcode "=" q,e,
1267 P.clt2mcode ";" $7))] }
1268 | s=ioption(storage)
1269 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1270 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1271 q=TEq e=initialize pv=TPtVirg
1272 { let (id,fn) = d in
1275 (Ast0.FunctionPointer
1276 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1277 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1278 [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
1279 | s=Ttypedef t=typedef_ctype id=comma_list(typedef_ident) pv=TPtVirg
1280 { let s = P.clt2mcode "typedef" s in
1283 Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv)))
1288 { Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv)) }
1289 | TMetaDecl { P.meta_decl $1 }
1290 | s=ioption(storage) t=ctype d=d_ident pv=TPtVirg
1291 { let (id,fn) = d in
1292 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1294 | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
1295 { let (id,fn) = d in
1296 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv)) }
1297 /* type is a typedef name */
1298 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident_or_symbol
1299 d=d_ident pv=TPtVirg
1300 { let (id,fn) = d in
1301 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1302 Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)) }
1303 | s=ioption(storage) cv=ioption(const_vol) i=pure_ident_or_symbol
1304 d=d_ident q=TEq e=initialize pv=TPtVirg
1305 { let (id,fn) = d in
1306 !Data.add_type_name (P.id2name i);
1307 let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
1308 Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
1309 P.clt2mcode ";" pv)) }
1310 /* function pointer type */
1311 | s=ioption(storage)
1312 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1313 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1315 { let (id,fn) = d in
1318 (Ast0.FunctionPointer
1319 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1320 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1321 Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
1322 | decl_ident TOPar eexpr_list_option TCPar TPtVirg
1323 { Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
1324 P.clt2mcode ")" $4,P.clt2mcode ";" $5)) }
1325 | decl_ident TOPar eexpr_list_option TCPar q=TEq e=initialize TPtVirg
1328 ($1,P.clt2mcode "(" $2,$3,
1329 P.clt2mcode ")" $4,P.clt2mcode "=" q,e,
1330 P.clt2mcode ";" $7)) }
1331 | s=ioption(storage)
1332 t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
1333 lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
1334 q=TEq e=initialize pv=TPtVirg
1335 { let (id,fn) = d in
1338 (Ast0.FunctionPointer
1339 (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
1340 P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
1341 Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))}
1345 disj_ident list(array_dec)
1346 { ($1, function t -> P.arrayify t $2) }
1348 array_dec: l=TOCro i=option(eexpr) r=TCCro { (l,i,r) }
1352 { Ast0.wrap(Ast0.InitExpr($1)) }
1353 | TOBrace initialize_list TCBrace
1354 { if P.struct_initializer $2
1356 let il = P.drop_dot_commas $2 in
1357 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
1359 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) }
1361 {let (nm,pure,clt) = $1 in
1362 Ast0.wrap(Ast0.MetaInit(P.clt2mcode nm clt,pure)) }
1365 /*arithexpr and not eexpr because can have ambiguity with comma*/
1366 /*dots and nests probably not allowed at top level, haven't looked into why*/
1367 arith_expr(eexpr,invalid) { Ast0.wrap(Ast0.InitExpr($1)) }
1368 | nest_expressions_only { Ast0.wrap(Ast0.InitExpr($1)) }
1369 | TOBrace initialize_list TCBrace
1370 { if P.struct_initializer $2
1372 let il = P.drop_dot_commas $2 in
1373 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
1375 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) }
1376 /* gccext:, labeled elements */
1377 | list(designator) TEq initialize2 /*can we have another of these on the rhs?*/
1378 { Ast0.wrap(Ast0.InitGccExt($1,P.clt2mcode "=" $2,$3)) }
1379 | mident TDotDot initialize2
1380 { Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */
1382 {let (nm,pure,clt) = $1 in
1383 Ast0.wrap(Ast0.MetaInit(P.clt2mcode nm clt,pure)) }
1385 {let (nm,lenname,pure,clt) = $1 in
1386 let nm = P.clt2mcode nm clt in
1389 Ast.AnyLen -> Ast0.AnyListLen
1390 | Ast.MetaLen nm -> Ast0.MetaListLen(P.clt2mcode nm clt)
1391 | Ast.CstLen n -> Ast0.CstListLen n in
1392 Ast0.wrap(Ast0.MetaInitList(nm,lenname,pure)) }
1396 { Ast0.DesignatorField (P.clt2mcode "." $1,$2) }
1398 { Ast0.DesignatorIndex (P.clt2mcode "[" $1,$2,P.clt2mcode "]" $3) }
1399 | TOCro eexpr TEllipsis eexpr TCCro
1400 { Ast0.DesignatorRange (P.clt2mcode "[" $1,$2,P.clt2mcode "..." $3,
1401 $4,P.clt2mcode "]" $5) }
1404 empty_list_start(initialize2,edots_when(TEllipsis,initialize))
1405 { Ast0.wrap(Ast0.DOTS($1 P.mkidots (fun c -> Ast0.IComma c))) }
1407 /* a statement that is part of a list */
1410 { let (nm,pure,clt) = $1 in
1411 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1416 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1418 | statement { [$1] }
1419 /* this doesn't allow expressions at top level, because the parser doesn't
1420 know whether there is one. If there is one, this is not sequencible.
1421 If there is not one, then it is. It seems complicated to get around
1422 this at the parser level. We would have to have a check afterwards to
1423 allow this. One case where this would be useful is for a when. Now
1424 we allow a sequence of whens, so one can be on only statements and
1425 one can be on only expressions. */
1426 | TOPar0 t=midzero_list(fun_start,fun_start) TCPar0
1427 { let (mids,code) = t in
1430 match Ast0.unwrap x with Ast0.DOTS([]) -> true | _ -> false)
1434 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, code, mids,
1435 P.clt2mcode ")" $3))] }
1437 /* a statement that is part of a list */
1438 decl_statement_expr:
1440 { let (nm,pure,clt) = $1 in
1441 [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
1446 (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
1448 | statement { [$1] }
1449 /* this doesn't allow expressions at top level, because the parser doesn't
1450 know whether there is one. If there is one, this is not sequencible.
1451 If there is not one, then it is. It seems complicated to get around
1452 this at the parser level. We would have to have a check afterwards to
1453 allow this. One case where this would be useful is for a when. Now
1454 we allow a sequence of whens, so one can be on only statements and
1455 one can be on only expressions. */
1456 | TOPar0 t=midzero_list(fun_after_stm,fun_after_dots_or) TCPar0
1457 { let (mids,code) = t in
1458 if List.for_all (function [] -> true | _ -> false) code
1462 List.map (function x -> Ast0.wrap(Ast0.DOTS x)) code in
1463 [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, dot_code, mids,
1464 P.clt2mcode ")" $3))] }
1466 /*****************************************************************************/
1468 /* expr cannot contain <... ...> at the top level. This can only
1469 be allowed as an expression when the expression is delimited on the left
1470 by an expression-specific marker. In that case, the rule eexpr is used, which
1471 allows <... ...> anywhere. Hopefully, this will not be too much of a problem
1473 dot_expressions is the most permissive. all three kinds of expressions use
1474 this once an expression_specific token has been seen
1475 The arg versions don't allow sequences, to avoid conflicting with commas in
1478 expr: basic_expr(expr,invalid) { $1 }
1479 /* allows ... and nests */
1480 eexpr: pre_basic_expr(eexpr,dot_expressions) { $1 }
1481 eargexpr: basic_expr(eexpr,dot_expressions) { $1 } /* no sequences */
1482 /* allows nests but not .... */
1483 dexpr: pre_basic_expr(eexpr,nest_expressions) { $1 }
1484 dargexpr: basic_expr(eexpr,nest_expressions) { $1 } /* no sequences */
1487 eexpr { Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))) }
1490 TInvalid { raise (Semantic_cocci.Semantic "not matchable") }
1493 TEllipsis { Ast0.wrap(Ast0.Edots(P.clt2mcode "..." $1,None)) }
1494 | nest_expressions { $1 }
1496 /* not clear what whencode would mean, so just drop it */
1498 TOEllipsis e=expr_dots(TEllipsis) c=TCEllipsis
1499 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<..." $1,
1500 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1501 P.clt2mcode "...>" c, None, false)) }
1502 | TPOEllipsis e=expr_dots(TEllipsis) c=TPCEllipsis
1503 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<+..." $1,
1504 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1505 P.clt2mcode "...+>" c, None, true)) }
1506 | TMeta { tmeta_to_exp $1 }
1508 nest_expressions_only:
1509 TOEllipsis e=expr_dots(TEllipsis) c=TCEllipsis
1510 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<..." $1,
1511 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1512 P.clt2mcode "...>" c, None, false)) }
1513 | TPOEllipsis e=expr_dots(TEllipsis) c=TPCEllipsis
1514 { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<+..." $1,
1515 Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
1516 P.clt2mcode "...+>" c, None, true)) }
1518 //whenexp: TWhen TNotEq w=eexpr TLineEnd { w }
1520 pre_basic_expr(recurser,primary_extra):
1521 basic_expr(recurser,primary_extra) { $1 }
1522 | pre_basic_expr(recurser,primary_extra) TComma
1523 basic_expr(recurser,primary_extra)
1524 { Ast0.wrap(Ast0.Sequence($1,P.clt2mcode "," $2,$3)) }
1526 basic_expr(recurser,primary_extra):
1527 assign_expr(recurser,primary_extra) { $1 }
1530 cond_expr(r,pe) { $1 }
1531 | unary_expr(r,pe) TAssign assign_expr_bis
1532 { let (op,clt) = $2 in
1533 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1534 Ast0.set_arg_exp $3,false)) }
1535 | unary_expr(r,pe) TEq assign_expr_bis
1538 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1541 cond_expr(eexpr,dot_expressions) { $1 }
1542 | unary_expr(eexpr,dot_expressions) TAssign assign_expr_bis
1543 { let (op,clt) = $2 in
1544 Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
1545 Ast0.set_arg_exp $3,false)) }
1546 | unary_expr(eexpr,dot_expressions) TEq assign_expr_bis
1549 ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
1552 arith_expr(r,pe) { $1 }
1553 | l=arith_expr(r,pe) w=TWhy t=option(eexpr)
1554 dd=TDotDot r=eargexpr/*see parser_c*/
1555 { Ast0.wrap(Ast0.CondExpr (l, P.clt2mcode "?" w, t,
1556 P.clt2mcode ":" dd, r)) }
1559 cast_expr(r,pe) { $1 }
1560 | arith_expr(r,pe) TMul arith_expr_bis
1561 { P.arith_op Ast.Mul $1 $2 $3 }
1562 | arith_expr(r,pe) TDmOp arith_expr_bis
1563 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1564 | arith_expr(r,pe) TPlus arith_expr_bis
1565 { P.arith_op Ast.Plus $1 $2 $3 }
1566 | arith_expr(r,pe) TMinus arith_expr_bis
1567 { P.arith_op Ast.Minus $1 $2 $3 }
1568 | arith_expr(r,pe) TShLOp arith_expr_bis
1569 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1570 | arith_expr(r,pe) TShROp arith_expr_bis
1571 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1572 | arith_expr(r,pe) TLogOp arith_expr_bis
1573 { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
1574 | arith_expr(r,pe) TEqEq arith_expr_bis
1575 { P.logic_op Ast.Eq $1 $2 $3 }
1576 | arith_expr(r,pe) TNotEq arith_expr_bis
1577 { P.logic_op Ast.NotEq $1 $2 $3 }
1578 | arith_expr(r,pe) TAnd arith_expr_bis
1579 { P.arith_op Ast.And $1 $2 $3 }
1580 | arith_expr(r,pe) TOr arith_expr_bis
1581 { P.arith_op Ast.Or $1 $2 $3 }
1582 | arith_expr(r,pe) TXor arith_expr_bis
1583 { P.arith_op Ast.Xor $1 $2 $3 }
1584 | arith_expr(r,pe) TAndLog arith_expr_bis
1585 { P.logic_op Ast.AndLog $1 $2 $3 }
1586 | arith_expr(r,pe) TOrLog arith_expr_bis
1587 { P.logic_op Ast.OrLog $1 $2 $3 }
1589 // allows dots now that an expression-specific token has been seen
1590 // need an extra rule because of recursion restrictions
1592 cast_expr(eexpr,dot_expressions) { $1 }
1593 | arith_expr_bis TMul arith_expr_bis
1594 { P.arith_op Ast.Mul $1 $2 $3 }
1595 | arith_expr_bis TDmOp arith_expr_bis
1596 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1597 | arith_expr_bis TPlus arith_expr_bis
1598 { P.arith_op Ast.Plus $1 $2 $3 }
1599 | arith_expr_bis TMinus arith_expr_bis
1600 { P.arith_op Ast.Minus $1 $2 $3 }
1601 | arith_expr_bis TShLOp arith_expr_bis
1602 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1603 | arith_expr_bis TShROp arith_expr_bis
1604 { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
1605 | arith_expr_bis TLogOp arith_expr_bis
1606 { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
1607 | arith_expr_bis TEqEq arith_expr_bis
1608 { P.logic_op Ast.Eq $1 $2 $3 }
1609 | arith_expr_bis TNotEq arith_expr_bis
1610 { P.logic_op Ast.NotEq $1 $2 $3 }
1611 | arith_expr_bis TAnd arith_expr_bis
1612 { P.arith_op Ast.And $1 $2 $3 }
1613 | arith_expr_bis TOr arith_expr_bis
1614 { P.arith_op Ast.Or $1 $2 $3 }
1615 | arith_expr_bis TXor arith_expr_bis
1616 { P.arith_op Ast.Xor $1 $2 $3 }
1617 | arith_expr_bis TAndLog arith_expr_bis
1618 { P.logic_op Ast.AndLog $1 $2 $3 }
1619 // no OrLog because it is left associative and this is for
1620 // a right argument, not sure why not the same problem for AndLog
1623 unary_expr(r,pe) { $1 }
1624 | lp=TOPar t=ctype rp=TCPar e=cast_expr(r,pe)
1625 { Ast0.wrap(Ast0.Cast (P.clt2mcode "(" lp, t,
1626 P.clt2mcode ")" rp, e)) }
1629 postfix_expr(r,pe) { $1 }
1630 | TInc unary_expr_bis
1631 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
1632 | TDec unary_expr_bis
1633 { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
1634 | unary_op cast_expr(r,pe)
1635 { let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
1636 | TBang unary_expr_bis
1637 { let mcode = P.clt2mcode Ast.Not $1 in
1638 Ast0.wrap(Ast0.Unary($2, mcode)) }
1639 | TSizeof unary_expr_bis
1640 { Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
1641 | s=TSizeof lp=TOPar t=ctype rp=TCPar
1642 { Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
1643 P.clt2mcode "(" lp,t,
1644 P.clt2mcode ")" rp)) }
1646 // version that allows dots
1648 postfix_expr(eexpr,dot_expressions) { $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(eexpr,dot_expressions)
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 unary_op: TAnd { P.clt2mcode Ast.GetRef $1 }
1666 | TMul { P.clt2mcode Ast.DeRef $1 }
1667 | TPlus { P.clt2mcode Ast.UnPlus $1 }
1668 | TMinus { P.clt2mcode Ast.UnMinus $1 }
1669 | TTilde { P.clt2mcode Ast.Tilde $1 }
1672 primary_expr(r,pe) { $1 }
1673 | postfix_expr(r,pe) TOCro eexpr TCCro
1674 { Ast0.wrap(Ast0.ArrayAccess ($1,P.clt2mcode "[" $2,$3,
1675 P.clt2mcode "]" $4)) }
1676 | postfix_expr(r,pe) TDot disj_ident
1677 { Ast0.wrap(Ast0.RecordAccess($1, P.clt2mcode "." $2, $3)) }
1678 | postfix_expr(r,pe) TPtrOp disj_ident
1679 { Ast0.wrap(Ast0.RecordPtAccess($1, P.clt2mcode "->" $2,
1681 | postfix_expr(r,pe) TInc
1682 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Inc $2)) }
1683 | postfix_expr(r,pe) TDec
1684 { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Dec $2)) }
1685 | postfix_expr(r,pe) TOPar eexpr_list_option TCPar
1686 { Ast0.wrap(Ast0.FunCall($1,P.clt2mcode "(" $2,
1688 P.clt2mcode ")" $4)) }
1689 /*(* gccext: also called compound literals *)
1690 empty case causes conflicts */
1691 | TOPar ctype TCPar TOBrace initialize_list TCBrace
1693 if P.struct_initializer $5
1695 let il = P.drop_dot_commas $5 in
1697 (Ast0.InitList(P.clt2mcode "{" $4,il,P.clt2mcode "}" $6,false))
1700 (Ast0.InitList(P.clt2mcode "{" $4,$5,P.clt2mcode "}" $6,true)) in
1702 (Ast0.Constructor(P.clt2mcode "(" $1, $2, P.clt2mcode ")" $3, init)) }
1704 primary_expr(recurser,primary_extra):
1705 func_ident { Ast0.wrap(Ast0.Ident($1)) }
1707 { let op = P.clt2mcode Ast.GetRefLabel $1 in
1708 Ast0.wrap(Ast0.Unary(Ast0.wrap(Ast0.Ident($2)), op)) }
1710 { let (x,clt) = $1 in
1711 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
1713 { let (x,clt) = $1 in
1714 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Float x) clt)) }
1716 { let (x,clt) = $1 in
1717 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.String x) clt)) }
1719 { let (x,clt) = $1 in
1720 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Char x) clt)) }
1722 { let (nm,constraints,pure,ty,clt) = $1 in
1724 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
1726 { let (nm,constraints,pure,clt) = $1 in
1727 Ast0.wrap(Ast0.MetaErr(P.clt2mcode nm clt,constraints,pure)) }
1729 { let (nm,constraints,pure,ty,clt) = $1 in
1731 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
1733 { let (nm,constraints,pure,ty,clt) = $1 in
1735 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
1737 { let (nm,constraints,pure,ty,clt) = $1 in
1739 (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.LocalID,pure)) }
1741 { Ast0.wrap(Ast0.Paren(P.clt2mcode "(" $1,$2,
1742 P.clt2mcode ")" $3)) }
1743 | TOPar0 midzero_list(recurser,eexpr) TCPar0
1744 { let (mids,code) = $2 in
1745 Ast0.wrap(Ast0.DisjExpr(P.clt2mcode "(" $1,
1747 P.clt2mcode ")" $3)) }
1748 | primary_extra { $1 }
1751 r=no_dot_start_end(dexpr,edots_when(dotter,eexpr)) { r }
1754 no_dot_start_end(grammar,dotter):
1755 g=grammar dg=list(pair(dotter,grammar))
1756 { function dot_builder ->
1757 g :: (List.concat(List.map (function (d,g) -> [dot_builder d;g]) dg)) }
1759 /*****************************************************************************/
1764 pure_ident_or_symbol:
1769 | TIdentifier { "identifier" }
1770 | TExpression { "expression" }
1771 | TStatement { "statement" }
1772 | TFunction { "function" }
1773 | TLocal { "local" }
1775 | TParameter { "parameter" }
1776 | TIdExpression { "idexpression" }
1777 | TInitialiser { "initialiser" }
1779 | TFresh { "fresh" }
1780 | TConstant { "constant" }
1781 | TError { "error" }
1782 | TWords { "words" }
1784 | TContext { "context" }
1785 | TGenerated { "generated" }
1786 | TTypedef { "typedef" }
1787 | TDeclarer { "declarer" }
1788 | TIterator { "iterator" }
1790 | TPosition { "position" }
1791 | TSymbol { "symbol" }
1794 TRuleName TDot pure_ident { (Some $1,P.id2name $3) }
1795 | TRuleName TDot pure_ident_kwd { (Some $1,$3) }
1797 pure_ident_or_meta_ident:
1798 pure_ident { (None,P.id2name $1) }
1799 | pure_ident_kwd { (None,$1) }
1803 TSymId { Ast0.wrap(Ast0.Id(P.sym2mcode $1)) }
1805 pure_ident_or_meta_ident_with_seed:
1806 pure_ident_or_meta_ident { ($1,Ast.NoVal) }
1807 | pure_ident_or_meta_ident TEq
1808 separated_nonempty_list(TCppConcatOp,seed_elem)
1810 [Ast.SeedString s] -> ($1,Ast.StringSeed s)
1811 | _ -> ($1,Ast.ListSeed $3) }
1814 TString { let (x,_) = $1 in Ast.SeedString x }
1815 | TMetaId { let (x,_,_,_,_) = $1 in Ast.SeedId x }
1816 | TMeta {failwith "tmeta"}
1817 | TVirtual TDot pure_ident
1818 { let nm = ("virtual",P.id2name $3) in
1819 Iteration.parsed_virtual_identifiers :=
1820 Common.union_set [snd nm]
1821 !Iteration.parsed_virtual_identifiers;
1822 try Ast.SeedString (List.assoc (snd nm) !Flag.defined_virtual_env)
1823 with Not_found -> Ast.SeedId nm }
1824 | TRuleName TDot pure_ident
1825 { let nm = ($1,P.id2name $3) in
1826 P.check_meta(Ast.MetaIdDecl(Ast.NONE,nm));
1829 pure_ident_or_meta_ident_with_x_eq(x_eq):
1830 i=pure_ident_or_meta_ident l=loption(x_eq)
1835 pure_ident_or_meta_ident_with_econstraint(x_eq):
1836 i=pure_ident_or_meta_ident optc=option(x_eq)
1839 None -> (i, Ast0.NoConstraint)
1843 pure_ident_or_meta_ident_with_idconstraint_virt(constraint_type):
1844 i=pure_ident_or_meta_ident c=option(constraint_type)
1848 None -> (i, Ast.IdNoConstraint)
1849 | Some constraint_ -> (i,constraint_))
1851 | TVirtual TDot pure_ident
1853 let nm = P.id2name $3 in
1854 Iteration.parsed_virtual_identifiers :=
1855 Common.union_set [nm]
1856 !Iteration.parsed_virtual_identifiers;
1860 pure_ident_or_meta_ident_with_idconstraint(constraint_type):
1861 i=pure_ident_or_meta_ident c=option(constraint_type)
1864 None -> (i, Ast.IdNoConstraint)
1865 | Some constraint_ -> (i,constraint_)
1869 re=regexp_eqid {Ast.IdRegExpConstraint re}
1875 then failwith "constraints not allowed in iso file");
1876 (if !Data.in_generating
1877 then failwith "constraints not allowed in a generated rule file");
1878 let (s,_) = re in Ast.IdRegExp (s,Regexp.regexp s)
1880 | TTildeExclEq re=TString
1882 then failwith "constraints not allowed in iso file");
1883 (if !Data.in_generating
1884 then failwith "constraints not allowed in a generated rule file");
1885 let (s,_) = re in Ast.IdNotRegExp (s,Regexp.regexp s)
1889 TNotEq i=pure_ident_or_meta_ident
1891 then failwith "constraints not allowed in iso file");
1892 (if !Data.in_generating
1893 (* pb: constraints not stored with metavars; too lazy to search for
1894 them in the pattern *)
1895 then failwith "constraints not allowed in a generated rule file");
1899 P.check_inherited_constraint i
1900 (function mv -> Ast.MetaIdDecl(Ast.NONE,mv)) in
1901 Ast.IdNegIdSet([],[i])
1902 | (None,i) -> Ast.IdNegIdSet([i],[])) }
1903 | TNotEq TOBrace l=comma_list(pure_ident_or_meta_ident) TCBrace
1905 then failwith "constraints not allowed in iso file");
1906 (if !Data.in_generating
1907 then failwith "constraints not allowed in a generated rule file");
1910 (function (str,meta) ->
1912 (Some rn,id) as i ->
1914 P.check_inherited_constraint i
1915 (function mv -> Ast.MetaIdDecl(Ast.NONE,mv)) in
1917 | (None,i) -> (i::str,meta))
1919 Ast.IdNegIdSet(str,meta)
1922 re_or_not_eqe_or_sub:
1923 re=regexp_eqid {Ast0.NotIdCstrt re}
1924 | ne=not_eqe {Ast0.NotExpCstrt ne}
1925 | s=sub {Ast0.SubExpCstrt s}
1928 ceq=not_ceq {Ast0.NotExpCstrt ceq}
1929 | s=sub {Ast0.SubExpCstrt s}
1934 then failwith "constraints not allowed in iso file");
1935 (if !Data.in_generating
1936 then failwith "constraints not allowed in a generated rule file");
1937 [Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))]
1939 | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
1941 then failwith "constraints not allowed in iso file");
1942 (if !Data.in_generating
1943 then failwith "constraints not allowed in a generated rule file");
1946 Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))))
1951 TNotEq i=ident_or_const
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");
1957 | TNotEq TOBrace l=comma_list(ident_or_const) TCBrace
1959 then failwith "constraints not allowed in iso file");
1960 (if !Data.in_generating
1961 then failwith "constraints not allowed in a generated rule file");
1965 (* has to be inherited because not clear how to check subterm constraints
1966 in the functorized CTL engine, so need the variable to be bound
1967 already when bind the subterm constrained metavariable *)
1970 then failwith "constraints not allowed in iso file");
1971 (if !Data.in_generating
1972 then failwith "constraints not allowed in a generated rule file");
1974 P.check_inherited_constraint i
1975 (function mv -> Ast.MetaExpDecl(Ast.NONE,mv,None)) in
1977 | TSub TOBrace l=comma_list(meta_ident) TCBrace
1979 then failwith "constraints not allowed in iso file");
1980 (if !Data.in_generating
1981 then failwith "constraints not allowed in a generated rule file");
1984 P.check_inherited_constraint i
1985 (function mv -> Ast.MetaExpDecl(Ast.NONE,mv,None)))
1989 i=pure_ident { Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))) }
1990 | wrapped_sym_ident { Ast0.wrap(Ast0.Ident($1)) }
1992 { let (x,clt) = $1 in
1993 Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
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");
2002 P.check_inherited_constraint i
2003 (function mv -> Ast.MetaPosDecl(Ast.NONE,mv)) in
2005 | TNotEq TOBrace l=comma_list(meta_ident) TCBrace
2007 then failwith "constraints not allowed in iso file");
2008 (if !Data.in_generating
2009 then failwith "constraints not allowed in a generated rule file");
2012 P.check_inherited_constraint i
2013 (function mv -> Ast.MetaPosDecl(Ast.NONE,mv)))
2019 { let (nm,constraints,pure,clt) = $1 in
2020 Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
2022 { let (nm,constraints,pure,clt) = $1 in
2024 (Ast0.MetaLocalFunc(P.clt2mcode nm clt,constraints,pure)) }
2026 fn_ident: disj_ident { $1 }
2028 { let (nm,constraints,pure,clt) = $1 in
2029 Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
2031 { let (nm,constraints,pure,clt) = $1 in
2033 (Ast0.MetaLocalFunc(P.clt2mcode nm clt,constraints,pure)) }
2036 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
2037 | wrapped_sym_ident { $1 }
2039 { let (nm,constraints,seed,pure,clt) = $1 in
2040 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,seed,pure)) }
2043 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
2044 | wrapped_sym_ident { $1 }
2045 | TMeta { tmeta_to_ident $1 }
2047 { let (nm,constraints,seed,pure,clt) = $1 in
2048 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,seed,pure)) }
2052 | lp=TOPar0 t=midzero_list(disj_ident,disj_ident) rp=TCPar0
2053 { let (mids,code) = t in
2055 (Ast0.DisjId(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
2057 type_ident: disj_ident { $1 }
2059 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
2063 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
2065 { let (nm,constraints,pure,clt) = $1 in
2066 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,Ast.NoVal,pure)) }
2070 { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
2072 { let (nm,constraints,pure,clt) = $1 in
2073 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,Ast.NoVal,pure)) }
2076 pure_ident_or_symbol
2077 { Ast0.wrap(Ast0.TypeName(P.id2mcode $1)) }
2078 | TMeta { tmeta_to_type $1 }
2080 { let (nm,pure,clt) = $1 in
2081 Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
2083 /*****************************************************************************/
2086 empty_list_start(one_dec(decl),TEllipsis)
2090 (fun _ d -> Ast0.wrap(Ast0.Pdots(P.clt2mcode "..." d)))
2091 (fun c -> Ast0.PComma c))) }
2096 { let (nm,lenname,pure,clt) = $1 in
2097 let nm = P.clt2mcode nm clt in
2100 Ast.AnyLen -> Ast0.AnyListLen
2101 | Ast.MetaLen nm -> Ast0.MetaListLen(P.clt2mcode nm clt)
2102 | Ast.CstLen n -> Ast0.CstListLen n in
2103 Ast0.wrap(Ast0.MetaParamList(nm,lenname,pure)) }
2105 /* ---------------------------------------------------------------------- */
2106 /* comma list parser, used for fn params, fn args, enums, initlists,
2109 /* enums: enum_decl, edots_when(TEllipsis,enum_decl_one)
2110 fun s d -> P.mkedots "..." d
2111 fun c -> Ast0.EComma c
2114 empty_list_start(elem,dotter):
2115 /* empty */ { fun build_dots build_comma -> [] }
2116 | nonempty_list_start(elem,dotter) { $1 }
2118 nonempty_list_start(elem,dotter): /* dots allowed */
2119 elem { fun build_dots build_comma -> [$1] }
2121 { fun build_dots build_comma ->
2122 $1::[Ast0.wrap(build_comma(P.clt2mcode "," $2))] }
2123 | elem TComma nonempty_list_start(elem,dotter)
2124 { fun build_dots build_comma ->
2125 $1::(Ast0.wrap(build_comma(P.clt2mcode "," $2)))::
2126 ($3 build_dots build_comma) }
2127 | TNothing nonempty_list_start(elem,dotter) { $2 }
2128 | d=dotter { fun build_dots build_comma -> [(build_dots "..." d)] }
2130 { fun build_dots build_comma ->
2131 [(build_dots "..." d);Ast0.wrap(build_comma(P.clt2mcode "," $2))] }
2132 | d=dotter TComma r=continue_list(elem,dotter)
2133 { fun build_dots build_comma ->
2134 (build_dots "..." d)::
2135 (Ast0.wrap(build_comma(P.clt2mcode "," $2)))::
2136 (r build_dots build_comma) }
2138 continue_list(elem,dotter): /* dots not allowed */
2139 elem { fun build_dots build_comma -> [$1] }
2141 { fun build_dots build_comma ->
2142 $1::[Ast0.wrap(build_comma(P.clt2mcode "," $2))] }
2143 | elem TComma nonempty_list_start(elem,dotter)
2144 { fun build_dots build_comma ->
2145 $1::(Ast0.wrap(build_comma(P.clt2mcode "," $2)))::
2146 ($3 build_dots build_comma) }
2147 | TNothing nonempty_list_start(elem,dotter) { $2 }
2149 /* ---------------------------------------------------------------------- */
2151 /* error words make it complicated to be able to use error as a metavariable
2152 name or a type in a metavariable list; for that we would like to allow TError
2153 as an ident, but that makes conflicts with this rule. To add back error words,
2154 need to find some appropriate delimiter for it, but it has not been used much
2157 TError TWords TEq TOCro cl=comma_list(dexpr) TCCro
2158 { [Ast0.wrap(Ast0.ERRORWORDS(cl))] }
2161 /* ---------------------------------------------------------------------- */
2162 /* sequences of statements and expressions */
2164 /* There are number of cases that must be considered:
2167 Dots and nests allowed at the beginning or end
2168 Expressions allowed at the beginning or end
2169 One function allowed, by itself
2171 Dots and nests allowed at the beginning or end
2172 Expressions not allowed at the beginning or end
2173 Functions not allowed
2174 3. The body of a nest:
2175 Dots and nests not allowed at the beginning or end
2176 Expressions allowed at the beginning or end
2177 Functions not allowed
2179 Dots and nests not allowed at the beginning but allowed at the end
2180 Expressions allowed at the beginning or end
2181 Functions not allowed
2183 These are implemented by the rules minus_toplevel_sequence,
2184 plus_toplevel_sequence, function_body_sequence, nest_body_sequence, and
2187 /* ------------------------------------------------------------------------ */
2188 /* Minus top level */
2190 /* doesn't allow only ... */
2192 fundecl { [Ast0.wrap(Ast0.OTHER($1))] }
2193 | ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
2194 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
2195 | toplevel_seq_startne(toplevel_after_dots_init)
2196 { List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1 }
2198 toplevel_seq_startne(after_dots_init):
2199 a=stm_dots_ell b=after_dots_init { a::b }
2200 | a=stm_dots_nest b=after_dots_init { a::b }
2201 | a=stm_dots_nest { [a] }
2202 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
2203 | decl_statement_expr toplevel_after_stm { $1@$2 }
2205 toplevel_seq_start(after_dots_init):
2206 stm_dots after_dots_init { $1::$2 }
2207 | expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
2208 | decl_statement_expr toplevel_after_stm { $1@$2 }
2210 toplevel_after_dots_init:
2211 TNothing toplevel_after_exp {$2}
2212 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
2213 | decl_statement_expr toplevel_after_stm {$1@$2}
2217 | stm_dots toplevel_after_dots {$1::$2}
2219 toplevel_after_dots:
2221 | TNothing toplevel_after_exp {$2}
2222 | expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
2223 | decl_statement_expr toplevel_after_stm {$1@$2}
2227 | stm_dots toplevel_after_dots {$1::$2}
2228 | decl_statement toplevel_after_stm {$1@$2}
2231 TOInit initialize_list TCBrace
2232 { if P.struct_initializer $2
2234 let il = P.drop_dot_commas $2 in
2235 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false))
2237 Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) }
2239 /* ------------------------------------------------------------------------ */
2240 /* Plus top level */
2242 /* does allow only ... also allows multiple top-level functions */
2244 ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
2245 | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
2246 | stm_dots plus_after_dots
2247 { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
2248 | expr plus_after_exp
2249 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
2250 | fundecl plus_after_stm { Ast0.wrap(Ast0.OTHER($1))::$2 }
2251 | decl_statement_expr plus_after_stm
2252 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
2256 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
2260 | TNothing plus_after_exp {$2}
2261 | expr plus_after_exp
2262 { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
2263 | fundecl plus_after_stm { Ast0.wrap(Ast0.OTHER($1))::$2 }
2264 | decl_statement_expr plus_after_stm
2265 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
2269 | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
2270 | fundecl plus_after_stm { Ast0.wrap(Ast0.OTHER($1))::$2 }
2271 | decl_statement plus_after_stm
2272 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
2274 /* ------------------------------------------------------------------------ */
2278 fun_after_stm { Ast0.wrap(Ast0.DOTS($1)) }
2282 | stm_dots fun_after_dots {$1::$2}
2283 | decl_statement fun_after_stm {$1@$2}
2287 | TNothing fun_after_exp {$2}
2288 | expr fun_after_exp {Ast0.wrap(Ast0.Exp($1))::$2}
2289 | decl_statement_expr fun_after_stm {$1@$2}
2292 stm_dots fun_after_dots {$1::$2}
2294 /* hack to allow mixing statements and expressions in an or */
2297 | TNothing fun_after_exp_or {$2}
2298 | expr fun_after_exp_or {Ast0.wrap(Ast0.Exp($1))::$2}
2299 | decl_statement_expr fun_after_stm {$1@$2}
2303 | stm_dots fun_after_dots {$1::$2}
2305 /* ------------------------------------------------------------------------ */
2309 nest_after_dots { Ast0.wrap(Ast0.DOTS($1)) }
2312 decl_statement_expr nest_after_stm {$1@$2}
2313 | TNothing nest_after_exp {$2}
2314 | expr nest_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
2318 | stm_dots nest_after_dots {$1::$2}
2319 | decl_statement nest_after_stm {$1@$2}
2323 | stm_dots nest_after_dots {$1::$2}
2325 /* ------------------------------------------------------------------------ */
2329 expr toplevel_after_exp
2330 { Ast0.wrap(Ast0.DOTS((Ast0.wrap(Ast0.Exp($1)))::$2)) }
2331 | decl_statement toplevel_after_stm
2332 { Ast0.wrap(Ast0.DOTS($1@$2)) }
2334 /* ---------------------------------------------------------------------- */
2336 /* arg expr. may contain a type or a explist metavariable */
2338 dargexpr { Ast0.set_arg_exp $1 }
2340 { let (nm,lenname,pure,clt) = $1 in
2341 let nm = P.clt2mcode nm clt in
2344 Ast.AnyLen -> Ast0.AnyListLen
2345 | Ast.MetaLen nm -> Ast0.MetaListLen(P.clt2mcode nm clt)
2346 | Ast.CstLen n -> Ast0.CstListLen n in
2347 Ast0.wrap(Ast0.MetaExprList(nm,lenname,pure)) }
2349 { Ast0.set_arg_exp(Ast0.wrap(Ast0.TypeExp($1))) }
2352 empty_list_start(aexpr,TEllipsis)
2356 (fun _ d -> Ast0.wrap(Ast0.Edots(P.clt2mcode "..." d,None)))
2357 (fun c -> Ast0.EComma c))) }
2359 /****************************************************************************/
2361 // non-empty lists - drop separator
2363 separated_nonempty_list(TComma,elem) { $1 }
2365 midzero_list(elem,aft):
2366 a=elem b=list(mzl(aft))
2367 { let (mids,code) = List.split b in (mids,(a::code)) }
2370 a=TMid0 b=elem { (P.clt2mcode "|" a, b) }
2372 edots_when(dotter,when_grammar):
2373 d=dotter { (d,None) }
2374 | d=dotter TWhen TNotEq w=when_grammar TLineEnd { (d,Some w) }
2376 whens(when_grammar,simple_when_grammar,any_strict):
2377 TWhen TNotEq w=when_grammar TLineEnd { [Ast0.WhenNot w] }
2378 | TWhen TEq w=simple_when_grammar TLineEnd { [Ast0.WhenAlways w] }
2379 | TWhen comma_list(any_strict) TLineEnd
2380 { List.map (function x -> Ast0.WhenModifier(x)) $2 }
2381 | TWhenTrue TNotEq e = eexpr TLineEnd { [Ast0.WhenNotTrue e] }
2382 | TWhenFalse TNotEq e = eexpr TLineEnd { [Ast0.WhenNotFalse e] }
2385 TAny { Ast.WhenAny }
2386 | TStrict { Ast.WhenStrict }
2387 | TForall { Ast.WhenForall }
2388 | TExists { Ast.WhenExists }
2390 /*****************************************************************************
2393 *****************************************************************************/
2396 TIsoExpression e1=eexpr el=list(iso(eexpr)) EOF
2397 { let fn x = Ast0.ExprTag x in P.iso_adjust fn fn e1 el }
2398 | TIsoArgExpression e1=eexpr el=list(iso(eexpr)) EOF
2399 { let fn x = Ast0.ArgExprTag x in P.iso_adjust fn fn e1 el }
2400 | TIsoTestExpression e1=eexpr el=list(iso(eexpr)) EOF
2401 { let fn x = Ast0.TestExprTag x in P.iso_adjust fn fn e1 el }
2402 | TIsoToTestExpression e1=eexpr el=list(iso(eexpr)) EOF
2403 { let ffn x = Ast0.ExprTag x in
2404 let fn x = Ast0.TestExprTag x in
2405 P.iso_adjust ffn fn e1 el }
2406 | TIsoStatement s1=iso_statement sl=list(iso(iso_statement)) EOF
2407 { let fn x = Ast0.StmtTag x in P.iso_adjust fn fn s1 sl }
2408 | TIsoType t1=ctype tl=list(iso(ctype)) EOF
2409 { let fn x = Ast0.TypeCTag x in P.iso_adjust fn fn t1 tl }
2410 | TIsoTopLevel e1=nest_start el=list(iso(nest_start)) EOF
2411 { let fn x = Ast0.DotsStmtTag x in P.iso_adjust fn fn e1 el }
2412 | TIsoDeclaration d1=decl_var dl=list(iso(decl_var)) EOF
2413 { let check_one = function
2417 (Semantic_cocci.Semantic
2418 "only one variable per declaration in an isomorphism rule") in
2419 let d1 = check_one d1 in
2423 Common.Left x -> Common.Left(check_one x)
2424 | Common.Right x -> Common.Right(check_one x))
2426 let fn x = Ast0.DeclTag x in P.iso_adjust fn fn d1 dl }
2429 TIso t=term { Common.Left t }
2430 | TRightIso t=term { Common.Right t }
2432 /*****************************************************************************
2435 *****************************************************************************/
2437 never_used: TPragma { () }
2438 | TPArob TMetaPos { () }
2439 | TScriptData { () }
2442 py=pure_ident TMPtVirg
2443 { ((Some (P.id2name py), None), None) }
2444 | py=pure_ident script_name_decl TMPtVirg
2445 { ((Some (P.id2name py), None), Some $2) }
2446 | TOPar TUnderscore TComma ast=pure_ident TCPar script_name_decl TMPtVirg
2447 { ((None, Some (P.id2name ast)), Some $6) }
2448 | TOPar str=pure_ident TComma TUnderscore TCPar script_name_decl TMPtVirg
2449 { ((Some (P.id2name str), None), Some $6) }
2450 | TOPar str=pure_ident TComma ast=pure_ident TCPar script_name_decl TMPtVirg
2451 { ((Some (P.id2name str), Some (P.id2name ast)), Some $6) }
2454 TShLOp TRuleName TDot cocci=pure_ident
2455 { let nm = P.id2name cocci in
2456 let mv = Parse_aux.lookup $2 nm in
2458 | TShLOp TVirtual TDot cocci=pure_ident
2459 { let nm = P.id2name cocci in
2460 Iteration.parsed_virtual_identifiers :=
2461 Common.union_set [nm]
2462 !Iteration.parsed_virtual_identifiers;
2463 let name = ("virtual", nm) in
2464 let mv = Ast.MetaIdDecl(Ast.NONE,name) in