123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330(* Because other the syntax s.[x] causes trouble *)moduleString=Stdlib.StringmoduleStringLabels=struct(* functions potentially in the stdlib, depending on OCaml version *)let[@warning"-32"]exists=letrecloopsilenf=ifi=lenthenfalseelsef(String.unsafe_getsi)||loops(i+1)lenfinfun~fs->loops0(String.lengths)f;;let[@warning"-32"]for_all=letrecloopsilenf=i=len||(f(String.unsafe_getsi)&&loops(i+1)lenf)infun~fs->loops0(String.lengths)f;;(* overwrite them with stdlib versions if available *)includeStdlib.StringLabelsendincludeStringLabelsletcompareab=Ordering.of_int(String.compareab)moduleT=structtypet=StringLabels.tletcompare=compareletequal(x:t)(y:t)=x=ylethash(s:t)=Poly.hashsletto_dyns=Dyn.Stringsendletto_dyn=T.to_dynletequal:string->string->bool=(=)lethash=Poly.hashletcapitalize=capitalize_asciiletuncapitalize=uncapitalize_asciiletuppercase=uppercase_asciiletlowercase=lowercase_asciiletindex=index_optletindex_from=index_from_optletrindex=rindex_optletrindex_from=rindex_from_optletbreaks~pos=subs~pos:0~len:pos,subs~pos~len:(lengths-pos)letis_emptys=lengths=0moduleCased_functions(X:sigvalnormalize:char->charend)=structletreccheck_prefixs~prefixleni=i=len||(X.normalizes.[i]=X.normalizeprefix.[i]&&check_prefixs~prefixlen(i+1));;letreccheck_suffixs~suffixsuffix_lenoffseti=i=suffix_len||(X.normalizes.[offset+i]=X.normalizesuffix.[i]&&check_suffixs~suffixsuffix_lenoffset(i+1));;letis_prefixs~prefix=letlen=lengthsinletprefix_len=lengthprefixinlen>=prefix_len&&check_prefixs~prefixprefix_len0;;letis_suffixs~suffix=letlen=lengthsinletsuffix_len=lengthsuffixinlen>=suffix_len&&check_suffixs~suffixsuffix_len(len-suffix_len)0;;letdrop_prefixs~prefix=ifis_prefixs~prefixtheniflengths=lengthprefixthenSome""elseSome(subs~pos:(lengthprefix)~len:(lengths-lengthprefix))elseNone;;letdrop_prefix_if_existss~prefix=matchdrop_prefixs~prefixwith|None->s|Somes->s;;letdrop_suffixs~suffix=ifis_suffixs~suffixtheniflengths=lengthsuffixthenSome""elseSome(subs~pos:0~len:(lengths-lengthsuffix))elseNone;;letdrop_suffix_if_existss~suffix=matchdrop_suffixs~suffixwith|None->s|Somes->s;;endincludeCased_functions(structletnormalizec=cend)moduleCaseless=Cased_functions(structletnormalize=Char.lowercase_asciiend)letextract_wordss~is_word_char=letrecskip_blanksi=ifi=lengthsthen[]elseifis_word_chars.[i]thenparse_wordi(i+1)elseskip_blanks(i+1)andparse_wordij=ifj=lengthsthen[subs~pos:i~len:(j-i)]elseifis_word_chars.[j]thenparse_wordi(j+1)elsesubs~pos:i~len:(j-i)::skip_blanks(j+1)inskip_blanks0;;letextract_comma_space_separated_wordss=extract_wordss~is_word_char:(function|','|' '|'\t'|'\n'->false|_->true);;letextract_blank_separated_wordss=extract_wordss~is_word_char:(function|' '|'\t'->false|_->true);;letlsplit2s~on=matchindexsonwith|None->None|Somei->Some(subs~pos:0~len:i,subs~pos:(i+1)~len:(lengths-i-1));;letlsplit2_exns~on=matchlsplit2s~onwith|Somes->s|None->Code_error.raise"lsplit2_exn"["s",Strings;"on",Charon];;letrsplit2s~on=matchrindexsonwith|None->None|Somei->Some(subs~pos:0~len:i,subs~pos:(i+1)~len:(lengths-i-1));;includeString_splitletescape_onlycs=letn=ref0inletlen=lengthsinfori=0tolen-1doifunsafe_getsi=cthenincrndone;if!n=0thenselse(letb=Bytes.create(len+!n)inn:=0;fori=0tolen-1doifunsafe_getsi=cthen(Bytes.unsafe_setb!n'\\';incrn);Bytes.unsafe_setb!n(unsafe_getsi);incrndone;Bytes.unsafe_to_stringb);;letlongest_mapl~f=List.fold_leftl~init:0~f:(funaccx->maxacc(length(fx)))letlongestl=longest_mapl~f:Fun.idletlongest_prefix=function|[]->""|[x]->x|x::xs->letrecloopleni=ifi<len&&List.for_allxs~f:(funs->s.[i]=x.[i])thenlooplen(i+1)elseiinletlen=List.fold_left~init:(lengthx)~f:(funaccx->minacc(lengthx))xsinsub~pos:0x~len:(looplen0);;letquoted=Printf.sprintf"%S"letmaybe_quoteds=letescaped=escapedsinif(s==escaped||s=escaped)&¬(String.containss' ')thenselsequoteds;;includeComparable.Make(T)moduleTable=Hashtbl.Make(T)letenumerate_gens=lets=" "^s^" "inletrecloop=function|[]->[]|[x]->[x]|[x;y]->[x;s;y]|x::l->x::", "::looplinfunl->concat(loopl)~sep:"";;letenumerate_and=enumerate_gen"and"letenumerate_or=enumerate_gen"or"letenumerate_one_of=function|[x]->x|s->"One of "^enumerate_ors;;lettakeslen=subs~pos:0~len:(min(lengths)len)letdropsn=letlen=lengthsinsubs~pos:(minnlen)~len:(max(len-n)0);;letsplit_nsn=letlen=lengthsinletn=minnleninsubs~pos:0~len:n,subs~pos:n~len:(len-n);;letfindi=letrecloopslen~fi=ifi>=lenthenNoneelseiff(String.unsafe_getsi)thenSomeielseloopslen~f(i+1)infuns~f->loops(String.lengths)~f0;;letrfindi=letrecloops~fi=ifi<0thenNoneelseiff(String.unsafe_getsi)thenSomeielseloops~f(i-1)infuns~f->loops~f(String.lengths-1);;letneed_quotings=letlen=String.lengthsinlen=0||letrecloopi=ifi=lenthenfalseelse(matchs.[i]with|' '|'\"'|'('|')'|'{'|'}'|';'|'#'->true|_->loop(i+1))inloop0;;letquote_for_shells=ifneed_quotingsthenStdlib.Filename.quoteselsesletquote_list_for_shell=function|[]->""|prog::args->letprog=ifSys.win32&&containsprog'/'thenmap~f:(function|'/'->'\\'|c->c)progelseproginquote_for_shellprog::List.map~f:quote_for_shellargs|>concat~sep:" ";;letof_listchars=lets=Bytes.make(List.lengthchars)'0'inList.iterichars~f:(funic->Bytes.setsic);Bytes.to_strings;;letfilter_mapt~f=(* TODO more efficient implementation *)to_seqt|>Seq.filter_map~f|>of_seq;;letdrop_prefix_and_suffixt~prefix~suffix=letp_len=String.lengthprefixinlets_len=String.lengthsuffixinlett_len=String.lengthtinletp_s_len=p_len+s_leninifp_s_len<=t_len&&is_prefixt~prefix&&is_suffixt~suffixthenSome(subt~pos:p_len~len:(t_len-p_s_len))elseNone;;letcontains_double_underscore=letrecauxsleni=ifi>len-2thenfalseelseifs.[i]='_'&&s.[i+1]='_'thentrueelseauxslen(i+1)infuns->auxs(String.lengths)0;;letlasts=iflengths>0thenSomes.[lengths-1]elseNone