123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100openFmlibopenCommontypeassoc=|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. *)letcolon=(30,Right)letarrow=(40,Right)letassign=(41,No)letlambda=(42,No)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)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))