123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418moduletypeSexp=sigtypet=|Atomofstring|ListoftlistendmoduletypeMonad=sigtype'atvalreturn:'a->'atvalbind:'at->('a->'bt)->'btendmoduletypeS=sigtypesexpvalparse_string:string->(sexp,int*string)resultvalparse_string_many:string->(sexplist,int*string)resultvalinput:in_channel->(sexp,string)resultvalinput_opt:in_channel->(sexpoption,string)resultvalinput_many:in_channel->(sexplist,string)resultvalserialised_length:sexp->intvalto_string:sexp->stringvalto_buffer:Buffer.t->sexp->unitvalto_channel:out_channel->sexp->unitmoduleParser:sigexceptionParse_errorofstringvalpremature_end_of_input:stringmoduleLexer:sigtypetvalcreate:unit->ttype_token=|Await:[>`other]token|Lparen:[>`other]token|Rparen:[>`other]token|Atom:int->[>`atom]tokenvalfeed:t->char->[`other|`atom]tokenvalfeed_eoi:t->unitendmoduleStack:sigtypet=|Empty|Openoft|Sexpofsexp*tvalto_list:t->sexplistvalopen_paren:t->tvalclose_paren:t->tvaladd_atom:string->t->tvaladd_token:[`other]Lexer.token->t->tendendmoduletypeInput=sigtypetmoduleMonad:sigtype'atvalreturn:'a->'atvalbind:'at->('a->'bt)->'btendvalread_string:t->int->(string,string)resultMonad.tvalread_char:t->(char,string)resultMonad.tend[@@deprecated"Use Parser module instead"][@@@warning"-3"]moduleMake_parser(Input:Input):sigvalparse:Input.t->(sexp,string)resultInput.Monad.tvalparse_many:Input.t->(sexplist,string)resultInput.Monad.tend[@@deprecated"Use Parser module instead"]endmoduleMake(Sexp:Sexp)=structopenSexpmoduleParser=structexceptionParse_errorofstringletparse_errormsg=raise(Parse_errormsg)letparse_errorff=Format.ksprintfparse_errorfletpremature_end_of_input="premature end of input"moduleLexer=structtypestate=|Init|Parsing_lengthtypet={mutablestate:state;mutablen:int}letcreate()={state=Init;n=0}letint_of_digitc=Char.codec-Char.code'0'type_token=|Await:[>`other]token|Lparen:[>`other]token|Rparen:[>`other]token|Atom:int->[>`atom]tokenletfeedtc=match(t.state,c)with|Init,'('->Lparen|Init,')'->Rparen|Init,'0'..'9'->t.state<-Parsing_length;t.n<-int_of_digitc;Await|Init,_->parse_errorf"invalid character %C, expected '(', ')' or '0'..'9'"c|Parsing_length,'0'..'9'->letlen=(t.n*10)+int_of_digitciniflen>Sys.max_string_lengththenparse_error"atom too big to represent"else(t.n<-len;Await)|Parsing_length,':'->t.state<-Init;Atomt.n|Parsing_length,_->parse_errorf"invalid character %C while parsing atom length, expected '0'..'9' \
or ':'"cletfeed_eoit=matcht.statewith|Init->()|Parsing_length->parse_errorpremature_end_of_inputendmoduleL=LexermoduleStack=structtypet=|Empty|Openoft|SexpofSexp.t*tletopen_parenstack=Openstackletclose_paren=letrecloopacc=function|Empty->parse_error"right parenthesis without matching left parenthesis"|Sexp(sexp,t)->loop(sexp::acc)t|Opent->Sexp(Listacc,t)infunt->loop[]tletto_list=letrecloopacc=function|Empty->acc|Sexp(sexp,t)->loop(sexp::acc)t|Open_->parse_errorpremature_end_of_inputinfunt->loop[]tletadd_atomsstack=Sexp(Atoms,stack)letadd_token(x:[`other]Lexer.token)stack=matchxwith|L.Await->stack|L.Lparen->open_parenstack|L.Rparen->close_parenstackendendopenParserletfeed_eoi_singlelexerstack=matchLexer.feed_eoilexer;Stack.to_liststackwith|exceptionParse_errormsg->Errormsg|[x]->Okx|[]->Errorpremature_end_of_input|_::_::_->assertfalseletfeed_eoi_manylexerstack=matchLexer.feed_eoilexer;Stack.to_liststackwith|exceptionParse_errormsg->Errormsg|l->Oklletone_tokensposlenlexerstackk=matchLexer.feedlexer(String.unsafe_getspos)with|exceptionParse_errormsg->Error(pos,msg)|L.Atomatom_len->(matchString.subs(pos+1)atom_lenwith|exception_->Error(len,premature_end_of_input)|atom->letpos=pos+1+atom_leninksposlenlexer(Stack.add_atomatomstack))|(L.Await|L.Lparen|L.Rparen)asx->(matchStack.add_tokenxstackwith|exceptionParse_errormsg->Error(pos,msg)|stack->ks(pos+1)lenlexerstack)[@@inlinedalways]letparse_string=letrecloopsposlenlexerstack=ifpos=lenthenmatchfeed_eoi_singlelexerstackwith|Errormsg->Error(pos,msg)|Ok_asok->okelseone_tokensposlenlexerstackcontandcontsposlenlexerstack=matchstackwith|Stack.Sexp(sexp,Empty)->ifpos=lenthenOksexpelseError(pos,"data after canonical S-expression")|stack->loopsposlenlexerstackinfuns->loops0(String.lengths)(Lexer.create())Emptyletparse_string_many=letrecloopsposlenlexerstack=ifpos=lenthenmatchfeed_eoi_manylexerstackwith|Errormsg->Error(pos,msg)|Ok_asok->okelseone_tokensposlenlexerstackloopinfuns->loops0(String.lengths)(Lexer.create())Emptyletone_tokenicclexerstack=matchLexer.feedlexercwith|L.Atomn->(matchreally_input_stringicnwith|exceptionEnd_of_file->raise(Parse_errorpremature_end_of_input)|s->Stack.add_atomsstack)|(L.Await|L.Lparen|L.Rparen)asx->Stack.add_tokenxstackletinput_opt=letrecloopiclexerstack=letc=input_charicinmatchone_tokenicclexerstackwith|Sexp(sexp,Empty)->Ok(Somesexp)|stack->loopiclexerstackinfunic->letlexer=Lexer.create()inmatchinput_charicwith|exceptionEnd_of_file->OkNone|c->(trymatchLexer.feedlexercwith|L.Atom_->assertfalse|(L.Await|L.Lparen|L.Rparen)asx->loopiclexer(Stack.add_tokenxEmpty)with|Parse_errormsg->Errormsg|End_of_file->Errorpremature_end_of_input)letinputic=matchinput_opticwith|OkNone->Errorpremature_end_of_input|Ok(Somex)->Okx|Errormsg->Errormsgletinput_many=letrecloopiclexerstack=matchinput_charicwith|exceptionEnd_of_file->Lexer.feed_eoilexer;Ok(Stack.to_liststack)|c->loopiclexer(one_tokenicclexerstack)infunic->tryloopic(Lexer.create())EmptywithParse_errormsg->Errormsgletserialised_length=letrecloopacct=matchtwith|Atoms->letlen=String.lengthsinletx=refleninletlen_len=ref1inwhile!x>9dox:=!x/10;incrlen_lendone;acc+!len_len+1+len|Listl->2+List.fold_leftloopacclinfunt->loop0tletto_bufferbufsexp=letrecloop=function|Atomstr->Buffer.add_stringbuf(string_of_int(String.lengthstr));Buffer.add_stringbuf":";Buffer.add_stringbufstr|Liste->Buffer.add_charbuf'(';List.iterloope;Buffer.add_charbuf')'inloopsexpletto_stringsexp=letbuf=Buffer.create(serialised_lengthsexp)into_bufferbufsexp;Buffer.contentsbufletto_channelocsexp=letrecloop=function|Atomstr->output_stringoc(string_of_int(String.lengthstr));output_charoc':';output_stringocstr|Listl->output_charoc'(';List.iterloopl;output_charoc')'inloopsexpmoduletypeInput=sigtypetmoduleMonad:Monadvalread_string:t->int->(string,string)resultMonad.tvalread_char:t->(char,string)resultMonad.tendmoduleMake_parser(Input:Input)=structopenInput.Monadlet(>>=)=bindlet(>>=*)mf=m>>=function|Error_aserr->returnerr|Okx->fxletone_tokeninputclexerstack=matchLexer.feedlexercwith|exceptionParse_errormsg->return(Errormsg)|L.Atomn->Input.read_stringinputn>>=*funs->return(Ok(Stack.add_atomsstack))|(L.Await|L.Lparen|L.Rparen)asx->return(matchStack.add_tokenxstackwith|exceptionParse_errormsg->Errormsg|stack->Okstack)letparse=letrecloopinputlexerstack=Input.read_charinput>>=function|Error_->return(feed_eoi_singlelexerstack)|Okc->(one_tokeninputclexerstack>>=*function|Sexp(sexp,Empty)->return(Oksexp)|stack->loopinputlexerstack)infuninput->loopinput(Lexer.create())Emptyletparse_many=letrecloopinputlexerstack=Input.read_charinput>>=function|Error_->return(feed_eoi_manylexerstack)|Okc->one_tokeninputclexerstack>>=*funstack->loopinputlexerstackinfuninput->loopinput(Lexer.create())EmptyendendmoduleT=structtypet=|Atomofstring|ListoftlistendincludeTincludeMake(T)