module Ast0 = Ast0_cocci
module Ast = Ast_cocci
module P = Parse_aux
+
+(* ---------------------------------------------------------------------- *)
+(* support for TMeta *)
+
+let print_meta (r,n) = r^"."^n
+
+let meta_metatable = Hashtbl.create(101)
+
+let coerce_tmeta newty name builder matcher =
+ try
+ let x = Hashtbl.find meta_metatable name in
+ if not (matcher x)
+ then
+ failwith
+ (Printf.sprintf "Metavariable %s is used as %s"
+ (print_meta name) newty)
+ with Not_found ->
+ (if !Flag_parsing_cocci.show_SP
+ then
+ Common.pr2
+ (Printf.sprintf
+ "Metavariable %s is assumed to be %s metavariable"
+ (print_meta name) newty));
+ Hashtbl.add meta_metatable name builder
+
+let tmeta_to_type (name,pure,clt) =
+ (coerce_tmeta "a type" name (TMetaType(name,pure,clt))
+ (function TMetaType(_,_,_) -> true | _ -> false));
+ Ast0.wrap(Ast0.MetaType(P.clt2mcode name clt,pure))
+
+let tmeta_to_field (name,pure,clt) =
+ (coerce_tmeta "a field" name (TMetaField(name,pure,clt))
+ (function TMetaField(_,_,_) -> true | _ -> false));
+ P.meta_field (name,pure,clt)
+
+let tmeta_to_exp (name,pure,clt) =
+ (coerce_tmeta "an expression" name
+ (TMetaExp(name,Ast0.NoConstraint,pure,None,clt))
+ (function TMetaExp(_,_,_,_,_) -> true | _ -> false));
+ Ast0.wrap
+ (Ast0.MetaExpr(P.clt2mcode name clt,Ast0.NoConstraint,None,Ast.ANY,pure))
+
+let tmeta_to_param (name,pure,clt) =
+ (coerce_tmeta "a parameter" name (TMetaParam(name,pure,clt))
+ (function TMetaParam(_,_,_) -> true | _ -> false));
+ Ast0.wrap(Ast0.MetaParam(P.clt2mcode name clt,pure))
+
+let tmeta_to_statement (name,pure,clt) =
+ (coerce_tmeta "a statement" name (TMetaType(name,pure,clt))
+ (function TMetaType(_,_,_) -> true | _ -> false));
+ P.meta_stm (name,pure,clt)
+
+let tmeta_to_seed_id (name,pure,clt) =
+ (coerce_tmeta "an identifier" name
+ (TMetaId(name,Ast.IdNoConstraint,pure,clt))
+ (function TMetaId(_,_,_,_) -> true | _ -> false));
+ Ast.SeedId name
+
+let tmeta_to_ident (name,pure,clt) =
+ (coerce_tmeta "an identifier" name
+ (TMetaId(name,Ast.IdNoConstraint,pure,clt))
+ (function TMetaId(_,_,_,_) -> true | _ -> false));
+ Ast0.wrap(Ast0.MetaId(P.clt2mcode name clt,Ast.IdNoConstraint,pure))
%}
%token EOF
%token TIdentifier TExpression TStatement TFunction TLocal TType TParameter
-%token TIdExpression TInitialiser TDeclaration TField
+%token TIdExpression TInitialiser TDeclaration TField TMetavariable
%token Tlist TFresh TConstant TError TWords TWhy0 TPlus0 TBang0
%token TPure TContext TGenerated
%token TTypedef TDeclarer TIterator TName TPosition TPosAny
%token<string> TRuleName
%token<Data.clt> Tchar Tshort Tint Tdouble Tfloat Tlong
+%token<Data.clt> Tsize_t Tssize_t Tptrdiff_t
%token<Data.clt> Tvoid Tstruct Tunion Tenum
%token<Data.clt> Tunsigned Tsigned
%token <Parse_aux.idinfo> TMetaIterator TMetaDeclarer
%token <Parse_aux.expinfo> TMetaErr
%token <Parse_aux.info> TMetaParam TMetaStm TMetaStmList TMetaType
-%token <Parse_aux.info> TMetaInit TMetaDecl TMetaField
+%token <Parse_aux.info> TMetaInit TMetaDecl TMetaField TMeta
%token <Parse_aux.list_info> TMetaParamList TMetaExpList
+%token <Parse_aux.list_info> TMetaFieldList
%token <Parse_aux.typed_expinfo> TMetaExp TMetaIdExp TMetaLocalIdExp TMetaConst
%token <Parse_aux.pos_info> TMetaPos
%token <string> TPathIsoFile
%token <string * Data.clt> TIncludeL TIncludeNL
-%token <Data.clt * token> TDefine
+%token <Data.clt * token> TDefine TUndef
%token <Data.clt * token * int * int> TDefineParam
%token <string * Data.clt> TMinusFile TPlusFile
| TUsing TPathIsoFile { Data.Iso(Common.Right $2) }
| TVirtual comma_list(pure_ident)
{ let names = List.map P.id2name $2 in
+ Iteration.parsed_virtual_rules :=
+ Common.union_set names !Iteration.parsed_virtual_rules;
(* ensure that the names of virtual and real rules don't overlap *)
List.iter
(function name -> Hashtbl.add Data.all_metadecls name [])
let tok = check_meta(Ast.MetaExpListDecl(arity,name,lenname)) in
!Data.add_explist_meta name lenname pure; tok)
len ids }
+| ar=arity ispure=pure
+ TField Tlist TOCro len=list_len TCCro
+ ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
+ { P.create_len_metadec ar ispure
+ (fun lenname arity name pure check_meta ->
+ let tok = check_meta(Ast.MetaFieldListDecl(arity,name,lenname)) in
+ !Data.add_field_list_meta name lenname pure; tok)
+ len ids }
list_len:
pure_ident_or_meta_ident { Common.Left $1 }
/* metavariable kinds with no constraints, etc */
%inline metakind:
- TParameter
+ TMetavariable
+ { (fun arity name pure check_meta ->
+ let tok = check_meta(Ast.MetaMetaDecl(arity,name)) in
+ !Data.add_meta_meta name pure; tok) }
+| TParameter
{ (fun arity name pure check_meta ->
let tok = check_meta(Ast.MetaParamDecl(arity,name)) in
!Data.add_param_meta name pure; tok) }
{ (fun arity name pure check_meta ->
let tok = check_meta(Ast.MetaFieldDecl(arity,name)) in
!Data.add_field_meta name pure; tok) }
+| TField Tlist
+ { (fun arity name pure check_meta ->
+ let len = Ast.AnyLen in
+ let tok = check_meta(Ast.MetaFieldListDecl(arity,name,len)) in
+ !Data.add_field_list_meta name len pure; tok) }
| TStatement Tlist
{ (fun arity name pure check_meta ->
let tok = check_meta(Ast.MetaStmListDecl(arity,name)) in
let vl = List.assoc name virtual_env in
!Data.add_virt_id_meta_found name vl; []
with Not_found ->
+ Iteration.parsed_virtual_identifiers :=
+ Common.union_set [name]
+ !Iteration.parsed_virtual_identifiers;
let name = ("virtual",name) in
let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
!Data.add_virt_id_meta_not_found name pure; tok in
| Some _ ->
!Data.add_local_idexp_meta ty name constraints pure;
check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
-| TExpression m=nonempty_list(TMul)
- { (fun arity name pure check_meta constraints ->
- let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
- let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
- !Data.add_exp_meta ty name constraints pure; tok) }
-| vl=meta_exp_type TOCro TCCro
+| TExpression ty=expression_type
{ (fun arity name pure check_meta constraints ->
- let ty = Some (List.map (function x -> Type_cocci.Array x) vl) in
+ let ty = Some [ty] in
let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
!Data.add_exp_meta ty name constraints pure; tok) }
| TConstant ty=ioption(meta_exp_type)
let tok = check_meta(Ast.MetaConstDecl(arity,name,ty)) in
!Data.add_const_meta ty name constraints pure; tok) }
+expression_type:
+ m=nonempty_list(TMul) { P.ty_pointerify Type_cocci.Unknown m }
+| Tenum m=list(TMul)
+ { P.ty_pointerify (Type_cocci.EnumName Type_cocci.NoName) m }
+| Tstruct m=list(TMul)
+ { P.ty_pointerify
+ (Type_cocci.StructUnionName (Type_cocci.Struct,Type_cocci.NoName)) m }
+| Tunion m=list(TMul)
+ { P.ty_pointerify
+ (Type_cocci.StructUnionName (Type_cocci.Union,Type_cocci.NoName)) m }
+
%inline metakind_atomic_expe:
TExpression
{ (fun arity name pure check_meta constraints ->
!Data.add_exp_meta ty name constraints pure; tok)
}
-
meta_exp_type:
t=typedef_ctype
{ [Ast0_cocci.ast0_type_to_type t] }
+| t=typedef_ctype TOCro TCCro
+ { [Type_cocci.Array (Ast0_cocci.ast0_type_to_type t)] }
| TOBrace t=comma_list(ctype) TCBrace m=list(TMul)
{ List.map
(function x -> P.ty_pointerify (Ast0_cocci.ast0_type_to_type x) m)
{ Ast0.wrap(Ast0.BaseType(Ast.DoubleType,[P.clt2mcode "double" ty])) }
| ty=Tfloat
{ Ast0.wrap(Ast0.BaseType(Ast.FloatType,[P.clt2mcode "float" ty])) }
+| ty=Tsize_t
+ { Ast0.wrap(Ast0.BaseType(Ast.SizeType,[P.clt2mcode "size_t" ty])) }
+| ty=Tssize_t
+ { Ast0.wrap(Ast0.BaseType(Ast.SSizeType,[P.clt2mcode "ssize_t" ty])) }
+| ty=Tptrdiff_t
+ { Ast0.wrap(Ast0.BaseType(Ast.PtrDiffType,[P.clt2mcode "ptrdiff_t" ty])) }
| s=Tenum i=ident
{ Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, Some i)) }
| s=Tenum i=ioption(ident) l=TOBrace ids=enum_decl_list r=TCBrace
then failwith "enums must be named in the iso file");
Ast0.wrap(Ast0.EnumDef(Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, i)),
P.clt2mcode "{" l, ids, P.clt2mcode "}" r)) }
-| s=struct_or_union i=ident
+| s=struct_or_union i=type_ident // allow typedef name
{ Ast0.wrap(Ast0.StructUnionName(s, Some i)) }
-| s=struct_or_union i=ioption(ident)
+| s=struct_or_union i=ioption(type_ident)
l=TOBrace d=struct_decl_list r=TCBrace
{ (if i = None && !Data.in_iso
then failwith "structures must be named in the iso file");
Ast0.wrap
(Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
+mctype:
+| TMeta { tmeta_to_type $1 }
+| ctype {$1}
+
/* signed, unsigned alone not allowed */
typedef_ctype:
cv=ioption(const_vol) ty=all_basic_types m=list(TMul)
{ P.pointerify (P.make_cv cv ty) m }
-| lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
+| lp=TOPar0 t=midzero_list(mctype,mctype) rp=TCPar0
{ let (mids,code) = t in
Ast0.wrap
(Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
+| TMeta { tmeta_to_type $1 }
/* ---------------------------------------------------------------------- */
struct_decl_one:
| TMetaField { P.meta_field $1 }
+ | TMetaFieldList { P.meta_field_list $1 }
+ | TMeta { tmeta_to_field $1 }
| t=ctype d=d_ident pv=TPtVirg
{ let (id,fn) = d in
Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv)) }
/* very restricted what kinds of expressions can appear in an enum decl */
enum_decl_one:
- | ident { Ast0.wrap(Ast0.Ident($1)) }
- | ident TEq enum_val
+ | disj_ident { Ast0.wrap(Ast0.Ident($1)) }
+ | disj_ident TEq enum_val
{ let id = Ast0.wrap(Ast0.Ident($1)) in
Ast0.wrap
(Ast0.Assignment
| TInt
{ let (x,clt) = $1 in
Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
+ | TMeta { tmeta_to_exp $1 }
| TMetaConst
{ let (nm,constraints,pure,ty,clt) = $1 in
Ast0.wrap
P.clt2mcode
(Ast.NonLocal (Parse_aux.str2inc (P.id2name $1)))
(P.drop_bef clt))) }
+| TUndef TLineEnd
+ { let (clt,ident) = $1 in
+ Ast0.wrap
+ (Ast0.Undef
+ (P.clt2mcode "#undef" clt,
+ (match ident with
+ TMetaId((nm,constraints,pure,clt)) ->
+ Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
+ | TIdent(nm_pure) ->
+ Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ "unexpected name for a #define")))) }
| d=defineop TLineEnd
{ d (Ast0.wrap(Ast0.DOTS([]))) }
| d=defineop t=ctype TLineEnd
/* ---------------------------------------------------------------------- */
-dparam: ident { Ast0.wrap(Ast0.DParam $1) }
+dparam: mident { Ast0.wrap(Ast0.DParam $1) }
define_param_list_option:
empty_list_start(dparam,TEllipsis)
funproto:
s=ioption(storage) t=ctype
- id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
+ id=fn_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
{ Ast0.wrap
(Ast0.UnInit
(s,
fundecl:
f=fninfo
- TFunDecl i=func_ident lp=TOPar d=decl_list(decl) rp=TCPar
+ TFunDecl i=fn_ident lp=TOPar d=decl_list(decl) rp=TCPar
lb=TOBrace b=fun_start rb=TCBrace
{ P.verify_parameter_declarations (Ast0.undots d);
Ast0.wrap(Ast0.FunDecl((Ast0.default_info(),Ast0.context_befaft()),
| s=Tregister { P.clt2mcode Ast.Register s }
| s=Textern { P.clt2mcode Ast.Extern s }
-decl: t=ctype i=ident
- { Ast0.wrap(Ast0.Param(t, Some i)) }
+decl: t=ctype i=disj_ident a=list(array_dec)
+ { let t = P.arrayify t a in Ast0.wrap(Ast0.Param(t, Some i)) }
| t=ctype { (*verify in FunDecl*) Ast0.wrap(Ast0.Param(t, None)) }
- | t=ctype lp=TOPar s=TMul i=ident rp=TCPar
+ | t=ctype lp=TOPar s=TMul i=disj_ident rp=TCPar
lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
{ let fnptr =
Ast0.wrap
| TMetaParam
{ let (nm,pure,clt) = $1 in
Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) }
+ | TMeta { tmeta_to_param $1 }
name_opt_decl:
decl { $1 }
statement:
includes { $1 } /* shouldn't be allowed to be a single_statement... */
+| TMeta { tmeta_to_statement $1}
| TMetaStm
{ P.meta_stm $1 }
| expr TPtVirg
| TReturn TPtVirg { P.ret $1 $2 }
| TBreak TPtVirg { P.break $1 $2 }
| TContinue TPtVirg { P.cont $1 $2 }
-| ident TDotDot { P.label $1 $2 }
-| TGoto ident TPtVirg { P.goto $1 $2 $3 }
+| mident TDotDot { P.label $1 $2 }
+| TGoto disj_ident TPtVirg { P.goto $1 $2 $3 }
| TOBrace fun_start TCBrace
{ P.seq $1 $2 $3 }
d_ident:
- ident list(array_dec)
- { ($1,
- function t ->
- List.fold_right
- (function (l,i,r) ->
- function rest ->
- Ast0.wrap
- (Ast0.Array(rest,P.clt2mcode "[" l,i,P.clt2mcode "]" r)))
- $2 t) }
+ disj_ident list(array_dec)
+ { ($1, function t -> P.arrayify t $2) }
array_dec: l=TOCro i=option(eexpr) r=TCCro { (l,i,r) }
/* gccext:, labeled elements */
| list(designator) TEq initialize2 /*can we have another of these on the rhs?*/
{ Ast0.wrap(Ast0.InitGccExt($1,P.clt2mcode "=" $2,$3)) }
-| ident TDotDot initialize2
+| mident TDotDot initialize2
{ Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */
designator:
- | TDot ident
+ | TDot disj_ident
{ Ast0.DesignatorField (P.clt2mcode "." $1,$2) }
| TOCro eexpr TCCro
{ Ast0.DesignatorIndex (P.clt2mcode "[" $1,$2,P.clt2mcode "]" $3) }
/*****************************************************************************/
-/* The following cannot contain <... ...> at the top level. This can only
-be allowed as an expression when the expression is delimited on both sides
-by expression-specific markers. In that case, the rule eexpr is used, which
+/* expr cannot contain <... ...> at the top level. This can only
+be allowed as an expression when the expression is delimited on the left
+by an expression-specific marker. In that case, the rule eexpr is used, which
allows <... ...> anywhere. Hopefully, this will not be too much of a problem
-in practice. */
+in practice.
+dot_expressions is the most permissive. all three kinds of expressions use
+this once an expression_specific token has been seen */
expr: basic_expr(expr,invalid) { $1 }
/* allows ... and nests */
eexpr: basic_expr(eexpr,dot_expressions) { $1 }
{ Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<+..." $1,
Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
P.clt2mcode "...+>" c, None, true)) }
+| TMeta { tmeta_to_exp $1 }
//whenexp: TWhen TNotEq w=eexpr TLineEnd { w }
basic_expr(recurser,primary_extra):
- assign_expr(recurser,primary_extra) { $1 }
+ assign_expr(recurser,primary_extra) { $1 }
assign_expr(r,pe):
cond_expr(r,pe) { $1 }
cond_expr(r,pe):
arith_expr(r,pe) { $1 }
- | l=arith_expr(r,pe) w=TWhy t=option(eexpr) dd=TDotDot r=cond_expr(r,pe)
+ | l=arith_expr(r,pe) w=TWhy t=option(eexpr) dd=TDotDot r=eexpr/*see parser_c*/
{ Ast0.wrap(Ast0.CondExpr (l, P.clt2mcode "?" w, t,
P.clt2mcode ":" dd, r)) }
arith_expr(r,pe):
cast_expr(r,pe) { $1 }
- | arith_expr(r,pe) TMul arith_expr(r,pe)
+ | arith_expr(r,pe) TMul arith_expr_bis
{ P.arith_op Ast.Mul $1 $2 $3 }
- | arith_expr(r,pe) TDmOp arith_expr(r,pe)
+ | arith_expr(r,pe) TDmOp arith_expr_bis
{ let (op,clt) = $2 in P.arith_op op $1 clt $3 }
- | arith_expr(r,pe) TPlus arith_expr(r,pe)
+ | arith_expr(r,pe) TPlus arith_expr_bis
{ P.arith_op Ast.Plus $1 $2 $3 }
- | arith_expr(r,pe) TMinus arith_expr(r,pe)
+ | arith_expr(r,pe) TMinus arith_expr_bis
{ P.arith_op Ast.Minus $1 $2 $3 }
- | arith_expr(r,pe) TShLOp arith_expr(r,pe)
+ | arith_expr(r,pe) TShLOp arith_expr_bis
{ let (op,clt) = $2 in P.arith_op op $1 clt $3 }
- | arith_expr(r,pe) TShROp arith_expr(r,pe)
+ | arith_expr(r,pe) TShROp arith_expr_bis
{ let (op,clt) = $2 in P.arith_op op $1 clt $3 }
- | arith_expr(r,pe) TLogOp arith_expr(r,pe)
+ | arith_expr(r,pe) TLogOp arith_expr_bis
{ let (op,clt) = $2 in P.logic_op op $1 clt $3 }
- | arith_expr(r,pe) TEqEq arith_expr(r,pe)
+ | arith_expr(r,pe) TEqEq arith_expr_bis
{ P.logic_op Ast.Eq $1 $2 $3 }
- | arith_expr(r,pe) TNotEq arith_expr(r,pe)
+ | arith_expr(r,pe) TNotEq arith_expr_bis
{ P.logic_op Ast.NotEq $1 $2 $3 }
- | arith_expr(r,pe) TAnd arith_expr(r,pe)
+ | arith_expr(r,pe) TAnd arith_expr_bis
{ P.arith_op Ast.And $1 $2 $3 }
- | arith_expr(r,pe) TOr arith_expr(r,pe)
+ | arith_expr(r,pe) TOr arith_expr_bis
{ P.arith_op Ast.Or $1 $2 $3 }
- | arith_expr(r,pe) TXor arith_expr(r,pe)
+ | arith_expr(r,pe) TXor arith_expr_bis
{ P.arith_op Ast.Xor $1 $2 $3 }
- | arith_expr(r,pe) TAndLog arith_expr(r,pe)
+ | arith_expr(r,pe) TAndLog arith_expr_bis
{ P.logic_op Ast.AndLog $1 $2 $3 }
- | arith_expr(r,pe) TOrLog arith_expr(r,pe)
+ | arith_expr(r,pe) TOrLog arith_expr_bis
{ P.logic_op Ast.OrLog $1 $2 $3 }
+// allows dots now that an expression-specific token has been seen
+// need an extra rule because of recursion restrictions
+arith_expr_bis:
+ cast_expr(eexpr,dot_expressions) { $1 }
+ | arith_expr_bis TMul arith_expr_bis
+ { P.arith_op Ast.Mul $1 $2 $3 }
+ | arith_expr_bis TDmOp arith_expr_bis
+ { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
+ | arith_expr_bis TPlus arith_expr_bis
+ { P.arith_op Ast.Plus $1 $2 $3 }
+ | arith_expr_bis TMinus arith_expr_bis
+ { P.arith_op Ast.Minus $1 $2 $3 }
+ | arith_expr_bis TShLOp arith_expr_bis
+ { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
+ | arith_expr_bis TShROp arith_expr_bis
+ { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
+ | arith_expr_bis TLogOp arith_expr_bis
+ { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
+ | arith_expr_bis TEqEq arith_expr_bis
+ { P.logic_op Ast.Eq $1 $2 $3 }
+ | arith_expr_bis TNotEq arith_expr_bis
+ { P.logic_op Ast.NotEq $1 $2 $3 }
+ | arith_expr_bis TAnd arith_expr_bis
+ { P.arith_op Ast.And $1 $2 $3 }
+ | arith_expr_bis TOr arith_expr_bis
+ { P.arith_op Ast.Or $1 $2 $3 }
+ | arith_expr_bis TXor arith_expr_bis
+ { P.arith_op Ast.Xor $1 $2 $3 }
+ | arith_expr_bis TAndLog arith_expr_bis
+ { P.logic_op Ast.AndLog $1 $2 $3 }
+// no OrLog because it is left associative and this is for
+// a right argument, not sure why not the same problem for AndLog
+
cast_expr(r,pe):
unary_expr(r,pe) { $1 }
| lp=TOPar t=ctype rp=TCPar e=cast_expr(r,pe)
unary_expr(r,pe):
postfix_expr(r,pe) { $1 }
- | TInc unary_expr(r,pe)
+ | TInc unary_expr_bis
{ Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
- | TDec unary_expr(r,pe)
+ | TDec unary_expr_bis
{ Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
| unary_op cast_expr(r,pe)
{ let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
- | TBang unary_expr(r,pe)
+ | TBang unary_expr_bis
{ let mcode = P.clt2mcode Ast.Not $1 in
Ast0.wrap(Ast0.Unary($2, mcode)) }
- | TSizeof unary_expr(r,pe)
+ | TSizeof unary_expr_bis
+ { Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
+ | s=TSizeof lp=TOPar t=ctype rp=TCPar
+ { Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
+ P.clt2mcode "(" lp,t,
+ P.clt2mcode ")" rp)) }
+
+// version that allows dots
+unary_expr_bis:
+ postfix_expr(eexpr,dot_expressions) { $1 }
+ | TInc unary_expr_bis
+ { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
+ | TDec unary_expr_bis
+ { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
+ | unary_op cast_expr(eexpr,dot_expressions)
+ { let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
+ | TBang unary_expr_bis
+ { let mcode = P.clt2mcode Ast.Not $1 in
+ Ast0.wrap(Ast0.Unary($2, mcode)) }
+ | TSizeof unary_expr_bis
{ Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
| s=TSizeof lp=TOPar t=ctype rp=TCPar
{ Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
| postfix_expr(r,pe) TOCro eexpr TCCro
{ Ast0.wrap(Ast0.ArrayAccess ($1,P.clt2mcode "[" $2,$3,
P.clt2mcode "]" $4)) }
- | postfix_expr(r,pe) TDot ident
+ | postfix_expr(r,pe) TDot disj_ident
{ Ast0.wrap(Ast0.RecordAccess($1, P.clt2mcode "." $2, $3)) }
- | postfix_expr(r,pe) TPtrOp ident
+ | postfix_expr(r,pe) TPtrOp disj_ident
{ Ast0.wrap(Ast0.RecordPtAccess($1, P.clt2mcode "->" $2,
$3)) }
| postfix_expr(r,pe) TInc
seed_elem:
TString { let (x,_) = $1 in Ast.SeedString x }
| TMetaId { let (x,_,_,_) = $1 in Ast.SeedId x }
+| TMeta {failwith "tmeta"}
| TRuleName TDot pure_ident
{ let nm = ($1,P.id2name $3) in
P.check_meta(Ast.MetaIdDecl(Ast.NONE,nm));
None -> (i, Ast.IdNoConstraint)
| Some constraint_ -> (i,constraint_))
}
-| TVirtual TDot pure_ident { Common.Right (P.id2name $3) }
+| TVirtual TDot pure_ident
+ {
+ let nm = P.id2name $3 in
+ Iteration.parsed_virtual_identifiers :=
+ Common.union_set [nm]
+ !Iteration.parsed_virtual_identifiers;
+ Common.Right nm
+ }
pure_ident_or_meta_ident_with_idconstraint(constraint_type):
i=pure_ident_or_meta_ident c=option(constraint_type)
(function mv -> Ast.MetaPosDecl(Ast.NONE,mv)))
l }
-func_ident: pure_ident
- { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
- | TMetaId
+func_ident: ident { $1 }
+ | TMetaFunc
{ let (nm,constraints,pure,clt) = $1 in
- Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
+ Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
+ | TMetaLocalFunc
+ { let (nm,constraints,pure,clt) = $1 in
+ Ast0.wrap
+ (Ast0.MetaLocalFunc(P.clt2mcode nm clt,constraints,pure)) }
+
+fn_ident: disj_ident { $1 }
| TMetaFunc
{ let (nm,constraints,pure,clt) = $1 in
Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
{ let (nm,constraints,pure,clt) = $1 in
Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
+mident: pure_ident
+ { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
+ | TMeta { tmeta_to_ident $1 }
+ | TMetaId
+ { let (nm,constraints,pure,clt) = $1 in
+ Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
+
+disj_ident:
+ mident { $1 }
+ | lp=TOPar0 t=midzero_list(disj_ident,disj_ident) rp=TCPar0
+ { let (mids,code) = t in
+ Ast0.wrap
+ (Ast0.DisjId(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
+
+type_ident: disj_ident { $1 }
+ | TTypeId
+ { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
+
decl_ident:
TDeclarerId
{ Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
typedef_ident:
pure_ident
{ Ast0.wrap(Ast0.TypeName(P.id2mcode $1)) }
+ | TMeta { tmeta_to_type $1 }
| TMetaType
{ let (nm,pure,clt) = $1 in
Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
(($2, nm), mv) }
| TShLOp TVirtual TDot cocci=pure_ident
{ let nm = P.id2name cocci in
+ Iteration.parsed_virtual_identifiers :=
+ Common.union_set [nm]
+ !Iteration.parsed_virtual_identifiers;
let name = ("virtual", nm) in
let mv = Ast.MetaIdDecl(Ast.NONE,name) in
(name,mv) }