123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194moduletypeSexp=sigtypet=|Atomofstring|ListoftlistendmoduleMake(Sexp:Sexp)=structopenSexpmoduletypeInput=sigtypetvalread_string:t->int->stringvalread_char:t->charendexceptionParse_errorofstringletparse_errormsg=raise_notrace(Parse_errormsg)letinvalid_character()=parse_error"invalid character"letmissing_left_parenthesis()=parse_error"right parenthesis without matching left parenthesis"moduleMake_parser(Input:Input)=structletint_of_digitc=Char.codec-Char.code'0'letrecparse_atominputlen=matchInput.read_charinputwith|'0'..'9'asc->letlen=(len*10)+int_of_digitciniflen>Sys.max_string_lengththenparse_error"atom too big to represent"elseparse_atominputlen|':'->lets=Input.read_stringinputleninAtoms|_->invalid_character()letrecparse_manyinputdepthacc=matchInput.read_charinputwith|'('->letsexps=parse_manyinput(depth+1)[]inparse_manyinput(depth+1)(Listsexps::acc)|')'->ifdepth=0thenmissing_left_parenthesis()elseList.revacc|'0'..'9'asc->letsexp=parse_atominput(int_of_digitc)inparse_manyinputdepth(sexp::acc)|_->invalid_character()letparse_oneinput=matchInput.read_charinputwith|'('->letsexps=parse_manyinput1[]inListsexps|')'->missing_left_parenthesis()|'0'..'9'asc->parse_atominput(int_of_digitc)|_->invalid_character()end[@@inlinedalways]letpremature_end="premature end of input"moduleString_input=structtypet={buf:string;mutablepos:int}letread_stringtlen=letpos=t.posinlets=String.subt.bufposlenint.pos<-pos+len;sletread_chart=letpos=t.posinletc=t.buf.[pos]int.pos<-pos+1;cleterror_of_exnt=function|Parse_errormsg->Error(t.pos,msg)|_->Error(t.pos,premature_end)endmoduleString_parser=Make_parser(String_input)letparse_strings=letinput:String_input.t={buf=s;pos=0}inmatchString_parser.parse_oneinputwith|x->ifinput.pos<>String.lengthsthenError(input.pos,"data after canonical S-expression")elseOkx|exceptione->String_input.error_of_exninputeletparse_string_manys=letinput:String_input.t={buf=s;pos=0}inmatchString_parser.parse_manyinput0[]with|l->Ok(List.revl)|exceptione->String_input.error_of_exninputemoduleIn_channel_input=structtypet=in_channelletread_string=really_input_stringletread_char=input_charendmoduleIn_channel_parser=Make_parser(In_channel_input)letinput_optic=letpos=LargeFile.pos_inicinmatchIn_channel_parser.parse_oneicwith|x->Ok(Somex)|exceptionEnd_of_file->ifLargeFile.pos_inic=posthenOkNoneelseErrorpremature_end|exceptionParse_errormsg->Errormsgletinputic=matchinput_opticwith|OkNone->Errorpremature_end|Ok(Somex)->Okx|Errormsg->Errormsgletinput_many=letrecloopicacc=matchinput_opticwith|Error_asres->res|OkNone->Ok(List.revacc)|Ok(Somex)->loopic(x::acc)infunic->loopic[]letserialised_length=letrecloopacct=matchtwith|Atoms->letlen=String.lengthsinletx=refleninletlen_len=ref1inwhile!x>9dox:=!x/10;incrlen_lendone;acc+!len_len+1+len|Listl->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')'inloopsexpend