123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167type'astate=|Partialof'apartial|Doneofint*'a|Failofint*stringlist*stringand'apartial={committed:int;continue:Bigstring.t->More.t->'astate}type'awith_state=Input.t->int->More.t->'atype'afailure=(stringlist->string->'astate)with_statetype('a,'r)success=('a->'rstate)with_statetype'at={run:'r.('rfailure->('a,'r)success->'rstate)with_state}letfail_kbufpos_marksmsg=Fail(pos-Input.initial_commit_posbuf,marks,msg)letsucceed_kbufpos_v=Done(pos-Input.initial_commit_posbuf,v)letfail_to_stringmarkserr=String.concat" > "marks^": "^errletstate_to_option=function|Done(_,v)->Somev|_->Noneletstate_to_result=function|Done(_,v)->Result.Okv|Partial_->Result.Error"incomplete input"|Fail(_,marks,err)->Result.Error(fail_to_stringmarkserr)letparse?(input=Bigstring.empty)p=p.run(Input.create0input)0Incompletefail_ksucceed_kletparse_bigstringpinput=state_to_result(p.run(Input.create0input)0Completefail_ksucceed_k)moduleMonad=structletreturn=funv->{run=funinputposmore_failsucc->succinputposmorev}letfailmsg={run=funinputposmorefail_succ->failinputposmore[]msg}let(>>=)pf={run=funinputposmorefailsucc->letsucc'input'pos'more'v=(fv).runinput'pos'more'failsuccinp.runinputposmorefailsucc'}let(>>|)pf={run=funinputposmorefailsucc->letsucc'input'pos'more'v=succinput'pos'more'(fv)inp.runinputposmorefailsucc'}let(<$>)fm=m>>|flet(<*>)fm=(* f >>= fun f -> m >>| f *){run=funinputposmorefailsucc->letsucc0input0pos0more0f=letsucc1input1pos1more1m=succinput1pos1more1(fm)inm.runinput0pos0more0failsucc1inf.runinputposmorefailsucc0}letliftfm=f<$>mletlift2fm1m2={run=funinputposmorefailsucc->letsucc1input1pos1more1m1=letsucc2input2pos2more2m2=succinput2pos2more2(fm1m2)inm2.runinput1pos1more1failsucc2inm1.runinputposmorefailsucc1}letlift3fm1m2m3={run=funinputposmorefailsucc->letsucc1input1pos1more1m1=letsucc2input2pos2more2m2=letsucc3input3pos3more3m3=succinput3pos3more3(fm1m2m3)inm3.runinput2pos2more2failsucc3inm2.runinput1pos1more1failsucc2inm1.runinputposmorefailsucc1}letlift4fm1m2m3m4={run=funinputposmorefailsucc->letsucc1input1pos1more1m1=letsucc2input2pos2more2m2=letsucc3input3pos3more3m3=letsucc4input4pos4more4m4=succinput4pos4more4(fm1m2m3m4)inm4.runinput3pos3more3failsucc4inm3.runinput2pos2more2failsucc3inm2.runinput1pos1more1failsucc2inm1.runinputposmorefailsucc1}let(*>)ab=(* a >>= fun _ -> b *){run=funinputposmorefailsucc->letsucc'input'pos'more'_=b.runinput'pos'more'failsuccina.runinputposmorefailsucc'}let(<*)ab=(* a >>= fun x -> b >>| fun _ -> x *){run=funinputposmorefailsucc->letsucc0input0pos0more0x=letsucc1input1pos1more1_=succinput1pos1more1xinb.runinput0pos0more0failsucc1ina.runinputposmorefailsucc0}endmoduleChoice=structlet(<?>)pmark={run=funinputposmorefailsucc->letfail'input'pos'more'marksmsg=failinput'pos'more'(mark::marks)msginp.runinputposmorefail'succ}let(<|>)pq={run=funinputposmorefailsucc->letfail'input'pos'more'marksmsg=(* The only two constructors that introduce new failure continuations are
* [<?>] and [<|>]. If the initial input position is less than the length
* of the committed input, then calling the failure continuation will
* have the effect of unwinding all choices and collecting marks along
* the way. *)ifpos<Input.commit_posinput'thenfailinput'pos'moremarksmsgelseq.runinput'posmore'failsuccinp.runinputposmorefail'succ}endmoduleMonad_use_for_debugging=structletreturn=Monad.returnletfail=Monad.faillet(>>=)=Monad.(>>=)let(>>|)mf=m>>=funx->return(fx)let(<$>)fm=m>>|flet(<*>)fm=f>>=funf->m>>|fletlift=(>>|)letlift2fm1m2=f<$>m1<*>m2letlift3fm1m2m3=f<$>m1<*>m2<*>m3letlift4fm1m2m3m4=f<$>m1<*>m2<*>m3<*>m4let(*>)ab=a>>=fun_->blet(<*)ab=a>>=funx->b>>|fun_->xend