123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275moduleI=Reason_parser.MenhirInterpretertypetoken=Reason_parser.tokentypeinvalid_docstrings=Reason_lexer.invalid_docstringsmoduleStep:sigtype'aparsertype'astep=|Intermediateof'aparser|Successof'a*invalid_docstrings|Errorvalinitialize:'aI.checkpoint->'astepvaloffer:'aparser->tokenReason_lexer.positioned->'astepvaladd_docstring:string->Lexing.position->Lexing.position->'aparser->'aparservalrecover:'aI.checkpoint->invalid_docstrings->'aparservalrecovery_env:'aparser->'aI.env*invalid_docstringsend=structtype'apostfix_state={checkpoint:'aI.checkpoint;docstrings:invalid_docstrings;fallback:'aI.checkpoint;postfix_ops:int;postfix_pos:Lexing.position;}type'aparser=|Normalof'aI.checkpoint*invalid_docstrings|After_potential_postfixof'apostfix_statetype'astep=|Intermediateof'aparser|Successof'a*invalid_docstrings|Errorletmark_potential_postfixtokenfallback=letstring_forallfs=leti=ref0inletlen=String.lengthsinletvalid=reftrueinwhile!i<len&&!validdovalid:=fs.[!i];incri;done;!validinmatchtokenwith|(Reason_parser.INFIXOP1s,pos,_)whenstring_forall((=)'^')s->(funcheckpointdocstrings->After_potential_postfix{checkpoint;fallback;docstrings;postfix_ops=String.lengths;postfix_pos=pos;})|_->(funcheckpointdocstrings->Normal(checkpoint,docstrings))letrecoffer_postfixcountpos=function|I.Shifting_|I.AboutToReduce_ascheckpoint->offer_postfixcountpos(I.resumecheckpoint)|I.InputNeeded_ascheckpoint->ifcount<=0thencheckpointelse(letpos_cnum=pos.Lexing.pos_cnuminletpos'={poswithLexing.pos_cnum=pos_cnum+1}inoffer_postfix(count-1)pos'(I.offercheckpoint(Reason_parser.POSTFIXOP"^",pos,pos')))|other->otherletrecstepmark_potential_postfixsafepointdocstrings=function|I.Shifting_|I.AboutToReduce_ascheckpoint->stepmark_potential_postfixsafepointdocstrings(I.resumecheckpoint)|I.InputNeeded_ascheckpoint->Intermediate(mark_potential_postfixcheckpointdocstrings)|I.Acceptedx->Success(x,docstrings)|I.Rejected|I.HandlingError_->Errorletofferparsertoken=matchparserwith|Normal(checkpoint,docstrings)->step(mark_potential_postfixtokencheckpoint)checkpointdocstrings(I.offercheckpointtoken)|After_potential_postfixr->matchstep(mark_potential_postfixtokenr.checkpoint)r.checkpointr.docstrings(I.offerr.checkpointtoken)with|Error->begin(* Try applying postfix operators on fallback parser *)matchoffer_postfixr.postfix_opsr.postfix_posr.fallbackwith|I.InputNeeded_ascheckpoint->step(mark_potential_postfixtokencheckpoint)checkpointr.docstrings(I.offercheckpointtoken)|_->Errorend|result->resultletadd_docstringtextstartpendpparser=matchparserwith|Normal(checkpoint,docstrings)->letdocstrings=Reason_lexer.add_invalid_docstringtextstartpendpdocstringsinNormal(checkpoint,docstrings)|After_potential_postfixr->letdocstrings=Reason_lexer.add_invalid_docstringtextstartpendpr.docstringsinAfter_potential_postfix{rwithdocstrings}letinitializecheckpoint=step(funparserds->Normal(parser,ds))checkpointReason_lexer.empty_invalid_docstringscheckpointletrecovercpds=beginmatchcpwith|I.InputNeeded_->()|_->assertfalseend;Normal(cp,ds)letrecovery_envparser=letcp,ds=matchparserwith|Normal(cp,ds)->(cp,ds)|After_potential_postfixr->(r.checkpoint,r.docstrings)inmatchcpwith|I.InputNeededenv->(env,ds)|_->assertfalseendtype'aparser='aStep.parsertype'astep='aStep.step=|Intermediateof'aparser|Successof'a*invalid_docstrings|Errorletinitialentryposition=matchStep.initialize(entryposition)with|Step.Intermediateparser->parser|_->assertfalseletrecoffer_manyparser=function|[]->Step.Intermediateparser|[token]->Step.offerparsertoken|token::tokens->matchStep.offerparsertokenwith|Step.Intermediateparser->offer_manyparsertokens|other->other(* Logic for inserting ';' *)lettry_insert_semi_on=function|Reason_parser.LET|Reason_parser.TYPE|Reason_parser.MODULE|Reason_parser.OPEN|Reason_parser.EXCEPTION|Reason_parser.INCLUDE|Reason_parser.DOCSTRING_|Reason_parser.LIDENT_|Reason_parser.UIDENT_|Reason_parser.IF|Reason_parser.WHILE|Reason_parser.FOR|Reason_parser.SWITCH|Reason_parser.TRY|Reason_parser.ASSERT|Reason_parser.EXTERNAL|Reason_parser.LAZY|Reason_parser.LBRACKETAT->true|_->false(* Logic for splitting '=?...' operators into '=' '?' '...' *)letadvancepn={pwithLexing.pos_cnum=p.Lexing.pos_cnum+n}letrecsplit_greatersaccpcur=function|'>'::tl->letpnext=(advancepcur1)insplit_greaters((Reason_parser.GREATER,pcur,pnext)::acc)pnexttl|nonGts->(List.revacc),nonGts,pcurletcommon_remaining_infix_tokenpcur=letpnext=advancepcur1infunction|['-']->Some(Reason_parser.MINUS,pcur,pnext)|['-';'.']->Some(Reason_parser.MINUSDOT,pcur,advancepnext1)|['+']->Some(Reason_parser.PLUS,pcur,pnext)|['+';'.']->Some(Reason_parser.PLUSDOT,pcur,advancepnext1)|['!']->Some(Reason_parser.BANG,pcur,pnext)|['>']->Some(Reason_parser.GREATER,pcur,pnext)|['<']->Some(Reason_parser.LESS,pcur,pnext)|_->Noneletrecdecompose_tokenpos0split=letpcur=advancepos01inletpnext=advancepos02inmatchsplitwith(* Empty token is a valid decomposition *)|[]->None|'='::tl->leteq=(Reason_parser.EQUAL,pcur,pnext)inlet(revFirstTwo,tl,pcur,_pnext)=matchtlwith|'?'::tlTl->[(Reason_parser.QUESTION,pcur,pnext);eq],tlTl,pnext,(advancepnext1)|_->[eq],tl,pcur,pnextiniftl==[]thenSome(List.revrevFirstTwo)else(matchcommon_remaining_infix_tokenpcurtlwith|None->None|Some(r)->Some(List.rev(r::revFirstTwo)))(* For type parameters type t<+'a> = .. *)|'<'::tl->letless=[Reason_parser.LESS,pcur,pnext]iniftl==[]thenSomelesselse(matchcommon_remaining_infix_tokenpcurtlwith|None->None(* Couldn't parse the non-empty tail - invalidates whole thing *)|Some(r)->Some(List.rev(r::less)))|'>'::_tl->(* Recurse to take advantage of all the logic in case the remaining
* begins with an equal sign. *)letgt_tokens,rest_split,prest=split_greaters[]pcursplitinifrest_split==[]thenSomegt_tokenselse(matchdecompose_tokenprestrest_splitwith|None->None(* Couldn't parse the non-empty tail - invalidates whole thing *)|Some(r)->Some(List.revgt_tokens@r))|_->Noneletrecinit_tailrec_auxaccinf=ifi>=nthenaccelseinit_tailrec_aux(fi::acc)(i+1)nfletlist_initlenf=List.rev(init_tailrec_aux[]0lenf)letexplodes=list_init(String.lengths)(String.gets)lettry_split_label(tok_kind,pos0,_posn)=matchtok_kindwith|Reason_parser.INFIXOP0s->(matchdecompose_tokenpos0(explodes)with|None->[]|Some(l)->l)|_->[](* Logic for attempting to consume a token
and try alternatives on failure *)letstepparsertoken=matchStep.offerparsertokenwith|(Success_|Intermediate_)asstep->step|Error->lettry_alternative_tokens=function|[]->Error|tokens->matchoffer_manyparsertokenswith|(Step.Intermediate_|Step.Success_)asresult->result(* Alternative failed... Return original failure *)|Step.Error->Errorinletalternative=matchtokenwith|tok_kind,pos,_whentry_insert_semi_ontok_kind->try_alternative_tokens[(Reason_parser.SEMI,pos,pos);token]|_->try_alternative_tokens(try_split_labeltoken)inmatchalternative,tokenwith|Error,(Reason_parser.DOCSTRINGtext,startp,endp)->Intermediate(Step.add_docstringtextstartpendpparser)|_->alternative(* Interface for recovery *)letrecover=Step.recoverletrecovery_env=Step.recovery_env