123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269(**************************************************************************)(* *)(* Copyright 2013 OCamlPro *)(* *)(* All rights reserved. This file is distributed under the terms of *)(* the Lesser GNU Public License version 3.0. *)(* *)(* This software 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 *)(* Lesser GNU General Public License for more details. *)(* *)(**************************************************************************)(* - Input stream handling - *)openApprox_lexermoduleStream=structtypestream={nstream:Nstream.t;last:token;before_last:token;region:Pos.Region.t;stop:Lexing.position->bool}letof_nstream?(stop=fun_->false)nstream={nstream;last=COMMENT;before_last=COMMENT;region=Pos.Region.zero;stop;}letnextstream=letshiftstreamtokregion={streamwithregion;last=tok;before_last=matchstream.lastwith|COMMENT->stream.before_last|tok->tok;}inmatchNstream.nextstream.nstreamwith|Some({Nstream.token;region},nstream)->ifstream.stop(Pos.Region.sndregion)thenEOF,shiftstreamEOFregionelsetoken,shift{streamwithnstream}tokenregion|_->EOF,shiftstreamEOFstream.regionletequalsst1st2=st1.nstream==st2.nstreamletnext_twostream=lettok1,stream=nextstreaminlettok2,stream=nextstreamintok1,tok2,streamletnext_threestream=lettok1,stream=nextstreaminlettok2,stream=nextstreaminlettok3,stream=nextstreamintok1,tok2,tok3,streamletpreviousstream=stream.before_lastlettokenstream=stream.lastletposstream=letpos1=Pos.Region.fststream.regioninletpos2=Pos.Region.sndstream.regioninLexing.(pos1.pos_lnum,pos1.pos_cnum-pos1.pos_bol,pos2.pos_cnum-pos1.pos_cnum)endletclose_defstream=matchStream.previousstreamwith|AMPERSAND|AMPERAMPER|BARBAR|BEGIN|COLONCOLON|COLONEQUAL|COMMA|DO|DOWNTO|ELSE|EQUAL|GREATER|IF|IN|INFIXOP0_|INFIXOP1_|INFIXOP2_|INFIXOP3_|INFIXOP4_|LBRACE|LBRACELESS|LBRACKET|LBRACKETBAR|LBRACKETLESS|LBRACKETGREATER|LESS|LESSMINUS|LPAREN|MATCH|MINUS|MINUSDOT|MINUSGREATER|OR|PLUS|PLUSDOT|QUESTION|QUESTIONQUESTION|SEMI|STAR|THEN|TO|TRY|WHEN|WHILE|TILDE->false|_->trueletparse_pathstream=letrecauxaccstream=matchStream.next_twostreamwith|DOT,UIDENTi,stream->aux(i::acc)stream|_->List.revacc,streaminmatchStream.nextstreamwith|UIDENTi,stream->letpath,stream=aux[]streamini::path,stream|_->[],streamletrecskip_to_next_parenstream=lettok,stream=Stream.nextstreaminmatchtokwith|RPAREN|EOF->stream|_->skip_to_next_parenstream(* - Now for the interesting stuff - *)typescope=Def|Block|Paren|Bracetypeenv=Aliasofstring*stringlist|Openofstringlisttypet=(scope*envlist)listletempty=[]letrecclosetscope=matchtwith|[]->[]|(scope1,_)::rwhenscope1=scope->r|_::r->closerscopeletmaybe_closetscope=matchtwith|(scope1,_)::rwhenscope1=scope->r|t->tletpushtinfo=matchtwith|(scope,infos)::r->(scope,info::infos)::r|[]->[Block,[info]](* print error ? *)(* [ (X : S) ]* *)letparse_functor_argsstream=letrecauxstream=letparse_error=[],streaminmatchStream.next_threestreamwith|LPAREN,UIDENTx,COLON,stream->beginmatchparse_pathstreamwith|[],_->parse_error|s,stream->(* XXX: convert module constraints into module aliases ?*)letstream=skip_to_next_parenstreaminletargs,stream=auxstreaminAlias(x,s)::args,streamend|_->parse_errorinauxstream(* functor (X: S) -> *)letparse_functorstream=letrecauxstream=letparse_error=[],streaminmatchStream.nextstreamwith|FUNCTOR,stream->letargs,stream=parse_functor_argsstreaminbeginmatchStream.nextstreamwith|MINUSGREATER,stream->letrest,stream=auxstreaminargs@rest,stream|_->parse_errorend|_->parse_errorinauxstreamletparsetstream0=lettok,stream=Stream.nextstream0inmatchtokwith|STRUCT|SIG|BEGIN|OBJECT->(Block,[])::t,stream|END->closetBlock,stream|LPAREN->(Paren,[])::t,stream|RPAREN->closetParen,stream|LBRACE->(matchparse_pathstreamwith|[],stream->(Brace,[])::t,stream|path,stream->(Brace,[Openpath])::t,stream)|RBRACE->closetBrace,stream|OPEN->lett=ifStream.previousstream=LETthentelsemaybe_closetDefinletpath,stream=parse_pathstreaminpusht(Openpath),stream|INCLUDE->letpath,stream=parse_pathstreaminpusht(Openpath),stream|LETwhenclose_defstream->(Def,[])::maybe_closetDef,stream|MODULE->lett=ifclose_defstreamthenmaybe_closetDefelsetinletident,stream=matchStream.nextstreamwith|UIDENTu,stream->u,stream|TYPE,stream1->(matchStream.nextstream1with|UIDENTu,stream->u,stream|_->"",stream)|_->"",streaminletfunctor_pre_args,stream=parse_functor_argsstreaminlettop_def,stream=matchStream.nextstreamwith|EQUAL,stream1->beginmatchparse_pathstream1with|[],_->[],stream|path,stream->path,streamend|_->[],stream(* todo *)inletfunctor_post_args,stream=matchStream.nextstreamwith|EQUAL,stream->parse_functorstream|_->[],streaminletaliases=functor_pre_args@functor_post_argsinlett=iftop_def<>[]thenpusht(Alias(ident,top_def))elsetin(Def,Open[ident]::aliases)::t,stream|UIDENT_->(* Module.( ... ) or Module.{ ... } *)letpath,stream=parse_pathstream0in(matchStream.next_twostreamwith|DOT,LPAREN,stream->(Paren,[Openpath])::t,stream|DOT,LBRACE,stream->(matchparse_pathstreamwith|[],stream->(Brace,[Openpath])::t,stream|path2,stream->(Brace,[Openpath;Openpath2])::t,stream)|_->t,stream)|_->t,streamletpos_afterlinecolpos=letopenLexinginpos.pos_lnum>line||pos.pos_lnum=line&&pos.pos_cnum-pos.pos_bol>=colletread_nstream?line?columnnstream=letrecparse_all(t,stream)=ifStream.previousstream=EOFthentelseparse_all(parsetstream)inletstop=matchline,columnwith|Somel,Somec->Some(pos_afterlc)|Somel,None->Some(pos_afterl0)|_->Noneinparse_all([Block,[]],Stream.of_nstream?stopnstream)letread?line?columnchan=read_nstream?line?column(Nstream.of_channelchan)letread_stringstring=read_nstream(Nstream.of_stringstring)letto_list=letauxacct=List.fold_left(funacc->function|Brace,_->acc(* brace opens don't propagate down *)|_,ctx->List.rev_appendctxacc)acctinfunction|(Brace,ctx)::t->aux(List.revctx)t|t->aux[]tletfold_nstreamfacc?(init=[])?stopnstream=letrecauxacctstream=ifStream.previousstream=EOFthenaccelselett1,stream1=parsetstreaminletreccatch_upaccstream=lettok,stream=Stream.nextstreaminifStream.equalsstreamstream1thenaccelsecatch_up(faccttok(Stream.posstream))streaminletacc=catch_upaccstreaminletacc=facct1(Stream.tokenstream1)(Stream.posstream1)inauxacct1stream1inletstream=Stream.of_nstream?stopnstreaminauxacc[Block,init]streamletfoldfacc?init?stopchan=fold_nstreamfacc?init?stop(Nstream.of_channelchan)letfold_stringfacc?init?stopchan=fold_nstreamfacc?init?stop(Nstream.of_stringchan)