X-Git-Url: http://git.hcoop.net/bpt/coccinelle.git/blobdiff_plain/88e711986b3855c3d5ecf43845f20e0fafef4e5c..65038c617fe3e5d7a284059fbfa78dddfbb9b9c4:/parsing_cocci/parser_cocci_menhir.mly diff --git a/parsing_cocci/parser_cocci_menhir.mly b/parsing_cocci/parser_cocci_menhir.mly index 24058d2..ef6df83 100644 --- a/parsing_cocci/parser_cocci_menhir.mly +++ b/parsing_cocci/parser_cocci_menhir.mly @@ -35,12 +35,75 @@ parameter needs both a type and an identifier *) 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,Ast.NoVal,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,Ast.NoVal,pure,clt)) + (function TMetaId(_,_,_,_,_) -> true | _ -> false)); + Ast0.wrap(Ast0.MetaId(P.clt2mcode name clt,Ast.IdNoConstraint,Ast.NoVal,pure)) %} %token EOF %token TIdentifier TExpression TStatement TFunction TLocal TType TParameter -%token TIdExpression TInitialiser +%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 @@ -49,6 +112,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 @@ -61,12 +125,14 @@ module P = Parse_aux %token TIdent TTypeId TDeclarerId TIteratorId %token TPragma -%token TMetaId TMetaFunc TMetaLocalFunc +%token TMetaId +%token TMetaFunc TMetaLocalFunc %token TMetaIterator TMetaDeclarer %token TMetaErr %token TMetaParam TMetaStm TMetaStmList TMetaType -%token TMetaInit -%token TMetaParamList TMetaExpList +%token TMetaInit TMetaDecl TMetaField TMeta +%token TMetaParamList TMetaExpList TMetaInitList +%token TMetaFieldList %token TMetaExp TMetaIdExp TMetaLocalIdExp TMetaConst %token TMetaPos @@ -81,7 +147,7 @@ module P = Parse_aux %token TPathIsoFile %token TIncludeL TIncludeNL -%token TDefine +%token TDefine TUndef %token TDefineParam %token TMinusFile TPlusFile @@ -96,7 +162,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 @@ -128,7 +194,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 */ @@ -161,7 +227,7 @@ rule_name %start meta_main %type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> meta_main -%start <(string option (*string*) * string option (*ast*)) * Ast_cocci.meta_name * Ast_cocci.metavar> 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 @@ -210,8 +276,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 @@ -263,6 +329,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 []) @@ -329,6 +397,22 @@ metadec: 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 } +| ar=arity ispure=pure + TInitialiser 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.MetaInitListDecl(arity,name,lenname)) in + !Data.add_initlist_meta name lenname pure; tok) + len ids } list_len: pure_ident_or_meta_ident { Common.Left $1 } @@ -338,11 +422,15 @@ list_len: TFresh TIdentifier { (fun name check_meta seed -> let tok = check_meta(Ast.MetaFreshIdDecl(name,seed)) in - !Data.add_fresh_id_meta name; tok) } + !Data.add_fresh_id_meta name seed; tok) } /* 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) } @@ -364,10 +452,28 @@ list_len: { (fun arity name pure check_meta -> let tok = check_meta(Ast.MetaInitDecl(arity,name)) in !Data.add_init_meta name pure; tok) } +| TInitialiser Tlist + { (fun arity name pure check_meta -> + let len = Ast.AnyLen in + let tok = check_meta(Ast.MetaInitListDecl(arity,name,len)) in + !Data.add_initlist_meta name len pure; tok) } | TStatement { (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) } +| 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 @@ -399,6 +505,9 @@ list_len: 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 @@ -447,14 +556,9 @@ list_len: | 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) @@ -462,6 +566,17 @@ list_len: 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 -> @@ -493,10 +608,11 @@ list_len: !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) @@ -543,11 +659,22 @@ 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)) } -| s=struct_or_union 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 + { (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=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"); @@ -582,14 +709,19 @@ ctype: 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 } /* ---------------------------------------------------------------------- */ @@ -598,10 +730,16 @@ 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 } + | 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))] } + 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 @@ -610,11 +748,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)) } @@ -622,8 +760,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 */ { [] } @@ -631,6 +769,41 @@ continue_struct_decl_list: | struct_decl { $1 } +/* ---------------------------------------------------------------------- */ +/* very restricted what kinds of expressions can appear in an enum decl */ + +enum_decl_one: + | disj_ident { Ast0.wrap(Ast0.Ident($1)) } + | disj_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)) } + | TMeta { tmeta_to_exp $1 } + | 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 @@ -642,13 +815,13 @@ minus_body: /*ew=loption(error_words)*/ { match f@b(*@ew*) with [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty") - | code -> Top_level.top_level code } + | code -> code } plus_body: f=loption(filespec) b=loption(plus_start) /*ew=loption(error_words)*/ - { Top_level.top_level (f@b(*@ew*)) } + { f@b(*@ew*) } minus_exp_body: f=loption(filespec) @@ -656,13 +829,13 @@ minus_exp_body: /*ew=loption(error_words)*/ { match f@[b](*@ew*) with [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty") - | code -> Top_level.top_level code } + | code -> code } plus_exp_body: f=loption(filespec) b=top_eexpr /*ew=loption(error_words)*/ - { Top_level.top_level (f@[b](*@ew*)) } + { f@[b](*@ew*) } filespec: TMinusFile TPlusFile @@ -693,6 +866,23 @@ includes: P.clt2mcode (Ast.NonLocal (Parse_aux.str2inc (P.id2name $1))) (P.drop_bef clt))) } +| TUndef TLineEnd + { let (clt,ident) = $1 in + let aft = P.get_aft clt in (* move stuff after the define to the ident *) + Ast0.wrap + (Ast0.Undef + (P.clt2mcode "#undef" (P.drop_aft clt), + (match ident with + TMetaId((nm,constraints,seed,pure,clt)) -> + let clt = P.set_aft aft clt in + Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,seed,pure)) + | TIdent((nm,clt)) -> + let clt = P.set_aft aft clt in + Ast0.wrap(Ast0.Id(P.clt2mcode nm clt)) + | _ -> + raise + (Semantic_cocci.Semantic + "unexpected name for a #define")))) } | d=defineop TLineEnd { d (Ast0.wrap(Ast0.DOTS([]))) } | d=defineop t=ctype TLineEnd @@ -712,15 +902,19 @@ includes: defineop: TDefine { let (clt,ident) = $1 in + let aft = P.get_aft clt in (* move stuff after the define to the ident *) function body -> Ast0.wrap (Ast0.Define - (P.clt2mcode "#define" clt, + (P.clt2mcode "#define" (P.drop_aft 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)) + TMetaId((nm,constraints,seed,pure,clt)) -> + let clt = P.set_aft aft clt in + Ast0.wrap + (Ast0.MetaId(P.clt2mcode nm clt,constraints,seed,pure)) + | TIdent((nm,clt)) -> + let clt = P.set_aft aft clt in + Ast0.wrap(Ast0.Id(P.clt2mcode nm clt)) | _ -> raise (Semantic_cocci.Semantic @@ -729,61 +923,46 @@ defineop: body)) } | TDefineParam define_param_list_option TCPar { let (clt,ident,parenoff,parencol) = $1 in + let aft = P.get_aft clt in (* move stuff after the define to the ( *) (* clt is the start of the #define itself *) let (arity,line,lline,offset,col,strbef,straft,pos) = clt in let lp = P.clt2mcode "(" - (arity,line,lline,parenoff,parencol,[],[],Ast0.NoMetaPos) in + (arity,line,lline,parenoff,parencol,[],[],[]) in function body -> Ast0.wrap (Ast0.Define - (P.clt2mcode "#define" clt, + (P.clt2mcode "#define" (P.drop_aft 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)) + TMetaId((nm,constraints,seed,pure,clt)) -> + Ast0.wrap + (Ast0.MetaId(P.clt2mcode nm clt,constraints,seed,pure)) + | TIdent((nm,clt)) -> + Ast0.wrap(Ast0.Id(P.clt2mcode nm clt)) | _ -> raise (Semantic_cocci.Semantic "unexpected name for a #define")), - Ast0.wrap (Ast0.DParams (lp,$2,P.clt2mcode ")" $3)),body)) } + (let clt = P.set_aft aft $3 in + Ast0.wrap (Ast0.DParams (lp,$2,P.clt2mcode ")" clt))),body)) } /* ---------------------------------------------------------------------- */ -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: mident { 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))) } /*****************************************************************************/ 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, @@ -794,7 +973,7 @@ funproto: 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()), @@ -849,10 +1028,10 @@ storage: | 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 @@ -863,6 +1042,7 @@ decl: t=ctype i=ident | 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 } @@ -883,9 +1063,10 @@ const_vol: statement: includes { $1 } /* shouldn't be allowed to be a single_statement... */ +| TMeta { tmeta_to_statement $1} | TMetaStm { P.meta_stm $1 } -| expr TPtVirg +| option(expr) TPtVirg { P.exp_stm $1 $2 } | TIf TOPar eexpr TCPar single_statement %prec TIf { P.ifthen $1 $2 $3 $4 $5 } @@ -906,8 +1087,8 @@ statement: | 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 } @@ -941,7 +1122,7 @@ what about statement metavariables? */ rule_elem_statement: one_decl_var { Ast0.wrap(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),$1)) } -| expr TPtVirg { P.exp_stm $1 $2 } +| option(expr) TPtVirg { P.exp_stm $1 $2 } | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 } | TReturn TPtVirg { P.ret $1 $2 } | TBreak TPtVirg { P.break $1 $2 } @@ -983,6 +1164,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) -> @@ -1044,6 +1226,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)) } @@ -1093,15 +1276,8 @@ one_decl_var: 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) } @@ -1109,11 +1285,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)) } @@ -1123,19 +1300,32 @@ 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 +| mident TDotDot initialize2 { Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */ + | TMetaInit + {let (nm,pure,clt) = $1 in + Ast0.wrap(Ast0.MetaInit(P.clt2mcode nm clt,pure)) } + | TMetaInitList + {let (nm,lenname,pure,clt) = $1 in + let nm = P.clt2mcode nm clt 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.MetaInitList(nm,lenname,pure)) } designator: - | TDot ident + | TDot disj_ident { Ast0.DesignatorField (P.clt2mcode "." $1,$2) } | TOCro eexpr TCCro { Ast0.DesignatorIndex (P.clt2mcode "[" $1,$2,P.clt2mcode "]" $3) } @@ -1144,34 +1334,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: @@ -1234,11 +1398,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 } @@ -1265,11 +1431,12 @@ nest_expressions: { 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 } @@ -1295,39 +1462,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) 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) @@ -1336,16 +1538,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, @@ -1363,9 +1584,9 @@ postfix_expr(r,pe): | 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 @@ -1379,6 +1600,9 @@ postfix_expr(r,pe): primary_expr(recurser,primary_extra): func_ident { Ast0.wrap(Ast0.Ident($1)) } + | TAndLog ident + { let op = P.clt2mcode Ast.GetRefLabel $1 in + Ast0.wrap(Ast0.Unary(Ast0.wrap(Ast0.Ident($2)), op)) } | TInt { let (x,clt) = $1 in Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) } @@ -1477,7 +1701,15 @@ pure_ident_or_meta_ident_with_seed: seed_elem: TString { let (x,_) = $1 in Ast.SeedString x } -| TMetaId { let (x,_,_,_) = $1 in Ast.SeedId x } +| TMetaId { let (x,_,_,_,_) = $1 in Ast.SeedId x } +| TMeta {failwith "tmeta"} +| TVirtual TDot pure_ident + { let nm = ("virtual",P.id2name $3) in + Iteration.parsed_virtual_identifiers := + Common.union_set [snd nm] + !Iteration.parsed_virtual_identifiers; + try Ast.SeedString (List.assoc (snd nm) !Flag.defined_virtual_env) + with Not_found -> Ast.SeedId nm } | TRuleName TDot pure_ident { let nm = ($1,P.id2name $3) in P.check_meta(Ast.MetaIdDecl(Ast.NONE,nm)); @@ -1505,7 +1737,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) @@ -1662,11 +1901,17 @@ not_pos: (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)) } @@ -1678,26 +1923,45 @@ func_ident: pure_ident ident: pure_ident { Ast0.wrap(Ast0.Id(P.id2mcode $1)) } | TMetaId - { let (nm,constraints,pure,clt) = $1 in - Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) } + { let (nm,constraints,seed,pure,clt) = $1 in + Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,seed,pure)) } + +mident: pure_ident + { Ast0.wrap(Ast0.Id(P.id2mcode $1)) } + | TMeta { tmeta_to_ident $1 } + | TMetaId + { let (nm,constraints,seed,pure,clt) = $1 in + Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,seed,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)) } | TMetaDeclarer { let (nm,constraints,pure,clt) = $1 in - Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) } + Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,Ast.NoVal,pure)) } iter_ident: TIteratorId { Ast0.wrap(Ast0.Id(P.id2mcode $1)) } | TMetaIterator { let (nm,constraints,pure,clt) = $1 in - Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) } + Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,Ast.NoVal,pure)) } 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)) } @@ -1705,21 +1969,12 @@ 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 } @@ -1733,14 +1988,49 @@ one_dec(decl): | 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 } /* ---------------------------------------------------------------------- */ @@ -1785,7 +2075,7 @@ when_body_sequence. /* doesn't allow only ... */ minus_start: - fundecl { [Ast0.wrap(Ast0.DECL($1))] } + fundecl { [Ast0.wrap(Ast0.OTHER($1))] } | ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] } | top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] } | toplevel_seq_startne(toplevel_after_dots_init) @@ -1825,7 +2115,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 */ @@ -1838,7 +2133,7 @@ plus_start: { (Ast0.wrap(Ast0.OTHER($1)))::$2 } | expr plus_after_exp { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 } -| fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 } +| fundecl plus_after_stm { Ast0.wrap(Ast0.OTHER($1))::$2 } | decl_statement_expr plus_after_stm { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 } @@ -1851,14 +2146,14 @@ plus_after_dots: | TNothing plus_after_exp {$2} | expr plus_after_exp { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 } -| fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 } +| fundecl plus_after_stm { Ast0.wrap(Ast0.OTHER($1))::$2 } | decl_statement_expr plus_after_stm { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 } plus_after_stm: /* empty */ {[]} | stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 } -| fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 } +| fundecl plus_after_stm { Ast0.wrap(Ast0.OTHER($1))::$2 } | decl_statement plus_after_stm { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 } @@ -1924,23 +2219,9 @@ 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 @@ -1953,21 +2234,13 @@ aexpr: | 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))) } /****************************************************************************/ @@ -2052,26 +2325,27 @@ never_used: TPragma { () } | TScriptData { () } script_meta_main: - py=pure_ident script_name_decl - { let (nm,mv) = $2 in - ((Some (P.id2name py), None), nm, mv) } - | TOPar TUnderscore TComma ast=pure_ident TCPar script_name_decl - { let (nm,mv) = $6 in - ((None, Some (P.id2name ast)), nm, mv) } - | TOPar str=pure_ident TComma TUnderscore TCPar script_name_decl - { let (nm,mv) = $6 in - ((Some (P.id2name str), None), nm, mv) } - | TOPar str=pure_ident TComma ast=pure_ident TCPar script_name_decl - { let (nm,mv) = $6 in - ((Some (P.id2name str), Some (P.id2name ast)), nm, mv) } + 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: - TShOp TRuleName TDot cocci=pure_ident TMPtVirg + TShLOp TRuleName TDot cocci=pure_ident { let nm = P.id2name cocci in let mv = Parse_aux.lookup $2 nm in (($2, nm), mv) } - | TShOp TVirtual TDot cocci=pure_ident TMPtVirg + | 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) } + (name,mv) }