123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113openFmlibopenCommontypeassoc=|Left|Right|Notypet=int*assoc(* Invariant: The same precedence leads to the same assoc
i.e. the precedence is the key to the operator group which
are considered equivalent. *)letwhere=(20,Left)letassign=(25,Right)letcolon=(30,Right)letarrow=(40,Right)letpush_arg=(45,Left)letpull_arg=(46,Right)letrelation=(50,No)letaddition=(60,Left)letmultiplication=(61,Left)letexponentiation=(62,Right)letunknown=(100,Left)letapplication=(200,Left)(* Precedences:
expression parse requirement
--------------------------------------------------------------
exp: A -> B exp: (A -> B) colon < arrow
\x := exp: T \x := (exp: T) assign < colon
\x y := x => y \x y := (x => y)
*)letmap:(int*assoc)String_map.t=letopenString_mapinempty|>add"->"arrow|>add"=>"arrow|>add":="assign|>add":"colon|>add"|>"push_arg|>add"<|"pull_arg|>add"="relation|>add"/="relation|>add"<"relation|>add">"relation|>add"<="relation|>add">="relation|>add"+"addition|>add"-"addition|>add"*"multiplication|>add"/"multiplication|>add"^"exponentiationletof_string(op:string):t=matchString_map.maybe_findopmapwith|None->unknown|Somed->dletcompare((prec1,_):t)((prec2,_):t):int=Stdlib.compareprec1prec2letprecedence=fstletassociativity=sndletneeds_parens(lower:toption)(is_left:bool)(upper:t):bool=matchlowerwith|None->false|Some(low_prec,low_assoc)->letprec,assoc=upperinassert(prec<>low_prec||low_assoc=assoc);prec>low_prec||(prec=low_prec(* because of the invariant lower and upper have the
same associativity. *)&&(matchassocwith|No->true|Left->notis_left|Right->is_left))