123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297(***********************************************************************)(* *)(* Objective Caml *)(* *)(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)(* *)(* Copyright 1996 Institut National de Recherche en Informatique et *)(* en Automatique. All rights reserved. This file is distributed *)(* under the terms of the GNU Library General Public License, with *)(* linking exception. *)(* *)(***********************************************************************)(* Modified by Jerome.Vouillon@pps.jussieu.fr for integration in RE *)(* $Id: re_str.ml,v 1.3 2002/07/03 15:47:54 vouillon Exp $ *)moduleRe=Coretyperegexp={re:Re.t;mtch:Re.reLazy.t;srch:Re.reLazy.t}letcompile_regexpsc=letre=Emacs.re~case:(notc)sin{re;mtch=lazy(Re.compile(Re.seq[Re.start;re]));srch=lazy(Re.compilere)}letstate=refNoneletstring_matchresp=trystate:=Some(Re.exec~pos:p(Lazy.forcere.mtch)s);truewithNot_found->state:=None;falseletstring_partial_matchresp=matchRe.exec_partial~pos:p(Lazy.forcere.mtch)swith`Full->string_matchresp|`Partial->true|`Mismatch->falseletsearch_forwardresp=tryletres=Re.exec~pos:p(Lazy.forcere.srch)sinstate:=Someres;fst(Re.Group.offsetres0)withNot_found->state:=None;raiseNot_foundletrecsearch_backwardresp=tryletres=Re.exec~pos:p(Lazy.forcere.mtch)sinstate:=Someres;pwithNot_found->state:=None;ifp=0thenraiseNot_foundelsesearch_backwardres(p-1)letvalid_groupn=n>=0&&n<10&&(match!statewith|None->false|Somem->n<Re.Group.nb_groupsm)letoffset_groupi=match!statewith|Somem->Re.Group.offsetmi|None->raiseNot_foundletgroup_leni=trylet(b,e)=offset_groupiine-bwithNot_found->0letrecrepl_lengthreplpqlen=ifp<lenthenbeginifrepl.[p]<>'\\'thenrepl_lengthrepl(p+1)(q+1)lenelsebeginletp=p+1inifp=lenthenfailwith"Str.replace: illegal backslash sequence";letq=matchrepl.[p]with|'\\'->q+1|'0'..'9'asc->q+group_len(Char.codec-Char.code'0')|_->q+2inrepl_lengthrepl(p+1)qlenendendelseqletrecreplaceorigreplpresqlen=ifp<lenthenbeginletc=repl.[p]inifc<>'\\'thenbeginBytes.setresqc;replaceorigrepl(p+1)res(q+1)lenendelsebeginmatchrepl.[p+1]with'\\'->Bytes.setresq'\\';replaceorigrepl(p+2)res(q+1)len|'0'..'9'asc->letd=trylet(b,e)=offset_group(Char.codec-Char.code'0')inletd=e-binifd>0thenString.blitorigbresqd;dwithNot_found->0inreplaceorigrepl(p+2)res(q+d)len|c->Bytes.setresq'\\';Bytes.setres(q+1)c;replaceorigrepl(p+2)res(q+2)lenendendletreplacement_textreplorig=letlen=String.lengthreplinletres=Bytes.create(repl_lengthrepl00len)inreplaceorigrepl0res0(String.lengthrepl);Bytes.unsafe_to_stringresletquotes=letlen=String.lengthsinletbuf=Buffer.create(2*len)infori=0tolen-1domatchs.[i]with'['|']'|'*'|'.'|'\\'|'?'|'+'|'^'|'$'asc->Buffer.add_charbuf'\\';Buffer.add_charbufc|c->Buffer.add_charbufcdone;Buffer.contentsbufletstring_beforesn=String.subs0nletstring_aftersn=String.subsn(String.lengths-n)letfirst_charssn=String.subs0nletlast_charssn=String.subs(String.lengths-n)nletregexpe=compile_regexpefalseletregexp_case_folde=compile_regexpetrueletregexp_strings=compile_regexp(quotes)falseletregexp_string_case_folds=compile_regexp(quotes)trueletgroup_beginningn=ifnot(valid_groupn)theninvalid_arg"Str.group_beginning";letpos=fst(offset_groupn)inifpos=-1thenraiseNot_foundelseposletgroup_endn=ifnot(valid_groupn)theninvalid_arg"Str.group_end";letpos=snd(offset_groupn)inifpos=-1thenraiseNot_foundelseposletmatched_groupntxt=let(b,e)=offset_groupninString.subtxtb(e-b)letreplace_matchedreplmatched=replacement_textreplmatchedletmatch_beginning()=group_beginning0andmatch_end()=group_end0andmatched_stringtxt=matched_group0txtletsubstitute_firstexprrepl_funtext=tryletpos=search_forwardexprtext0inString.concat""[string_beforetextpos;repl_funtext;string_aftertext(match_end())]withNot_found->textletglobal_substituteexprrepl_funtext=letrecreplaceaccustartlast_was_empty=letstartpos=iflast_was_emptythenstart+1elsestartinifstartpos>String.lengthtextthen(string_aftertextstart)::accuelsematchsearch_forwardexprtextstartposwith|pos->letend_pos=match_end()inletrepl_text=repl_funtextinreplace(repl_text::String.subtextstart(pos-start)::accu)end_pos(end_pos=pos)|exceptionNot_found->(string_aftertextstart)::accuinString.concat""(List.rev(replace[]0false))letglobal_replaceexprrepltext=global_substituteexpr(replacement_textrepl)textandreplace_firstexprrepltext=substitute_firstexpr(replacement_textrepl)textletsearch_forward_progressresp=letpos=search_forwardrespinifmatch_end()>pthenposelseifp<String.lengthsthensearch_forwardres(p+1)elseraiseNot_foundletbounded_splitexprtextnum=letstart=ifstring_matchexprtext0thenmatch_end()else0inletrecsplitaccustartn=ifstart>=String.lengthtextthenaccuelseifn=1then(string_aftertextstart)::accuelsetryletpos=search_forward_progressexprtextstartinsplit((String.subtextstart(pos-start))::accu)(match_end())(n-1)withNot_found->(string_aftertextstart)::accuinList.rev(split[]startnum)letsplitexprtext=bounded_splitexprtext0letbounded_split_delimexprtextnum=letrecsplitaccustartn=ifstart>String.lengthtextthenaccuelseifn=1then(string_aftertextstart)::accuelsetryletpos=search_forward_progressexprtextstartinsplit(String.subtextstart(pos-start)::accu)(match_end())(n-1)withNot_found->(string_aftertextstart)::accuiniftext=""then[]elseList.rev(split[]0num)letsplit_delimexprtext=bounded_split_delimexprtext0typesplit_result=Textofstring|Delimofstringletbounded_full_splitexprtextnum=letrecsplitaccustartn=ifstart>=String.lengthtextthenaccuelseifn=1thenText(string_aftertextstart)::accuelsetryletpos=search_forward_progressexprtextstartinlets=matched_stringtextinifpos>startthensplit(Delim(s)::Text(String.subtextstart(pos-start))::accu)(match_end())(n-1)elsesplit(Delim(s)::accu)(match_end())(n-1)withNot_found->Text(string_aftertextstart)::accuinList.rev(split[]0num)letfull_splitexprtext=bounded_full_splitexprtext0