X-Git-Url: https://git.hcoop.net/bpt/coccinelle.git/blobdiff_plain/113803cf8147c1b5332cc7d9ac43febcc197e4f0..3a31414346dd7d7e8baa4cb8b804a2d5e1797962:/parsing_cocci/parser_cocci_menhir.mly diff --git a/parsing_cocci/parser_cocci_menhir.mly b/parsing_cocci/parser_cocci_menhir.mly index 09fb8ad..f0b6832 100644 --- a/parsing_cocci/parser_cocci_menhir.mly +++ b/parsing_cocci/parser_cocci_menhir.mly @@ -1,23 +1,25 @@ /* -* Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen -* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller -* This file is part of Coccinelle. -* -* Coccinelle is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, according to version 2 of the License. -* -* Coccinelle is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with Coccinelle. If not, see . -* -* The authors reserve the right to distribute this or future versions of -* Coccinelle under other licenses. -*/ + * Copyright 2010, INRIA, University of Copenhagen + * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix + * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen + * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix + * This file is part of Coccinelle. + * + * Coccinelle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, according to version 2 of the License. + * + * Coccinelle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Coccinelle. If not, see . + * + * The authors reserve the right to distribute this or future versions of + * Coccinelle under other licenses. + */ %{ @@ -38,15 +40,16 @@ 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 %token TUsing TDisable TExtends TDepends TOn TEver TNever TExists TForall -%token TScript TReverse TNothing +%token TScript TInitialize TFinalize TNothing TVirtual %token TRuleName %token Tchar Tshort Tint Tdouble Tfloat Tlong +%token Tsize_t Tssize_t Tptrdiff_t %token Tvoid Tstruct Tunion Tenum %token Tunsigned Tsigned @@ -57,15 +60,16 @@ module P = Parse_aux %token TIf TElse TWhile TFor TDo TSwitch TCase TDefault TReturn %token TBreak TContinue TGoto TSizeof TFunDecl %token TIdent TTypeId TDeclarerId TIteratorId +%token TPragma -%token TMetaId TMetaFunc TMetaLocalFunc -%token TMetaIterator TMetaDeclarer -%token TMetaErr -%token TMetaParam TMetaStm TMetaStmList TMetaType -%token TMetaInit -%token TMetaParamList TMetaExpList -%token TMetaExp TMetaIdExp TMetaLocalIdExp TMetaConst -%token TMetaPos +%token TMetaId TMetaFunc TMetaLocalFunc +%token TMetaIterator TMetaDeclarer +%token TMetaErr +%token TMetaParam TMetaStm TMetaStmList TMetaType +%token TMetaInit TMetaDecl TMetaField +%token TMetaParamList TMetaExpList +%token TMetaExp TMetaIdExp TMetaLocalIdExp TMetaConst +%token TMetaPos %token TArob TArobArob TPArob %token TScriptData @@ -76,10 +80,10 @@ module P = Parse_aux %token TWhy TDotDot TBang TOPar TOPar0 %token TMid0 TCPar TCPar0 -%token TPragma TPathIsoFile +%token TPathIsoFile %token TIncludeL TIncludeNL -%token TDefine -%token TDefineParam +%token TDefine TUndef +%token TDefineParam %token TMinusFile TPlusFile %token TInc TDec @@ -91,9 +95,9 @@ module P = Parse_aux %token TOr %token TXor %token TAnd -%token TEqEq TNotEq +%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 @@ -103,12 +107,14 @@ module P = Parse_aux %token TPtrOp -%token TMPtVirg +%token TMPtVirg TCppConcatOp %token TEq TDot TComma TPtVirg %token TAssign %token TIso TRightIso TIsoExpression TIsoStatement TIsoDeclaration TIsoType -%token TIsoTopLevel TIsoArgExpression TIsoTestExpression +%token TIsoTopLevel TIsoArgExpression TIsoTestExpression TIsoToTestExpression + +%token TUnderscore %token TInvalid @@ -123,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 */ @@ -143,7 +149,7 @@ module P = Parse_aux %type plus_exp_main %start include_main -%type <(string,string) Common.either list> include_main +%type include_main %start iso_rule_name %type @@ -156,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 @@ -205,8 +211,12 @@ 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 + { P.make_final_script_rule_name_result lang d } extends: /* empty */ { () } @@ -238,7 +248,6 @@ disable: exists: TExists { Ast.Exists } | TForall { Ast.Forall } -| TReverse TForall { Ast.ReverseForall } | { Ast.Undetermined } is_expression: // for more flexible parsing of top level expressions @@ -250,27 +259,53 @@ include_main: | list(incl) TArobArob { $1 } incl: - TUsing TString { Common.Left(P.id2name $2) } -| TUsing TPathIsoFile { Common.Right $2 } + TIncludeL { let (x,_) = $1 in Data.Include(x) } +| TUsing TString { Data.Iso(Common.Left(P.id2name $2)) } +| 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 []) + names; + Data.Virt(names) } metadec: ar=arity ispure=pure kindfn=metakind ids=comma_list(pure_ident_or_meta_ident) TMPtVirg { P.create_metadec ar ispure kindfn ids } +| kindfn=metakind_fresh ids=comma_list(pure_ident_or_meta_ident_with_seed) + TMPtVirg + { P.create_fresh_metadec kindfn ids } +| ar=arity ispure=pure + kindfn=metakind_atomic_maybe_virt + ids= + comma_list(pure_ident_or_meta_ident_with_idconstraint_virt(re_or_not_eqid)) + TMPtVirg + { let (normal,virt) = Common.partition_either (fun x -> x) ids in + let (idfn,virtfn) = kindfn in + function cr -> + (P.create_metadec_with_constraints ar ispure idfn normal cr) @ + (P.create_metadec_virt ar ispure virtfn virt cr) } | ar=arity ispure=pure kindfn=metakind_atomic - ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_eq)) TMPtVirg - { P.create_metadec_ne ar ispure kindfn ids } + ids=comma_list(pure_ident_or_meta_ident_with_idconstraint(re_or_not_eqid)) + TMPtVirg + { P.create_metadec_with_constraints ar ispure kindfn ids } | ar=arity ispure=pure kindfn=metakind_atomic_expi - ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_eqe)) TMPtVirg - { P.create_metadec_ne ar ispure kindfn ids } + ids=comma_list(pure_ident_or_meta_ident_with_econstraint(re_or_not_eqe_or_sub)) + TMPtVirg + { P.create_metadec_with_constraints ar ispure kindfn ids } | ar=arity ispure=pure kindfn=metakind_atomic_expe - ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_ceq)) TMPtVirg - { P.create_metadec_ne ar ispure kindfn ids } + ids=comma_list(pure_ident_or_meta_ident_with_econstraint(not_ceq_or_sub)) + TMPtVirg + { P.create_metadec_with_constraints ar ispure kindfn ids } | ar=arity TPosition a=option(TPosAny) - ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_pos)) TMPtVirg + ids=comma_list(pure_ident_or_meta_ident_with_x_eq(not_pos)) TMPtVirg (* pb: position variables can't be inherited from normal rules, and then there is no way to inherit from a generated rule, so there is no point to have a position variable *) @@ -280,43 +315,50 @@ metadec: let tok = check_meta(Ast.MetaPosDecl(arity,name)) in let any = match a with None -> Ast.PER | Some _ -> Ast.ALL in !Data.add_pos_meta name constraints any; tok in - P.create_metadec_ne ar false kindfn ids } + 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 } -%inline metakind: +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 - { (fun arity name pure check_meta -> - let tok = check_meta(Ast.MetaFreshIdDecl(arity,name)) in - !Data.add_id_meta name [] pure; tok) } -| TParameter + { (fun name check_meta seed -> + let tok = check_meta(Ast.MetaFreshIdDecl(name,seed)) in + !Data.add_fresh_id_meta name; tok) } + +/* metavariable kinds with no constraints, etc */ +%inline metakind: + TParameter { (fun arity name pure check_meta -> let tok = check_meta(Ast.MetaParamDecl(arity,name)) in !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 @@ -329,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 @@ -349,13 +399,27 @@ metadec: then (!Data.add_iterator_name name; []) else raise (Semantic_cocci.Semantic "bad iterator")) } +%inline metakind_atomic_maybe_virt: + TIdentifier + { + let idfn arity name pure check_meta constraints = + let tok = check_meta(Ast.MetaIdDecl(arity,name)) in + !Data.add_id_meta name constraints pure; tok in + let virtfn arity name pure check_meta virtual_env = + try + 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 + (idfn,virtfn) } %inline metakind_atomic: - TIdentifier - { (fun arity name pure check_meta constraints -> - let tok = check_meta(Ast.MetaIdDecl(arity,name)) in - !Data.add_id_meta name constraints pure; tok) } -| TFunction + TFunction { (fun arity name pure check_meta constraints -> let tok = check_meta(Ast.MetaFuncDecl(arity,name)) in !Data.add_func_meta name constraints pure; tok) } @@ -397,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) @@ -412,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 -> @@ -420,28 +490,34 @@ metadec: | vl=meta_exp_type // no error if use $1 but doesn't type check { (fun arity name pure check_meta constraints -> let ty = Some vl in - List.iter - (function c -> - match Ast0.unwrap c with - Ast0.Constant(_) -> - if not - (List.exists - (function - Type_cocci.BaseType(Type_cocci.IntType) -> true - | Type_cocci.BaseType(Type_cocci.ShortType) -> true - | Type_cocci.BaseType(Type_cocci.LongType) -> true - | _ -> false) - vl) - then failwith "metavariable with int constraint must be an int" - | _ -> ()) - constraints; + (match constraints with + Ast0.NotExpCstrt constraints -> + List.iter + (function c -> + match Ast0.unwrap c with + Ast0.Constant(_) -> + if not + (List.exists + (function + Type_cocci.BaseType(Type_cocci.IntType) -> true + | Type_cocci.BaseType(Type_cocci.ShortType) -> true + | Type_cocci.BaseType(Type_cocci.LongType) -> true + | _ -> false) + vl) + then + failwith "metavariable with int constraint must be an int" + | _ -> ()) + constraints + | _ -> ()); let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in - !Data.add_exp_meta ty name constraints pure; tok) } - + !Data.add_exp_meta ty name constraints pure; tok) + } meta_exp_type: - t=ctype + 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) @@ -452,68 +528,117 @@ arity: TBang0 { Ast.UNIQUE } | TPlus0 { Ast.MULTI } | /* empty */ { Ast.NONE } -generic_ctype_full: - q=ctype_qualif_opt ty=Tchar - { q (Ast0.wrap(Ast0.BaseType(Ast.CharType,[P.clt2mcode "char" ty]))) } - | q=ctype_qualif_opt ty=Tshort - { q (Ast0.wrap(Ast0.BaseType(Ast.ShortType,[P.clt2mcode "short" ty])))} - | q=ctype_qualif_opt ty=Tint - { q (Ast0.wrap(Ast0.BaseType(Ast.IntType,[P.clt2mcode "int" ty]))) } - | t=Tdouble - { Ast0.wrap(Ast0.BaseType(Ast.DoubleType,[P.clt2mcode "double" t])) } - | t=Tfloat - { Ast0.wrap(Ast0.BaseType(Ast.FloatType,[P.clt2mcode "float" t])) } - | q=ctype_qualif_opt ty=Tlong - { q (Ast0.wrap(Ast0.BaseType(Ast.LongType,[P.clt2mcode "long" ty]))) } - | q=ctype_qualif_opt ty=Tlong ty1=Tlong - { q (Ast0.wrap - (Ast0.BaseType - (Ast.LongLongType, - [P.clt2mcode "long" ty;P.clt2mcode "long" ty1]))) } - | s=Tenum i=ident - { Ast0.wrap(Ast0.EnumName(P.clt2mcode "enum" s, i)) } - | s=struct_or_union i=ident - { Ast0.wrap(Ast0.StructUnionName(s, Some i)) } - | s=struct_or_union i=ioption(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.StructUnionDef(Ast0.wrap(Ast0.StructUnionName(s, i)), - P.clt2mcode "{" l, - d, P.clt2mcode "}" r)) } - | s=TMetaType l=TOBrace d=struct_decl_list r=TCBrace - { let (nm,pure,clt) = s in - let ty = - Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) in - Ast0.wrap - (Ast0.StructUnionDef(ty,P.clt2mcode "{" l,d,P.clt2mcode "}" r)) } - | r=TRuleName TDot p=TIdent - { let nm = (r,P.id2name p) in - (* this is only possible when we are in a metavar decl. Otherwise, - it will be represented already as a MetaType *) - let _ = P.check_meta(Ast.MetaTypeDecl(Ast.NONE,nm)) in - Ast0.wrap(Ast0.MetaType(P.clt2mcode nm (P.id2clt p), - Ast0.Impure (*will be ignored*))) } - | p=TTypeId - { Ast0.wrap(Ast0.TypeName(P.id2mcode p)) } - | q=ctype_qualif_opt p=TMetaType - { let (nm,pure,clt) = p in - q (Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure))) } - -generic_ctype: - q=ctype_qualif { q None } - | generic_ctype_full { $1 } +/* ---------------------------------------------------------------------- */ + +%inline +signable_types: + ty=Tchar + { Ast0.wrap(Ast0.BaseType(Ast.CharType,[P.clt2mcode "char" ty])) } +| ty=Tshort + { Ast0.wrap(Ast0.BaseType(Ast.ShortType,[P.clt2mcode "short" ty])) } +| ty=Tint + { Ast0.wrap(Ast0.BaseType(Ast.IntType,[P.clt2mcode "int" ty])) } +| p=TMetaType + { let (nm,pure,clt) = p in + Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) } +| r=TRuleName TDot p=TIdent + { let nm = (r,P.id2name p) in + (* this is only possible when we are in a metavar decl. Otherwise, + it will be represented already as a MetaType *) + let _ = P.check_meta(Ast.MetaTypeDecl(Ast.NONE,nm)) in + Ast0.wrap(Ast0.MetaType(P.clt2mcode nm (P.id2clt p), + Ast0.Impure (*will be ignored*))) } +| ty=Tlong + { Ast0.wrap(Ast0.BaseType(Ast.LongType,[P.clt2mcode "long" ty])) } +| ty1=Tlong ty2=Tlong + { Ast0.wrap + (Ast0.BaseType + (Ast.LongLongType, + [P.clt2mcode "long" ty1;P.clt2mcode "long" ty2])) } + +%inline +non_signable_types: + ty=Tvoid + { Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" ty])) } +| ty=Tdouble + { 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 + { (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) + 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.StructUnionDef(Ast0.wrap(Ast0.StructUnionName(s, i)), + P.clt2mcode "{" l, + d, P.clt2mcode "}" r)) } +| s=TMetaType l=TOBrace d=struct_decl_list r=TCBrace + { let (nm,pure,clt) = s in + let ty = Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) in + Ast0.wrap(Ast0.StructUnionDef(ty,P.clt2mcode "{" l,d,P.clt2mcode "}" r)) } +| p=TTypeId + { Ast0.wrap(Ast0.TypeName(P.id2mcode p)) } + +%inline +all_basic_types: + r=Tsigned ty=signable_types + { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,Some ty)) } +| r=Tunsigned ty=signable_types + { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,Some ty)) } +| ty=signable_types { ty } +| ty=non_signable_types { ty } + +ctype: + cv=ioption(const_vol) ty=all_basic_types m=list(TMul) + { P.pointerify (P.make_cv cv ty) m } +| r=Tsigned + { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,None)) } +| r=Tunsigned + { Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,None)) } +| lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0 + { let (mids,code) = t in + Ast0.wrap + (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) } + +/* 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 + { let (mids,code) = t in + Ast0.wrap + (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) } + +/* ---------------------------------------------------------------------- */ struct_or_union: s=Tstruct { P.clt2mcode Ast.Struct s } | 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))] } - | t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar + 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 let t = @@ -521,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)) } @@ -533,57 +658,48 @@ 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 */ { [] } | struct_decl struct_decl_list_start { $1@$2 } | struct_decl { $1 } -ctype: - cv=ioption(const_vol) ty=generic_ctype m=list(TMul) - { P.pointerify (P.make_cv cv ty) m } - | cv=ioption(const_vol) t=Tvoid m=nonempty_list(TMul) - { let ty = - Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" t])) in - P.pointerify (P.make_cv cv ty) m } - | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0 - /* more hacks */ - { let (mids,code) = t in - Ast0.wrap - (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) } - -ctype_full: - cv=ioption(const_vol) ty=generic_ctype_full m=list(TMul) - { P.pointerify (P.make_cv cv ty) m } - | cv=ioption(const_vol) t=Tvoid m=nonempty_list(TMul) - { let ty = - Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" t])) in - P.pointerify (P.make_cv cv ty) m } - | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0 - /* more hacks */ - { let (mids,code) = t in - Ast0.wrap - (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) } +/* ---------------------------------------------------------------------- */ +/* very restricted what kinds of expressions can appear in an enum decl */ -fn_ctype: // allows metavariables - ty=generic_ctype m=list(TMul) { P.pointerify ty m } - | t=Tvoid m=list(TMul) - { P.pointerify - (Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" t]))) - m } +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)) } -%inline ctype_qualif: - r=Tunsigned - { function x -> Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Unsigned r,x)) } -| r=Tsigned - { function x -> Ast0.wrap(Ast0.Signed(P.clt2mcode Ast.Signed r,x)) } +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)) } -%inline ctype_qualif_opt: - s=ctype_qualif { function x -> s (Some x) } -| /* empty */ { function x -> x } +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))) } /*****************************************************************************/ @@ -593,30 +709,30 @@ declarations, statements, and expressions for the subterms */ minus_body: f=loption(filespec) b=loption(minus_start) - ew=loption(error_words) - { match f@b@ew with + /*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 } plus_body: f=loption(filespec) b=loption(plus_start) - ew=loption(error_words) - { Top_level.top_level (f@b@ew) } + /*ew=loption(error_words)*/ + { Top_level.top_level (f@b(*@ew*)) } minus_exp_body: f=loption(filespec) b=top_eexpr - ew=loption(error_words) - { match f@[b]@ew with + /*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 } plus_exp_body: f=loption(filespec) b=top_eexpr - ew=loption(error_words) - { Top_level.top_level (f@[b]@ew) } + /*ew=loption(error_words)*/ + { Top_level.top_level (f@[b](*@ew*)) } filespec: TMinusFile TPlusFile @@ -627,7 +743,8 @@ filespec: includes: TIncludeL { Ast0.wrap - (Ast0.Include(P.clt2mcode "#include" (P.drop_aft (P.id2clt $1)), + (Ast0.Include(P.clt2mcode "#include" + (P.drop_pos (P.drop_aft (P.id2clt $1))), let (arity,ln,lln,offset,col,strbef,straft,pos) = P.id2clt $1 in let clt = @@ -637,7 +754,8 @@ includes: (P.drop_bef clt))) } | TIncludeNL { Ast0.wrap - (Ast0.Include(P.clt2mcode "#include" (P.drop_aft (P.id2clt $1)), + (Ast0.Include(P.clt2mcode "#include" + (P.drop_pos (P.drop_aft (P.id2clt $1))), let (arity,ln,lln,offset,col,strbef,straft,pos) = P.id2clt $1 in let clt = @@ -645,6 +763,22 @@ 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 { let ty = Ast0.wrap(Ast0.TopExp(Ast0.wrap(Ast0.TypeExp(t)))) in d (Ast0.wrap(Ast0.DOTS([ty]))) } @@ -678,10 +812,12 @@ defineop: Ast0.wrap Ast0.NoParams, body)) } | TDefineParam define_param_list_option TCPar - { let (clt,ident,parenoff) = $1 in + { let (clt,ident,parenoff,parencol) = $1 in + (* 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,0,[],[],Ast0.NoMetaPos) in + P.clt2mcode "(" + (arity,line,lline,parenoff,parencol,[],[],Ast0.NoMetaPos) in function body -> Ast0.wrap (Ast0.Define @@ -699,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))) } /*****************************************************************************/ @@ -739,23 +857,13 @@ funproto: (Ast0.FunctionType(Some t, P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)), id, P.clt2mcode ";" pt)) } -| s=ioption(storage) t=Tvoid - id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg - { let t = Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" t])) in - Ast0.wrap - (Ast0.UnInit - (s, - Ast0.wrap - (Ast0.FunctionType(Some t, - P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)), - id, P.clt2mcode ";" pt)) } - fundecl: f=fninfo TFunDecl i=func_ident lp=TOPar d=decl_list(decl) rp=TCPar lb=TOBrace b=fun_start rb=TCBrace - { Ast0.wrap(Ast0.FunDecl((Ast0.default_info(),Ast0.context_befaft()), + { P.verify_parameter_declarations (Ast0.undots d); + Ast0.wrap(Ast0.FunDecl((Ast0.default_info(),Ast0.context_befaft()), f, i, P.clt2mcode "(" lp, d, P.clt2mcode ")" rp, @@ -770,7 +878,7 @@ fninfo: List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in raise (Semantic_cocci.Semantic "duplicate storage") with Not_found -> (Ast0.FStorage($1))::$2 } - | t=fn_ctype r=fninfo_nt { (Ast0.FType(t))::r } + | t=ctype r=fninfo_nt { (Ast0.FType(t))::r } | Tinline fninfo { try let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in @@ -809,7 +917,8 @@ storage: decl: t=ctype i=ident { Ast0.wrap(Ast0.Param(t, Some i)) } - | t=fn_ctype lp=TOPar s=TMul i=ident rp=TCPar + | t=ctype { (*verify in FunDecl*) Ast0.wrap(Ast0.Param(t, None)) } + | t=ctype lp=TOPar s=TMul i=ident rp=TCPar lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar { let fnptr = Ast0.wrap @@ -817,18 +926,13 @@ decl: t=ctype i=ident (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp, P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in Ast0.wrap(Ast0.Param(fnptr, Some i)) } - | t=Tvoid - { let ty = - Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" t])) in - Ast0.wrap(Ast0.VoidParam(ty)) } | TMetaParam { let (nm,pure,clt) = $1 in Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) } name_opt_decl: decl { $1 } - | t=ctype { Ast0.wrap(Ast0.Param(t, None)) } - | t=fn_ctype lp=TOPar s=TMul rp=TCPar + | t=ctype lp=TOPar s=TMul rp=TCPar lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar { let fnptr = Ast0.wrap @@ -862,8 +966,8 @@ statement: { P.doloop $1 $2 $3 $4 $5 $6 $7 } | iter_ident TOPar eexpr_list_option TCPar single_statement { P.iterator $1 $2 $3 $4 $5 } -| TSwitch TOPar eexpr TCPar TOBrace list(case_line) TCBrace - { P.switch $1 $2 $3 $4 $5 $6 $7 } +| TSwitch TOPar eexpr TCPar TOBrace list(decl_var) list(case_line) TCBrace + { P.switch $1 $2 $3 $4 $5 (List.concat $6) $7 $8 } | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 } | TReturn TPtVirg { P.ret $1 $2 } | TBreak TPtVirg { P.break $1 $2 } @@ -895,7 +999,7 @@ stm_dots: { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." a, b, P.clt2mcode "...+>" c, List.concat w, true)) } -whenppdecs: w=whens(when_start,rule_elem_statement) +whenppdecs: w=whens(when_start,rule_elem_statement,any_strict) { w } /* a statement that fits into a single rule_elem. should nests be included? @@ -929,9 +1033,14 @@ single_statement: case_line: TDefault TDotDot fun_start - { Ast0.wrap(Ast0.Default(P.clt2mcode "default" $1,P.clt2mcode ":" $2,$3)) } + { Ast0.wrap + (Ast0.Default(P.clt2mcode "default" $1,P.clt2mcode ":" $2,$3)) } | TCase eexpr TDotDot fun_start { Ast0.wrap(Ast0.Case(P.clt2mcode "case" $1,$2,P.clt2mcode ":" $3,$4)) } +/* | lp=TOPar0 t=midzero_list(case_line,case_line) rp=TCPar0 + { let (mids,code) = ([],[t]) in + Ast0.wrap + (Ast0.DisjCase(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) } */ /* In the following, an identifier as a type is not fully supported. Indeed, the language is ambiguous: what is foo * bar; */ @@ -940,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) -> @@ -967,7 +1077,7 @@ decl_var: P.clt2mcode ";" pv))] } /* function pointer type */ | s=ioption(storage) - t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar + 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 @@ -981,7 +1091,7 @@ decl_var: { [Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3, P.clt2mcode ")" $4,P.clt2mcode ";" $5))] } | s=ioption(storage) - t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar + t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar q=TEq e=initialize pv=TPtVirg { let (id,fn) = d in @@ -991,13 +1101,17 @@ decl_var: (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1, P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]} - | s=Ttypedef t=ctype_full id=typedef_ident pv=TPtVirg + | s=Ttypedef t=typedef_ctype id=comma_list(typedef_ident) pv=TPtVirg { let s = P.clt2mcode "typedef" s in - [Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv))] } + List.map + (function id -> + Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv))) + id } 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)) } @@ -1020,7 +1134,7 @@ one_decl_var: P.clt2mcode ";" pv)) } /* function pointer type */ | s=ioption(storage) - t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar + 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 @@ -1034,7 +1148,7 @@ one_decl_var: { Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3, P.clt2mcode ")" $4,P.clt2mcode ";" $5)) } | s=ioption(storage) - t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar + t=ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar q=TEq e=initialize pv=TPtVirg { let (id,fn) = d in @@ -1063,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)) } @@ -1077,51 +1192,30 @@ 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 */ -designator: - | TDot ident - { Ast0.DesignatorField (P.clt2mcode "." $1,$2) } - | TOCro eexpr TCCro +designator: + | TDot ident + { Ast0.DesignatorField (P.clt2mcode "." $1,$2) } + | TOCro eexpr TCCro { Ast0.DesignatorIndex (P.clt2mcode "[" $1,$2,P.clt2mcode "]" $3) } - | TOCro eexpr TEllipsis eexpr TCCro + | TOCro eexpr TEllipsis eexpr TCCro { Ast0.DesignatorRange (P.clt2mcode "[" $1,$2,P.clt2mcode "..." $3, $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 } -| 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 } -| i=initialize2 c=TComma r=comma_initializers(dotter) - { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))]):: - r } - -comma_initializers2(dotter): - /* empty */ { [] } -| 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: @@ -1184,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 } @@ -1245,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) @@ -1286,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 unary_expr(r,pe) + | 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, @@ -1384,35 +1534,156 @@ no_dot_start_end(grammar,dotter): pure_ident: TIdent { $1 } +pure_ident_kwd: + | TIdentifier { "identifier" } + | TExpression { "expression" } + | TStatement { "statement" } + | TFunction { "function" } + | TLocal { "local" } + | TType { "type" } + | TParameter { "parameter" } + | TIdExpression { "idexpression" } + | TInitialiser { "initialiser" } + | Tlist { "list" } + | TFresh { "fresh" } + | TConstant { "constant" } + | TError { "error" } + | TWords { "words" } + | TPure { "pure" } + | TContext { "context" } + | TGenerated { "generated" } + | TTypedef { "typedef" } + | TDeclarer { "declarer" } + | TIterator { "iterator" } + | TName { "name" } + | TPosition { "position" } + meta_ident: - TRuleName TDot pure_ident { (Some $1,P.id2name $3) } + TRuleName TDot pure_ident { (Some $1,P.id2name $3) } + | TRuleName TDot pure_ident_kwd { (Some $1,$3) } pure_ident_or_meta_ident: pure_ident { (None,P.id2name $1) } + | pure_ident_kwd { (None,$1) } | meta_ident { $1 } - | Tlist { (None,"list") } - | TError { (None,"error") } - | TType { (None,"type") } - | TName { (None,"name") } -pure_ident_or_meta_ident_with_not_eq(not_eq): - i=pure_ident_or_meta_ident l=loption(not_eq) { (i,l) } +pure_ident_or_meta_ident_with_seed: + pure_ident_or_meta_ident { ($1,Ast.NoVal) } + | pure_ident_or_meta_ident TEq + separated_nonempty_list(TCppConcatOp,seed_elem) + { match $3 with + [Ast.SeedString s] -> ($1,Ast.StringSeed s) + | _ -> ($1,Ast.ListSeed $3) } + +seed_elem: + TString { let (x,_) = $1 in Ast.SeedString x } +| TMetaId { let (x,_,_,_) = $1 in Ast.SeedId x } +| TRuleName TDot pure_ident + { let nm = ($1,P.id2name $3) in + P.check_meta(Ast.MetaIdDecl(Ast.NONE,nm)); + Ast.SeedId nm } + +pure_ident_or_meta_ident_with_x_eq(x_eq): + i=pure_ident_or_meta_ident l=loption(x_eq) + { + (i, l) + } + +pure_ident_or_meta_ident_with_econstraint(x_eq): + i=pure_ident_or_meta_ident optc=option(x_eq) + { + match optc with + None -> (i, Ast0.NoConstraint) + | Some c -> (i, c) + } + +pure_ident_or_meta_ident_with_idconstraint_virt(constraint_type): + i=pure_ident_or_meta_ident c=option(constraint_type) + { + Common.Left + (match c with + None -> (i, Ast.IdNoConstraint) + | Some constraint_ -> (i,constraint_)) + } +| 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) + { + match c with + None -> (i, Ast.IdNoConstraint) + | Some constraint_ -> (i,constraint_) + } + +re_or_not_eqid: + re=regexp_eqid {Ast.IdRegExpConstraint re} + | ne=not_eqid {ne} + +regexp_eqid: + TTildeEq re=TString + { (if !Data.in_iso + then failwith "constraints not allowed in iso file"); + (if !Data.in_generating + then failwith "constraints not allowed in a generated rule file"); + let (s,_) = re in Ast.IdRegExp (s,Str.regexp s) + } + | TTildeExclEq re=TString + { (if !Data.in_iso + then failwith "constraints not allowed in iso file"); + (if !Data.in_generating + then failwith "constraints not allowed in a generated rule file"); + let (s,_) = re in Ast.IdNotRegExp (s,Str.regexp s) + } -not_eq: - TNotEq i=pure_ident +not_eqid: + TNotEq i=pure_ident_or_meta_ident { (if !Data.in_iso then failwith "constraints not allowed in iso file"); (if !Data.in_generating (* pb: constraints not stored with metavars; too lazy to search for them in the pattern *) then failwith "constraints not allowed in a generated rule file"); - [Ast0.wrap(Ast0.Id(P.id2mcode i))] } - | TNotEq TOBrace l=comma_list(pure_ident) TCBrace + (match i with + (Some rn,id) -> + let i = + P.check_inherited_constraint i + (function mv -> Ast.MetaIdDecl(Ast.NONE,mv)) in + Ast.IdNegIdSet([],[i]) + | (None,i) -> Ast.IdNegIdSet([i],[])) } + | TNotEq TOBrace l=comma_list(pure_ident_or_meta_ident) TCBrace { (if !Data.in_iso then failwith "constraints not allowed in iso file"); (if !Data.in_generating then failwith "constraints not allowed in a generated rule file"); - List.map (function i -> Ast0.wrap(Ast0.Id(P.id2mcode i))) l } + let (str,meta) = + List.fold_left + (function (str,meta) -> + function + (Some rn,id) as i -> + let i = + P.check_inherited_constraint i + (function mv -> Ast.MetaIdDecl(Ast.NONE,mv)) in + (str,i::meta) + | (None,i) -> (i::str,meta)) + ([],[]) l in + Ast.IdNegIdSet(str,meta) + } + +re_or_not_eqe_or_sub: + re=regexp_eqid {Ast0.NotIdCstrt re} + | ne=not_eqe {Ast0.NotExpCstrt ne} + | s=sub {Ast0.SubExpCstrt s} + +not_ceq_or_sub: + ceq=not_ceq {Ast0.NotExpCstrt ceq} + | s=sub {Ast0.SubExpCstrt s} not_eqe: TNotEq i=pure_ident @@ -1420,7 +1691,8 @@ not_eqe: then failwith "constraints not allowed in iso file"); (if !Data.in_generating then failwith "constraints not allowed in a generated rule file"); - [Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))] } + [Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))] + } | TNotEq TOBrace l=comma_list(pure_ident) TCBrace { (if !Data.in_iso then failwith "constraints not allowed in iso file"); @@ -1428,8 +1700,9 @@ not_eqe: then failwith "constraints not allowed in a generated rule file"); List.map (function i -> - Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))) - l } + Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))) + l + } not_ceq: TNotEq i=ident_or_const @@ -1445,6 +1718,30 @@ not_ceq: then failwith "constraints not allowed in a generated rule file"); l } +sub: + (* has to be inherited because not clear how to check subterm constraints + in the functorized CTL engine, so need the variable to be bound + already when bind the subterm constrained metavariable *) + TSub i=meta_ident + { (if !Data.in_iso + then failwith "constraints not allowed in iso file"); + (if !Data.in_generating + then failwith "constraints not allowed in a generated rule file"); + let i = + P.check_inherited_constraint i + (function mv -> Ast.MetaExpDecl(Ast.NONE,mv,None)) in + [i] } + | TSub TOBrace l=comma_list(meta_ident) TCBrace + { (if !Data.in_iso + then failwith "constraints not allowed in iso file"); + (if !Data.in_generating + then failwith "constraints not allowed in a generated rule file"); + List.map + (function i -> + P.check_inherited_constraint i + (function mv -> Ast.MetaExpDecl(Ast.NONE,mv,None))) + l} + ident_or_const: i=pure_ident { Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))) } | TInt @@ -1457,25 +1754,19 @@ not_pos: then failwith "constraints not allowed in iso file"); (if !Data.in_generating then failwith "constraints not allowed in a generated rule file"); - match i with - (None,_) -> failwith "constraint must be an inherited variable" - | (Some rule,name) -> - let i = (rule,name) in - P.check_meta(Ast.MetaPosDecl(Ast.NONE,i)); - [i] } + let i = + P.check_inherited_constraint i + (function mv -> Ast.MetaPosDecl(Ast.NONE,mv)) in + [i] } | TNotEq TOBrace l=comma_list(meta_ident) TCBrace { (if !Data.in_iso then failwith "constraints not allowed in iso file"); (if !Data.in_generating then failwith "constraints not allowed in a generated rule file"); List.map - (function - (None,_) -> - failwith "constraint must be an inherited variable" - | (Some rule,name) -> - let i = (rule,name) in - P.check_meta(Ast.MetaPosDecl(Ast.NONE,i)); - i) + (function i -> + P.check_inherited_constraint i + (function mv -> Ast.MetaPosDecl(Ast.NONE,mv))) l } func_ident: pure_ident @@ -1521,47 +1812,80 @@ 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 } /* ---------------------------------------------------------------------- */ -error_words: +/* error words make it complicated to be able to use error as a metavariable +name or a type in a metavariable list; for that we would like to allow TError +as an ident, but that makes conflicts with this rule. To add back error words, +need to find some appropriate delimiter for it, but it has not been used much +so just drop it */ +/*error_words: TError TWords TEq TOCro cl=comma_list(dexpr) TCCro { [Ast0.wrap(Ast0.ERRORWORDS(cl))] } +*/ /* ---------------------------------------------------------------------- */ /* sequences of statements and expressions */ @@ -1634,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 */ @@ -1733,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))) } /****************************************************************************/ @@ -1794,7 +2102,7 @@ edots_when(dotter,when_grammar): d=dotter { (d,None) } | d=dotter TWhen TNotEq w=when_grammar TLineEnd { (d,Some w) } -whens(when_grammar,simple_when_grammar): +whens(when_grammar,simple_when_grammar,any_strict): TWhen TNotEq w=when_grammar TLineEnd { [Ast0.WhenNot w] } | TWhen TEq w=simple_when_grammar TLineEnd { [Ast0.WhenAlways w] } | TWhen comma_list(any_strict) TLineEnd @@ -1814,18 +2122,22 @@ any_strict: *****************************************************************************/ iso_main: - TIsoExpression e1=dexpr el=list(iso(dexpr)) EOF - { P.iso_adjust (function x -> Ast0.ExprTag x) e1 el } -| TIsoArgExpression e1=dexpr el=list(iso(dexpr)) EOF - { P.iso_adjust (function x -> Ast0.ArgExprTag x) e1 el } -| TIsoTestExpression e1=dexpr el=list(iso(dexpr)) EOF - { P.iso_adjust (function x -> Ast0.TestExprTag x) e1 el } + TIsoExpression e1=eexpr el=list(iso(eexpr)) EOF + { let fn x = Ast0.ExprTag x in P.iso_adjust fn fn e1 el } +| TIsoArgExpression e1=eexpr el=list(iso(eexpr)) EOF + { let fn x = Ast0.ArgExprTag x in P.iso_adjust fn fn e1 el } +| TIsoTestExpression e1=eexpr el=list(iso(eexpr)) EOF + { let fn x = Ast0.TestExprTag x in P.iso_adjust fn fn e1 el } +| TIsoToTestExpression e1=eexpr el=list(iso(eexpr)) EOF + { let ffn x = Ast0.ExprTag x in + let fn x = Ast0.TestExprTag x in + P.iso_adjust ffn fn e1 el } | TIsoStatement s1=single_statement sl=list(iso(single_statement)) EOF - { P.iso_adjust (function x -> Ast0.StmtTag x) s1 sl } + { let fn x = Ast0.StmtTag x in P.iso_adjust fn fn s1 sl } | TIsoType t1=ctype tl=list(iso(ctype)) EOF - { P.iso_adjust (function x -> Ast0.TypeCTag x) t1 tl } + { let fn x = Ast0.TypeCTag x in P.iso_adjust fn fn t1 tl } | TIsoTopLevel e1=nest_start el=list(iso(nest_start)) EOF - { P.iso_adjust (function x -> Ast0.DotsStmtTag x) e1 el } + { let fn x = Ast0.DotsStmtTag x in P.iso_adjust fn fn e1 el } | TIsoDeclaration d1=decl_var dl=list(iso(decl_var)) EOF { let check_one = function [x] -> x @@ -1840,7 +2152,7 @@ iso_main: Common.Left x -> Common.Left(check_one x) | Common.Right x -> Common.Right(check_one x)) dl in - P.iso_adjust (function x -> Ast0.DeclTag x) d1 dl } + let fn x = Ast0.DeclTag x in P.iso_adjust fn fn d1 dl } iso(term): TIso t=term { Common.Left t } @@ -1855,5 +2167,28 @@ never_used: TPragma { () } | TPArob TMetaPos { () } | TScriptData { () } -script_meta_main: py=pure_ident TShOp TRuleName TDot cocci=pure_ident TMPtVirg - { (P.id2name py, ($3, P.id2name cocci)) } +script_meta_main: + 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) }