1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677openCore_kerneltypeheader=stringlisttypeitem={description:string;sequence:string;}[@@derivingsexp]moduleParser=structopenAngstromletis_not_eol=function|'\n'|'\r'->false|_->trueletcomment_line=choice[char';';char'#']>>=funcomment_char->take_whileis_not_eol>>|funcomment_msg->(comment_char,comment_msg)letheader=sep_byend_of_linecomment_lineletdescription_line=char'>'*>take_whileis_not_eolletsequence_line=peek_char_fail>>=(function|'>'->fail"Expected sequence line, not description"|_->take_whileis_not_eol)letitem=description_line<*end_of_line>>=fundescription->sep_byend_of_linesequence_line>>|funseqs->letsequence=String.concatseqsin{description;sequence}letfasta=letp=header>>=funheader->sep_byend_of_lineitem>>=funitems->option()end_of_line*>end_of_input>>|fun()->List.map~f:sndheader,itemsinp<?>"fasta"endletfrom_strings=Angstrom.(parse_string~consume:All)Parser.fastasletfrom_filefn=In_channel.with_filefn~f:(funic->letAngstrom.Buffered.{buf;off;len},res=Angstrom_unix.parseParser.fastaicinmatchreswith|Okr->Okr|Error_->letsnippet=Bigstringaf.substringbuf~off~len:(Int.min30len)inletmsg=sprintf"Failed to parse: %s"snippetinErrormsg)letfrom_file_exnfn=from_filefn|>Result.ok_or_failwithletsequences_from_file_exnfn=matchfrom_filefnwith|Ok(_,items)->List.mapitems~f:(funi->i.sequence)|Errormsg->failwithmsgletto_filefnitems=Out_channel.with_filefn~f:(funoc->List.iteritems~f:(funit->fprintfoc">%s\n%s\n"it.descriptionit.sequence))