123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118typelocation=Lexing.position*Lexing.positiontypeassociativity=Left|Right|NonAsstypefixity=Prefix|Infixof(int*associativity)typeterm=|Varofstring|Cstofstring|Appof(term*term)|Absof(string*term)letrecto_string=function|Varx->x|Cstx->x|App(t,u)->Printf.sprintf"(%s %s)"(to_stringt)(to_stringu)|Abs(x,t)->Printf.sprintf"(lambda %s. %s)"x(to_stringt)moduleSMap=UtilsLib.Utils.StringMaptypesig_info=fixitySMap.tlettest_sig=List.fold_left(funacc(name,prec)->SMap.addnameprecacc)SMap.empty[("+",Infix(5,Left));("-",Infix(4,Left));("*",Infix(7,Left));("/",Infix(6,Left));("~",Prefix);("!",Prefix);]letget_fixitysymsignature=SMap.findsymsignaturetypetoken=Termofterm|Opof(string*fixity)lettok_to_string=functionTermt->to_stringt|Op(x,_)->xletis_infix=functionInfix_->true|_->falseletis_prefix=functionPrefix->true|_->falseletlower_thanf1f2=match(f1,f2)withInfix(p1,_),Infix(p2,_)->p1<p2|_->falseletnext=function[]->(None,[])|a::tl->(Somea,tl)letrecparse_sequencestacktokenstream=let()=Printf.printf"stack: '%s', token: '%s', stream: '%s'\n"(UtilsLib.Utils.string_of_list" ; "tok_to_stringstack)(matchtokenwithSomet->tok_to_stringt|None->"None")(UtilsLib.Utils.string_of_list" ; "tok_to_stringstream)inmatch(stack,token)with|[],Somet->(* shift to initiate the process *)lettoken',stream'=nextstreaminparse_sequence(t::stack)token'stream'|[Termt],None->(* sucessful parse *)t|[Term_],Sometok->(* shift *)lettoken',stream'=nextstreaminparse_sequence(tok::stack)token'stream'|Termt::Op(o,f)::tl,_whenis_prefixf->(* reduce: prefix operators have the highest precedence *)parse_sequence(Term(App(Csto,t))::tl)tokenstream|Op(_o,_f)::_tl,Sometok->(* shift. It makes sens to shift *)lettoken',stream'=nextstreaminparse_sequence(tok::stack)token'stream'|Termt2::Op(o1,f1)::Termt1::tl,Some(Op(_o2,f2))whenis_infixf1&&is_infixf2&&lower_thanf2f1->(* reduce: there are two different operators, *)(* and the first one has the highest precedence *)parse_sequence(Term(App(App(Csto1,t1),t2))::tl)tokenstream|Term_t2::Op(_o1,f1)::Term_t1::_,Some(Op(_o2,f2)astok)whenis_infixf1&&is_infixf2&&lower_thanf1f2->(* shift: there are two different operators, *)(* and the second one has the highest precedence *)lettoken',stream'=nextstreaminparse_sequence(tok::stack)token'stream'|Termt2::Op(o1,f1)::Termt1::tl,Some(Op(o2,f2))whenis_infixf1&&f1=f2->((* there is a sequence with the same operator *)matchf1with|Infix(_,Left)->(* reduce: it is left associative *)parse_sequence(Term(App(App(Csto1,t1),t2))::tl)tokenstream|Infix(_,Right)->(* shift: it is right associative *)lettoken',stream'=nextstreaminparse_sequence(Op(o2,f2)::stack)token'stream'|Infix(_,NonAss)->(* error: since it is not associative, there *)(* should not be such a sequence *)failwith(Printf.sprintf"Syntax error: Operator \"%s\" is non-associative, but here is \
used as associative"o1)|Prefix->failwith"Bug: Shouldn't happen")|Termt2::Op(o1,f1)::Termt1::tl,_whenis_infixf1->(* reduce: the operator has precedence over application *)parse_sequence(Term(App(App(Csto1,t1),t2))::tl)tokenstream|Term_t2::Op(o1,_f1)::_,_->failwith(Printf.sprintf"Parse error on \"%s\""o1)|Term_t2::Term_t1::_tl,Some(Op(o,f))->(* shift: the operator will take precedence over application *)lettoken',stream'=nextstreaminparse_sequence(Op(o,f)::stack)token'stream'|Termt2::Termt1::tl,Some(Term_)|Termt2::Termt1::tl,None->(* reduce: application can be perfomed *)parse_sequence(Term(App(t1,t2))::tl)tokenstream|_,None->(* unsuccessful parse: no token left and no reduction was performed *)failwith"Parse error"