123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344openCommonopenCst_cppmoduleAst=Cst_cppmoduleFlag=Flag_parsing(*****************************************************************************)(* Wrappers *)(*****************************************************************************)letpr2,pr2_once=Common2.mk_pr2_wrappersFlag.verbose_parsingletwarningsv=if!Flag.verbose_parsingthenCommon2.warning("PARSING: "^s)velsevexceptionSemanticofstring*Cst_cpp.tok(*****************************************************************************)(* Parse helpers functions *)(*****************************************************************************)(*-------------------------------------------------------------------------- *)(* Type related *)(*-------------------------------------------------------------------------- *)typeshortLong=Short|Long|LongLong(* note: have a full_info: parse_info list; to remember ordering
* between storage, qualifier, type? well this info is already in
* the Ast_c.info, just have to sort them to get good order
*)typedecl={storageD:storage;typeD:(signoption*shortLongoption*typeCbisoption)wrap;qualifD:typeQualifier;inlineD:boolwrap;}letnullDecl={storageD=NoSto;typeD=(None,None,None),noii;qualifD=Ast.nQ;inlineD=false,noii;}letaddStorageDxdecl=matchdeclwith|{storageD=NoSto;_}->{declwithstorageD=x}|{storageD=(StoTypedefii|Sto(_,ii))asy;_}->ifx=ythendecl|>warning"duplicate storage classes"elseraise(Semantic("multiple storage classes",ii))letaddInlineDiidecl=matchdeclwith|{inlineD=(false,[]);_}->{declwithinlineD=(true,[ii])}|{inlineD=(true,_ii2);_}->decl|>warning"duplicate inline"|_->raiseImpossibleletaddTypeDtydecl=matchty,declwith|(Left3Signed,_ii),{typeD=((SomeSigned,_b,_c),_ii2);_}->decl|>warning"duplicate 'signed'"|(Left3UnSigned,_ii),{typeD=((SomeUnSigned,_b,_c),_ii2);_}->decl|>warning"duplicate 'unsigned'"|(Left3_,ii),{typeD=((Some_,_b,_c),_ii2);_}->raise(Semantic("both signed and unsigned specified",List.hdii))|(Left3x,ii),{typeD=((None,b,c),ii2);_}->{declwithtypeD=(Somex,b,c),ii@ii2}|(Middle3Short,_ii),{typeD=((_a,SomeShort,_c),_ii2);_}->decl|>warning"duplicate 'short'"(* gccext: long long allowed *)|(Middle3Long,ii),{typeD=((a,SomeLong,c),ii2);_}->{declwithtypeD=(a,SomeLongLong,c),ii@ii2}|(Middle3Long,_ii),{typeD=((_a,SomeLongLong,_c),_ii2);_}->decl|>warning"triplicate 'long'"|(Middle3_,ii),{typeD=((_a,Some_,_c),_ii2);_}->raise(Semantic("both long and short specified",List.hdii))|(Middle3x,ii),{typeD=((a,None,c),ii2);_}->{declwithtypeD=(a,Somex,c),ii@ii2}|(Right3_t,ii),{typeD=((_a,_b,Some_),_ii2);_}->raise(Semantic("two or more data types",List.hdii))|(Right3t,ii),{typeD=((a,b,None),ii2);_}->{declwithtypeD=(a,b,Somet),ii@ii2}letaddQualiftq1tq2=matchtq1,tq2with|{const=Some_;_},{const=Some_;_}->tq2|>warning"duplicate 'const'"|{volatile=Some_;_},{volatile=Some_;_}->tq2|>warning"duplicate 'volatile'"|{const=Somex;_},_->{tq2withconst=Somex}|{volatile=Somex;_},_->{tq2withvolatile=Somex}|_->Common2.internal_error"there is no noconst or novolatile keyword"letaddQualifDququ2={qu2withqualifD=addQualifququ2.qualifD}(*-------------------------------------------------------------------------- *)(* Declaration/Function related *)(*-------------------------------------------------------------------------- *)(* stdC: type section, basic integer types (and ritchie)
* To understand the code, just look at the result (right part of the PM)
* and go back.
*)lettype_and_storage_from_decl{storageD=st;qualifD=qu;typeD=(ty,iit);inlineD=(inline,iinl);}=(qu,(matchtywith|(None,None,None)->(* mine (originally default to int, but this looks like bad style) *)letdecl={v_namei=None;v_type=qu,(BaseTypeVoid,iit);v_storage=st}inraise(Semantic("no type (could default to 'int')",List.hd(Lib_parsing_cpp.ii_of_any(OneDecldecl))))|(None,None,Somet)->(t,iit)|(Somesign,None,(None|Some(BaseType(IntType(Si(_,CInt))))))->BaseType(IntType(Si(sign,CInt))),iit|((None|SomeSigned),Somex,(None|Some(BaseType(IntType(Si(_,CInt))))))->BaseType(IntType(Si(Signed,[Short,CShort;Long,CLong;LongLong,CLongLong]|>List.assocx))),iit|(SomeUnSigned,Somex,(None|Some(BaseType(IntType(Si(_,CInt))))))->BaseType(IntType(Si(UnSigned,[Short,CShort;Long,CLong;LongLong,CLongLong]|>List.assocx))),iit|(Somesign,None,(Some(BaseType(IntTypeCChar))))->BaseType(IntType(Si(sign,CChar2))),iit|(None,SomeLong,(Some(BaseType(FloatTypeCDouble))))->BaseType(FloatType(CLongDouble)),iit|(Some_,_,Some_)->raise(Semantic("signed, unsigned valid only for char and int",List.hdiit))|(_,Some_,(Some(BaseType(FloatType(CFloat|CLongDouble)))))->raise(Semantic("long or short specified with floatint type",List.hdiit))|(_,SomeShort,(Some(BaseType(FloatTypeCDouble))))->raise(Semantic("the only valid combination is long double",List.hdiit))|(_,Some_,Some_)->(* mine *)raise(Semantic("long, short valid only for int or float",List.hdiit))(* if do short uint i, then gcc say parse error, strange ? it is
* not a parse error, it is just that we dont allow with typedef
* either short/long or signed/unsigned. In fact, with
* parse_typedef_fix2 (with et() and dt()) now I say too parse
* error so this code is executed only when do short struct
* {....} and never with a typedef cos now we parse short uint i
* as short ident ident => parse error (cos after first short i
* pass in dt() mode) *))),st,(inline,iinl)lettype_and_register_from_decldecl=let{storageD=st;_}=declinlet(t,_storage,_inline)=type_and_storage_from_decldeclinmatchstwith|NoSto->t,None|Sto(Register,ii)->t,Someii|StoTypedefii|Sto(_,ii)->raise(Semantic("storage class specified for parameter of function",ii))letfixNameForParam(name,ftyp)=matchnamewith|None,[],IdIdentid->id,ftyp|_->letii=Lib_parsing_cpp.ii_of_any(Namename)|>List.hdinraise(Semantic("parameter have qualifier",ii))lettype_and_storage_for_funcdef_from_decldecl=let(returnType,storage,_inline)=type_and_storage_from_decldeclin(matchstoragewith|StoTypedeftok->raise(Semantic("function definition declared 'typedef'",tok))|_x->(returnType,storage))(*
* this function is used for func definitions (not declarations).
* In that case we must have a name for the parameter.
* This function ensures that we give only parameterTypeDecl with well
* formed Classic constructor.
*
* todo?: do we accept other declaration in ?
* so I must add them to the compound of the deffunc. I dont
* have to handle typedef pb here cos C forbid to do VF f { ... }
* with VF a typedef of func cos here we dont see the name of the
* argument (in the typedef)
*)let(fixOldCDecl:fullType->fullType)=funty->matchsndtywith|FunctionType({ft_params=params;_}),_iifunc->(* stdC: If the prototype declaration declares a parameter for a
* function that you are defining (it is part of a function
* definition), then you must write a name within the declarator.
* Otherwise, you can omit the name. *)(matchAst.unparenparamswith|[{p_name=None;p_type=ty2;_},_]->(matchAst.unwrap_typeCty2with|BaseTypeVoid->ty|_->(* less: there is some valid case actually, when use interfaces
* and generic callbacks where specific instances do not
* need the extra parameter (happens a lot in plan9).
* Maybe this check is better done in a scheck for C.
let info = Lib_parsing_cpp.ii_of_any (Type ty2) +> List.hd in
pr2 (spf "SEMANTIC: parameter name omitted (but I continue) at %s"
(Parse_info.string_of_info info)
);
*)ty)|params->(params|>List.iter(fun(param,_)->matchparamwith|{p_name=None;p_type=_ty2;_}->(* see above
let info = Lib_parsing_cpp.ii_of_any (Type ty2) +> List.hd in
(* if majuscule, then certainly macro-parameter *)
pr2 (spf "SEMANTIC: parameter name omitted (but I continue) at %s"
(Parse_info.string_of_info info)
);
*)()|_->()));ty)(* todo? can we declare prototype in the decl or structdef,
* ... => length <> but good kan meme
*)|_->(* gcc says parse error but I dont see why *)letii=Lib_parsing_cpp.ii_of_any(Typety)|>List.hdinraise(Semantic("seems this is not a function",ii))(* TODO: this is ugly ... use record! *)letfixFunc((name,ty,sto),cp)=matchtywith|(aQ,(FunctionType({ft_params=params;_}asftyp),_iifunc))->(* it must be nullQualif, cos parser construct only this *)assert(aQ=*=nQ);(matchAst.unparenparamswith[{p_name=None;p_type=ty2;_},_]->(matchAst.unwrap_typeCty2with|BaseTypeVoid->()(* failwith "internal errror: fixOldCDecl not good" *)|_->())|params->params|>List.iter(function|({p_name=Some_s;_},_)->()(* failwith "internal errror: fixOldCDecl not good" *)|_->()));{f_name=name;f_type=ftyp;f_storage=sto;f_body=cp;}|_->letii=Lib_parsing_cpp.ii_of_any(Typety)|>List.hdinraise(Semantic("function definition without parameters",ii))letfixFieldOrMethodDecl(xs,semicolon)=matchxswith|[FieldDecl({v_namei=Some(name,ini_opt);v_type=(q,(FunctionTypeft,ii_ft));v_storage=sto;}),_noiicomma]->(* todo? define another type instead of onedecl? *)MemberDecl(MethodDecl({v_namei=Some(name,None);v_type=(q,(FunctionTypeft,ii_ft));v_storage=sto;},(matchini_optwith|None->None|Some(EqInit(tokeq,InitExpr(C(Int"0"),iizero)))->Some(tokeq,List.hdiizero)|_->raise(Semantic("can't assign expression to method decl",semicolon))),semicolon))|_->MemberField(xs,semicolon)(*-------------------------------------------------------------------------- *)(* shortcuts *)(*-------------------------------------------------------------------------- *)letmk_eeii=(e,ii)letmk_funcalle1args=Call(e1,args)letmk_constructorid(lp,params,rp)cp=letparams,_hasdots=matchparamswith|Some(params,ellipsis)->params,ellipsis|None->[],Noneinletftyp={ft_ret=nQ,(BaseTypeVoid,noii);ft_params=(lp,params,rp);ft_dots=None;(* TODO *)ft_const=None;ft_throw=None;}in{f_name=(None,noQscope,IdIdentid);f_type=ftyp;f_storage=NoSto;f_body=cp}letmk_destructortildeid(lp,_voidopt,rp)exnoptcp=letftyp={ft_ret=nQ,(BaseTypeVoid,noii);ft_params=(lp,[],rp);ft_dots=None;ft_const=None;ft_throw=exnopt;}in{f_name=(None,noQscope,IdDestructor(tilde,id));f_type=ftyp;f_storage=NoSto;f_body=cp;}letopt_to_list_paramsparams=matchparamswith|Some(params,_ellipsis)->(* todo? raise a warning that should not have ellipsis? *)params|None->[]