123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227openFmlib_stdtypeassoc=|Left|Righttypeinfo={precedence:int;associativity:assoc;}letleft(p:int):info=assert(0<=p);{precedence=p;associativity=Left;}letright(p:int):info=assert(0<=p);{precedence=p;associativity=Right;}moduleMap=structincludeBtree.Map(Char)letfindcmap=matchfind_optcmapwith|None->assertfalse|Somer->rendletoperators:string="+-*/^!&|"letmap:'infoMap.t=letopenMapinempty|>add'|'(left10)|>add'&'(left20)|>add'!'(left30)|>add'+'(left40)|>add'-'(left40)|>add'*'(left50)|>add'/'(left50)|>add'^'(right60)letis_left0(o1:char)(o2:char):bool=leti1=Map.findo1mapandi2=Map.findo2mapini1.precedence>i2.precedence||(i1.precedence=i2.precedence&&i1.associativity=Left)moduleCP=Character.Make(Unit)(String)(String)openCPletis_left(a:char)(b:char):boolt=return(is_left0ab)letoperator:chart=one_of_charsoperators("one of \""^operators^"\"")letmake_unary(u:char)(a:string):stringt=return("("^String.oneu^a^")")letmake_binary(a:string)(o:char)(b:string):stringt=return("("^a^String.oneo^b^")")letprimary:stringt=mapString.oneletterletlpar:chart=(let*_=char'('inreturn')')</>(let*_=char'['inreturn']')</>(let*_=char'{'inreturn'}')letrpar(p:char):chart=charp(func->c=p)("'"^String.onep^"'")letrecexp():stringt=letprim()=parenthesized(fun_a_->returna)lparexprpar</>primaryinoperator_expression(prim())(Someoperator)operatoris_leftmake_unarymake_binaryletparse:Parser.t=make()(exp())let%test_=letp=Parser.run_on_string"a"parseinParser.(has_succeededp&&columnp=1&&finalp="a")let%test_=letp=Parser.run_on_string"a+-b+c"parseinParser.(has_succeededp&&finalp="((a+(-b))+c)")let%test_=letp=Parser.run_on_string"a+b*c"parseinParser.(has_succeededp&&finalp="(a+(b*c))")let%test_=letp=Parser.run_on_string"[a*{b+[[[(((c)))]]]}]^d"parseinParser.(has_succeededp&&finalp="((a*(b+c))^d)")let%test_=letp=Parser.run_on_string"a*-b*c"parseinParser.(has_succeededp&&finalp="(a*(-(b*c)))")let%test_=letp=Parser.run_on_string"a+b^c^d"parseinParser.(has_succeededp&&finalp="(a+(b^(c^d)))")let%test_=letp=Parser.run_on_string"a+b*c^d"parseinParser.(has_succeededp&&finalp="(a+(b*(c^d)))")let%test_=letp=Parser.run_on_string"a+!b+c"parseinParser.(has_succeededp&&finalp="(a+(!(b+c)))")