Source file parenthesize.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
open Spotlib.Spot
(** Primitive operators *)
type assoc = Left | Right | Noassoc
type level = float
type 'a t = assoc -> level -> 'a
type 'a t_ = 'a t
include Monad.Make(struct
type 'a t = 'a t_
let bind at f = fun a l -> f (at a l) a l
let return a = fun _ _ -> a
end)
module Make(A : sig
type t
end) = struct
type ppr = A.t t
type parens = A.t -> A.t
let left : 'a t -> 'a t = fun p _a l -> p Left l
let right : 'a t -> 'a t = fun p _a l -> p Right l
let noassoc : 'a t -> 'a t = fun p _a l -> p Noassoc l
let level : level -> 'a t -> 'a t = fun l p a _l -> p a l
let reset : 'a t -> 'a t = fun t -> noassoc (level 0.0 t)
let need_parens : assoc -> level -> bool t = fun assoc lev out_pos out_lev ->
match compare out_lev lev with
| 1 -> true
| -1 -> false
| 0 ->
begin match out_pos, assoc with
| Left, Left -> false
| Right, Right -> false
| _ -> true
end
| _ -> assert false
let maybe_parens : parens -> assoc -> level -> ppr -> ppr = fun parens assoc lev t ->
need_parens assoc lev >>= function
| true -> fmap parens & reset t
| false -> t
let atom a = return a
let binop parens build assoc lev l r =
maybe_parens parens assoc lev
& level lev
& left l >>= fun l ->
right r >>= fun r ->
return (build l r)
let list parens build lev xs =
maybe_parens parens Noassoc lev & fmap build & mapM (level lev) xs
let prefix parens build lev x =
maybe_parens parens Right lev & fmap build & level lev & right x
let postfix parens build lev x =
maybe_parens parens Left lev & fmap build & level lev & left x
let parens ps x = fmap ps & level (-1.0) x
end