X-Git-Url: https://git.hcoop.net/bpt/coccinelle.git/blobdiff_plain/90aeb998d88488b4402e7b211b064056d175fcbb..3a31414346dd7d7e8baa4cb8b804a2d5e1797962:/parsing_cocci/parser_cocci_menhir.mly diff --git a/parsing_cocci/parser_cocci_menhir.mly b/parsing_cocci/parser_cocci_menhir.mly index b081347..f0b6832 100644 --- a/parsing_cocci/parser_cocci_menhir.mly +++ b/parsing_cocci/parser_cocci_menhir.mly @@ -40,7 +40,7 @@ module P = Parse_aux %token EOF %token TIdentifier TExpression TStatement TFunction TLocal TType TParameter -%token TIdExpression TInitialiser +%token TIdExpression TInitialiser TDeclaration TField %token Tlist TFresh TConstant TError TWords TWhy0 TPlus0 TBang0 %token TPure TContext TGenerated %token TTypedef TDeclarer TIterator TName TPosition TPosAny @@ -49,6 +49,7 @@ module P = Parse_aux %token TRuleName %token Tchar Tshort Tint Tdouble Tfloat Tlong +%token Tsize_t Tssize_t Tptrdiff_t %token Tvoid Tstruct Tunion Tenum %token Tunsigned Tsigned @@ -65,7 +66,7 @@ module P = Parse_aux %token TMetaIterator TMetaDeclarer %token TMetaErr %token TMetaParam TMetaStm TMetaStmList TMetaType -%token TMetaInit +%token TMetaInit TMetaDecl TMetaField %token TMetaParamList TMetaExpList %token TMetaExp TMetaIdExp TMetaLocalIdExp TMetaConst %token TMetaPos @@ -81,7 +82,7 @@ module P = Parse_aux %token TPathIsoFile %token TIncludeL TIncludeNL -%token TDefine +%token TDefine TUndef %token TDefineParam %token TMinusFile TPlusFile @@ -96,7 +97,7 @@ module P = Parse_aux %token TAnd %token TEqEq TNotEq TTildeEq TTildeExclEq TSub %token TLogOp /* TInf TSup TInfEq TSupEq */ -%token TShOp /* TShl TShr */ +%token TShLOp TShROp /* TShl TShr */ %token TDmOp /* TDiv TMod */ %token TPlus TMinus %token TMul TTilde @@ -113,6 +114,8 @@ module P = Parse_aux %token TIso TRightIso TIsoExpression TIsoStatement TIsoDeclaration TIsoType %token TIsoTopLevel TIsoArgExpression TIsoTestExpression TIsoToTestExpression +%token TUnderscore + %token TInvalid /* operator precedence */ @@ -126,7 +129,7 @@ module P = Parse_aux %left TAnd %left TEqEq TNotEq %left TLogOp /* TInf TSup TInfEq TSupEq */ -%left TShOp /* TShl TShr */ +%left TShLOp TShROp /* TShl TShr */ %left TPlus TMinus %left TMul TDmOp /* TDiv TMod */ @@ -159,7 +162,7 @@ rule_name %start meta_main %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> meta_main -%start script_meta_main +%start <(string option (*string*) * string option (*ast*)) * (Ast_cocci.meta_name * Ast_cocci.metavar) option> script_meta_main %start iso_main %type iso_main @@ -208,8 +211,8 @@ rule_name: /* these rules have no name as a cheap way to ensure that no normal rule inherits their metavariables or depends on them */ { P.make_generated_rule_name_result None d i a e ee } - | TScript TDotDot lang=pure_ident d=depends TArob - { P.make_script_rule_name_result lang d } + | TScript TDotDot lang=pure_ident nm=ioption(pure_ident) d=depends TArob + { P.make_script_rule_name_result lang nm d } | TInitialize TDotDot lang=pure_ident d=depends TArob { P.make_initial_script_rule_name_result lang d } | TFinalize TDotDot lang=pure_ident d=depends TArob @@ -261,6 +264,8 @@ incl: | 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 []) @@ -312,23 +317,25 @@ metadec: !Data.add_pos_meta name constraints any; tok in P.create_metadec_with_constraints ar false kindfn ids } | ar=arity ispure=pure - TParameter Tlist TOCro id=pure_ident_or_meta_ident TCCro + TParameter 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.MetaParamListDecl(arity,name,Some lenname)) in - !Data.add_paramlist_meta name (Some lenname) pure; tok) - id ids } + let tok = check_meta(Ast.MetaParamListDecl(arity,name,lenname)) in + !Data.add_paramlist_meta name lenname pure; tok) + len ids } | ar=arity ispure=pure - TExpression Tlist TOCro id=pure_ident_or_meta_ident TCCro + TExpression 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.MetaExpListDecl(arity,name,Some lenname)) in - !Data.add_explist_meta name (Some lenname) pure; tok) - id ids } + let tok = check_meta(Ast.MetaExpListDecl(arity,name,lenname)) in + !Data.add_explist_meta name lenname pure; tok) + len ids } + +list_len: + pure_ident_or_meta_ident { Common.Left $1 } +| TInt { let (x,clt) = $1 in Common.Right (int_of_string x) } %inline metakind_fresh: TFresh TIdentifier @@ -344,12 +351,14 @@ metadec: !Data.add_param_meta name pure; tok) } | TParameter Tlist { (fun arity name pure check_meta -> - let tok = check_meta(Ast.MetaParamListDecl(arity,name,None)) in - !Data.add_paramlist_meta name None pure; tok) } + let len = Ast.AnyLen in + let tok = check_meta(Ast.MetaParamListDecl(arity,name,len)) in + !Data.add_paramlist_meta name len pure; tok) } | TExpression Tlist { (fun arity name pure check_meta -> - let tok = check_meta(Ast.MetaExpListDecl(arity,name,None)) in - !Data.add_explist_meta name None pure; tok) } + let len = Ast.AnyLen in + let tok = check_meta(Ast.MetaExpListDecl(arity,name,len)) in + !Data.add_explist_meta name len pure; tok) } | TType { (fun arity name pure check_meta -> let tok = check_meta(Ast.MetaTypeDecl(arity,name)) in @@ -362,6 +371,14 @@ metadec: { (fun arity name pure check_meta -> let tok = check_meta(Ast.MetaStmDecl(arity,name)) in !Data.add_stm_meta name pure; tok) } +| TDeclaration + { (fun arity name pure check_meta -> + let tok = check_meta(Ast.MetaDeclDecl(arity,name)) in + !Data.add_decl_meta name pure; tok) } +| TField + { (fun arity name pure check_meta -> + let tok = check_meta(Ast.MetaFieldDecl(arity,name)) in + !Data.add_field_meta name pure; tok) } | TStatement Tlist { (fun arity name pure check_meta -> let tok = check_meta(Ast.MetaStmListDecl(arity,name)) in @@ -393,6 +410,9 @@ metadec: 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 @@ -441,14 +461,9 @@ metadec: | 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) @@ -456,6 +471,17 @@ metadec: 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 -> @@ -487,10 +513,11 @@ metadec: !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) @@ -537,8 +564,19 @@ non_signable_types: { 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, i)) } + { Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, Some i)) } +| s=Tenum i=ioption(ident) l=TOBrace ids=enum_decl_list r=TCBrace + { (if i = None && !Data.in_iso + 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 { Ast0.wrap(Ast0.StructUnionName(s, Some i)) } | s=struct_or_union i=ioption(ident) @@ -592,10 +630,14 @@ struct_or_union: | u=Tunion { P.clt2mcode Ast.Union u } struct_decl: - TNothing { [] } + TNothing { [] } + | struct_decl_one { [$1] } + +struct_decl_one: + | TMetaField { P.meta_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))] } + Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv)) } | t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar pv=TPtVirg { let (id,fn) = d in @@ -604,11 +646,11 @@ struct_decl: (Ast0.FunctionPointer (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1, P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in - [Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] } + Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv)) } | cv=ioption(const_vol) i=pure_ident d=d_ident pv=TPtVirg { let (id,fn) = d in let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in - [Ast0.wrap(Ast0.UnInit(None,fn idtype,id,P.clt2mcode ";" pv))] } + Ast0.wrap(Ast0.UnInit(None,fn idtype,id,P.clt2mcode ";" pv)) } struct_decl_list: struct_decl_list_start { Ast0.wrap(Ast0.DOTS($1)) } @@ -616,8 +658,8 @@ struct_decl_list: struct_decl_list_start: struct_decl { $1 } | struct_decl struct_decl_list_start { $1@$2 } -| d=edots_when(TEllipsis,struct_decl) r=continue_struct_decl_list - { (P.mkddots "..." d)::r } +| d=edots_when(TEllipsis,struct_decl_one) r=continue_struct_decl_list + { (P.mkddots_one "..." d)::r } continue_struct_decl_list: /* empty */ { [] } @@ -625,6 +667,40 @@ continue_struct_decl_list: | struct_decl { $1 } +/* ---------------------------------------------------------------------- */ +/* 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 + { let id = Ast0.wrap(Ast0.Ident($1)) in + Ast0.wrap + (Ast0.Assignment + (id,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3, + false)) } + +enum_val: + ident { Ast0.wrap(Ast0.Ident($1)) } + | TInt + { let (x,clt) = $1 in + Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) } + | TMetaConst + { let (nm,constraints,pure,ty,clt) = $1 in + Ast0.wrap + (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) } + | TMetaExp + { let (nm,constraints,pure,ty,clt) = $1 in + Ast0.wrap + (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) } + | TMetaIdExp + { let (nm,constraints,pure,ty,clt) = $1 in + Ast0.wrap + (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) } + +enum_decl_list: + nonempty_list_start(enum_decl_one,edots_when(TEllipsis,enum_decl_one)) + { Ast0.wrap(Ast0.DOTS($1 P.mkedots (fun c -> Ast0.EComma c))) } + /*****************************************************************************/ /* have to inline everything to avoid conflicts? switch to proper @@ -687,6 +763,20 @@ includes: 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 @@ -745,33 +835,15 @@ defineop: /* ---------------------------------------------------------------------- */ -define_param_list: define_param_list_start - {let circle x = - match Ast0.unwrap x with Ast0.DPcircles(_) -> true | _ -> false in - if List.exists circle $1 - then Ast0.wrap(Ast0.CIRCLES($1)) - else Ast0.wrap(Ast0.DOTS($1)) } - -define_param_list_start: - ident { [Ast0.wrap(Ast0.DParam $1)] } - | ident TComma define_param_list_start - { Ast0.wrap(Ast0.DParam $1):: - Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $2))::$3 } - | d=TEllipsis r=list(dp_comma_args(TEllipsis)) - { (P.mkdpdots "..." d):: - (List.concat (List.map (function x -> x (P.mkdpdots "...")) r)) } - -dp_comma_args(dotter): - c=TComma d=dotter - { function dot_builder -> - [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," c)); dot_builder d] } -| TComma ident - { function dot_builder -> - [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $1)); - Ast0.wrap(Ast0.DParam $2)] } - -define_param_list_option: define_param_list { $1 } - | /* empty */ { Ast0.wrap(Ast0.DOTS([])) } +dparam: ident { Ast0.wrap(Ast0.DParam $1) } + +define_param_list_option: + empty_list_start(dparam,TEllipsis) + { Ast0.wrap + (Ast0.DOTS + ($1 + (fun _ d -> Ast0.wrap(Ast0.DPdots(P.clt2mcode "," d))) + (fun c -> Ast0.DPComma c))) } /*****************************************************************************/ @@ -977,6 +1049,7 @@ a disjunction on a statement with a declaration in each branch */ decl_var: t=ctype pv=TPtVirg { [Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv))] } + | TMetaDecl { [P.meta_decl $1] } | s=ioption(storage) t=ctype d=comma_list(d_ident) pv=TPtVirg { List.map (function (id,fn) -> @@ -1038,6 +1111,7 @@ decl_var: one_decl_var: t=ctype pv=TPtVirg { Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv)) } + | TMetaDecl { P.meta_decl $1 } | s=ioption(storage) t=ctype d=d_ident pv=TPtVirg { let (id,fn) = d in Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) } @@ -1103,11 +1177,12 @@ initialize: eexpr { Ast0.wrap(Ast0.InitExpr($1)) } | TOBrace initialize_list TCBrace - { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) } - | TOBrace TCBrace - { Ast0.wrap - (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []), - P.clt2mcode "}" $2)) } + { if P.struct_initializer $2 + then + let il = P.drop_dot_commas $2 in + Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false)) + else + Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) } | TMetaInit {let (nm,pure,clt) = $1 in Ast0.wrap(Ast0.MetaInit(P.clt2mcode nm clt,pure)) } @@ -1117,13 +1192,14 @@ initialize2: /*dots and nests probably not allowed at top level, haven't looked into why*/ arith_expr(eexpr,invalid) { Ast0.wrap(Ast0.InitExpr($1)) } | TOBrace initialize_list TCBrace - { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) } -| TOBrace TCBrace - { Ast0.wrap - (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []), - P.clt2mcode "}" $2)) } + { if P.struct_initializer $2 + then + let il = P.drop_dot_commas $2 in + Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false)) + else + Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) } /* gccext:, labeled elements */ -| list(designator) TEq initialize2 +| 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 { Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */ @@ -1138,34 +1214,8 @@ designator: $4,P.clt2mcode "]" $5) } initialize_list: - initialize_list_start { Ast0.wrap(Ast0.DOTS($1)) } - -initialize_list_start: - initialize2 TComma { [$1;Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))] } -| initialize2 TComma initialize_list_start - { $1::Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))::$3 } -| TNothing initialize_list_start - { $2 } /* + code only */ -| d=edots_when(TEllipsis,initialize) - r=comma_initializers(edots_when(TEllipsis,initialize)) - { (P.mkidots "..." d):: - (List.concat(List.map (function x -> x (P.mkidots "...")) r)) } - -comma_initializers(dotter): - /* empty */ { [] } -| d=dotter r=comma_initializers2(dotter) - { (function dot_builder -> [dot_builder d])::r } -| TNothing r=comma_initializers(dotter) { r } -| i=initialize2 c=TComma r=comma_initializers(dotter) - { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))]):: - r } - -comma_initializers2(dotter): - /* empty */ { [] } -| TNothing r=comma_initializers(dotter) { r } -| i=initialize2 c=TComma r=comma_initializers(dotter) - { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))]):: - r } + empty_list_start(initialize2,edots_when(TEllipsis,initialize)) + { Ast0.wrap(Ast0.DOTS($1 P.mkidots (fun c -> Ast0.IComma c))) } /* a statement that is part of a list */ decl_statement: @@ -1228,11 +1278,13 @@ decl_statement_expr: /*****************************************************************************/ -/* 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 } @@ -1289,39 +1341,74 @@ assign_expr_bis: 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) TShOp 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) TLogOp 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_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) @@ -1330,16 +1417,35 @@ 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, @@ -1499,7 +1605,14 @@ pure_ident_or_meta_ident_with_idconstraint_virt(constraint_type): 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) @@ -1699,41 +1812,68 @@ typedef_ident: /*****************************************************************************/ decl_list(decl): - /* empty */ { Ast0.wrap(Ast0.DOTS([])) } -| decl_list_start(decl) - {let circle x = - match Ast0.unwrap x with Ast0.Pcircles(_) -> true | _ -> false in - if List.exists circle $1 - then Ast0.wrap(Ast0.CIRCLES($1)) - else Ast0.wrap(Ast0.DOTS($1)) } - -decl_list_start(decl): - one_dec(decl) { [$1] } -| one_dec(decl) TComma decl_list_start(decl) - { $1::Ast0.wrap(Ast0.PComma(P.clt2mcode "," $2))::$3 } -| TEllipsis list(comma_decls(TEllipsis,decl)) - { Ast0.wrap(Ast0.Pdots(P.clt2mcode "..." $1)):: - (List.concat(List.map (function x -> x (P.mkpdots "...")) $2)) } + empty_list_start(one_dec(decl),TEllipsis) + { Ast0.wrap + (Ast0.DOTS + ($1 + (fun _ d -> Ast0.wrap(Ast0.Pdots(P.clt2mcode "..." d))) + (fun c -> Ast0.PComma c))) } one_dec(decl): decl { $1 } | TMetaParamList { let (nm,lenname,pure,clt) = $1 in let nm = P.clt2mcode nm clt in - let lenname = - match lenname with - Some nm -> Some(P.clt2mcode nm clt) - | None -> None in + let lenname = + match lenname with + Ast.AnyLen -> Ast0.AnyListLen + | Ast.MetaLen nm -> Ast0.MetaListLen(P.clt2mcode nm clt) + | Ast.CstLen n -> Ast0.CstListLen n in Ast0.wrap(Ast0.MetaParamList(nm,lenname,pure)) } -comma_decls(dotter,decl): - TComma dotter - { function dot_builder -> - [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1)); - dot_builder $2] } -| TComma one_dec(decl) - { function dot_builder -> - [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1)); $2] } +/* ---------------------------------------------------------------------- */ +/* comma list parser, used for fn params, fn args, enums, initlists, + #define params */ + +/* enums: enum_decl, edots_when(TEllipsis,enum_decl_one) +fun s d -> P.mkedots "..." d +fun c -> Ast0.EComma c + */ + +empty_list_start(elem,dotter): + /* empty */ { fun build_dots build_comma -> [] } +| nonempty_list_start(elem,dotter) { $1 } + +nonempty_list_start(elem,dotter): /* dots allowed */ + elem { fun build_dots build_comma -> [$1] } +| elem TComma + { fun build_dots build_comma -> + $1::[Ast0.wrap(build_comma(P.clt2mcode "," $2))] } +| elem TComma nonempty_list_start(elem,dotter) + { fun build_dots build_comma -> + $1::(Ast0.wrap(build_comma(P.clt2mcode "," $2))):: + ($3 build_dots build_comma) } +| TNothing nonempty_list_start(elem,dotter) { $2 } +| d=dotter { fun build_dots build_comma -> [(build_dots "..." d)] } +| d=dotter TComma + { fun build_dots build_comma -> + [(build_dots "..." d);Ast0.wrap(build_comma(P.clt2mcode "," $2))] } +| d=dotter TComma r=continue_list(elem,dotter) + { fun build_dots build_comma -> + (build_dots "..." d):: + (Ast0.wrap(build_comma(P.clt2mcode "," $2))):: + (r build_dots build_comma) } + +continue_list(elem,dotter): /* dots not allowed */ + elem { fun build_dots build_comma -> [$1] } +| elem TComma + { fun build_dots build_comma -> + $1::[Ast0.wrap(build_comma(P.clt2mcode "," $2))] } +| elem TComma nonempty_list_start(elem,dotter) + { fun build_dots build_comma -> + $1::(Ast0.wrap(build_comma(P.clt2mcode "," $2))):: + ($3 build_dots build_comma) } +| TNothing nonempty_list_start(elem,dotter) { $2 } /* ---------------------------------------------------------------------- */ @@ -1818,7 +1958,12 @@ toplevel_after_stm: top_init: TOInit initialize_list TCBrace - { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) } + { if P.struct_initializer $2 + then + let il = P.drop_dot_commas $2 in + Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,il,P.clt2mcode "}" $3,false)) + else + Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3,true)) } /* ------------------------------------------------------------------------ */ /* Plus top level */ @@ -1917,49 +2062,28 @@ when_start: /* ---------------------------------------------------------------------- */ -eexpr_list: - eexpr_list_start - {let circle x = - match Ast0.unwrap x with Ast0.Ecircles(_) -> true | _ -> false in - let star x = - match Ast0.unwrap x with Ast0.Estars(_) -> true | _ -> false in - if List.exists circle $1 - then Ast0.wrap(Ast0.CIRCLES($1)) - else - if List.exists star $1 - then Ast0.wrap(Ast0.STARS($1)) - else Ast0.wrap(Ast0.DOTS($1)) } - /* arg expr. may contain a type or a explist metavariable */ aexpr: - eexpr - { Ast0.set_arg_exp $1 } + dexpr { Ast0.set_arg_exp $1 } | TMetaExpList { let (nm,lenname,pure,clt) = $1 in let nm = P.clt2mcode nm clt in let lenname = match lenname with - Some nm -> Some(P.clt2mcode nm clt) - | None -> None in + Ast.AnyLen -> Ast0.AnyListLen + | Ast.MetaLen nm -> Ast0.MetaListLen(P.clt2mcode nm clt) + | Ast.CstLen n -> Ast0.CstListLen n in Ast0.wrap(Ast0.MetaExprList(nm,lenname,pure)) } | ctype { Ast0.set_arg_exp(Ast0.wrap(Ast0.TypeExp($1))) } -eexpr_list_start: - aexpr { [$1] } - | aexpr TComma eexpr_list_start - { $1::Ast0.wrap(Ast0.EComma(P.clt2mcode "," $2))::$3 } - -comma_args(dotter): - c=TComma d=dotter - { function dot_builder -> - [Ast0.wrap(Ast0.EComma(P.clt2mcode "," c)); dot_builder d] } -| TComma aexpr - { function dot_builder -> - [Ast0.wrap(Ast0.EComma(P.clt2mcode "," $1)); $2] } - -eexpr_list_option: eexpr_list { $1 } - | /* empty */ { Ast0.wrap(Ast0.DOTS([])) } +eexpr_list_option: + empty_list_start(aexpr,TEllipsis) + { Ast0.wrap + (Ast0.DOTS + ($1 + (fun _ d -> Ast0.wrap(Ast0.Edots(P.clt2mcode "..." d,None))) + (fun c -> Ast0.EComma c))) } /****************************************************************************/ @@ -2044,7 +2168,27 @@ never_used: TPragma { () } | TScriptData { () } script_meta_main: - py=pure_ident TShOp TRuleName TDot cocci=pure_ident TMPtVirg - { (P.id2name py, ($3, P.id2name cocci)) } - | py=pure_ident TShOp TVirtual TDot cocci=pure_ident TMPtVirg - { (P.id2name py, ("virtual", P.id2name cocci)) } + py=pure_ident TMPtVirg + { ((Some (P.id2name py), None), None) } + | py=pure_ident script_name_decl TMPtVirg + { ((Some (P.id2name py), None), Some $2) } + | TOPar TUnderscore TComma ast=pure_ident TCPar script_name_decl TMPtVirg + { ((None, Some (P.id2name ast)), Some $6) } + | TOPar str=pure_ident TComma TUnderscore TCPar script_name_decl TMPtVirg + { ((Some (P.id2name str), None), Some $6) } + | TOPar str=pure_ident TComma ast=pure_ident TCPar script_name_decl TMPtVirg + { ((Some (P.id2name str), Some (P.id2name ast)), Some $6) } + +script_name_decl: + TShLOp TRuleName TDot cocci=pure_ident + { let nm = P.id2name cocci in + let mv = Parse_aux.lookup $2 nm in + (($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) }