123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113(**************************************************************************)(* *)(* OCaml *)(* *)(* Daniel de Rauglaudre, projet Cristal, INRIA Rocquencourt *)(* *)(* Copyright 1997 Institut National de Recherche en Informatique et *)(* en Automatique. *)(* *)(* All rights reserved. This file is distributed under the terms of *)(* the GNU Lesser General Public License version 2.1, with the *)(* special exception on linking described in the file LICENSE. *)(* *)(**************************************************************************)type'at={mutablecount:int;mutabledata:'adata}and'adata=Sempty|Sconsof'a*'adata|Sgenof'agen|Sbuffio:buffio->chardataand'agen={mutablecurr:'aoptionoption;func:unit->'aoption}andbuffio={ic:in_channel;buff:bytes;mutablelen:int;mutableind:int}exceptionFailureexceptionErrorofstringletcount{count}=countletfill_buffb=b.len<-inputb.icb.buff0(Bytes.lengthb.buff);b.ind<-0letpeek:typev.vt->voption=funs->(* consult the first item of s *)matchs.datawithSempty->None|Scons(a,_)->Somea|Sgen{curr=Somea}->a|Sgeng->letx=g.func()ing.curr<-Somex;x|Sbuffiob->ifb.ind>=b.lenthenfill_buffb;ifb.len==0thenbegins.data<-Sempty;NoneendelseSome(Bytes.unsafe_getb.buffb.ind)letrecjunk:typev.vt->unit=funs->matchs.datawithScons(_,d)->s.count<-(succs.count);s.data<-d|Sgen({curr=Some_}asg)->s.count<-(succs.count);g.curr<-None|Sbuffiob->ifb.ind>=b.lenthenfill_buffb;ifb.len==0thens.data<-Semptyelse(s.count<-(succs.count);b.ind<-succb.ind)|_->matchpeekswithNone->()|Some_->junksletrecngetns=ifn<=0then[],s.data,0elsematchpeekswithSomea->junks;let(al,d,k)=nget(predn)sina::al,Scons(a,d),succk|None->[],s.data,0letnpeekns=let(al,d,len)=ngetnsins.count<-(s.count-len);s.data<-d;alletnthnst=tryList.nth(npeek(n+1)st)nwithStdlib.Failure_->raiseFailureletrecnjunknst=ifn<>0then(junkst;njunk(n-1)st)letnexts=matchpeekswithSomea->junks;a|None->raiseFailureletis_emptys=matchpeekswith|Some_->false|None->true(* Stream building functions *)letfrom?(offset=0)f={count=offset;data=Sgen{curr=None;func=f}}(* NB we need the thunk for value restriction *)letempty()={count=0;data=Sempty}letof_string?(offset=0)s=letcount=ref0infrom~offset(fun()->letc=!countinifc<String.lengthsthen(incrcount;Somes.[c])elseNone)letof_channelic={count=0;data=Sbuffio{ic=ic;buff=Bytes.create4096;len=0;ind=0}}