68 lines
2.4 KiB
OCaml
68 lines
2.4 KiB
OCaml
|
|
type expr
|
|
= Const of int
|
|
| Add of expr * expr
|
|
| Mul of expr * expr
|
|
| Sub of expr * expr
|
|
| Div of expr * expr
|
|
|
|
let rec show_expr (e:expr): string =
|
|
match e with
|
|
| Const i -> string_of_int i
|
|
| Add (a, b) -> "(" ^ (show_expr a) ^ "+" ^ (show_expr b) ^ ")"
|
|
| Mul (a, b) -> "(" ^ (show_expr a) ^ "*" ^ (show_expr b) ^ ")"
|
|
| Sub (a, b) -> "(" ^ (show_expr a) ^ "-" ^ (show_expr b) ^ ")"
|
|
| Div (a, b) -> "(" ^ (show_expr a) ^ "/" ^ (show_expr b) ^ ")"
|
|
|
|
let rec show_pretty_expr (e:expr): string =
|
|
let add_sub_left (e:expr): bool =
|
|
match e with
|
|
| Const i -> false
|
|
| Add (a, b) -> false
|
|
| Sub (a, b) -> false
|
|
| Mul (a, b) -> false
|
|
| Div (a, b) -> false in
|
|
let mul_div_left (e:expr): bool =
|
|
match e with
|
|
| Const i -> false
|
|
| Add (a, b) -> true
|
|
| Sub (a, b) -> true
|
|
| Mul (a, b) -> false
|
|
| Div (a, b) -> false in
|
|
let needs_paren_left (e:expr): bool =
|
|
match e with
|
|
| Const i -> raise (Failure "This shouldn't be called here.")
|
|
| Add (a, b) -> add_sub_left a
|
|
| Sub (a, b) -> add_sub_left a
|
|
| Mul (a, b) -> mul_div_left a
|
|
| Div (a, b) -> mul_div_left a in
|
|
let add_sub_right (add:bool) (e:expr): bool =
|
|
match e with
|
|
| Const i -> false
|
|
| Add (a, b) -> add
|
|
| Sub (a, b) -> true
|
|
| Mul (a, b) -> false
|
|
| Div (a, b) -> false in
|
|
let mul_div_right (mul:bool) (e:expr): bool =
|
|
match e with
|
|
| Const i -> false
|
|
| Add (a, b) -> true
|
|
| Sub (a, b) -> true
|
|
| Mul (a, b) -> mul
|
|
| Div (a, b) -> true in
|
|
let needs_paren_right (e:expr): bool =
|
|
match e with
|
|
| Const i -> raise (Failure "This shouldn't be called here.")
|
|
| Add (a, b) -> add_sub_right true b
|
|
| Sub (a, b) -> add_sub_right false b
|
|
| Mul (a, b) -> mul_div_right true b
|
|
| Div (a, b) -> mul_div_right false b in
|
|
let wrap (b:bool) (s:bytes): bytes =
|
|
(if b then "(" else "") ^ s ^ (if b then ")" else "") in
|
|
match e with
|
|
| Const i -> string_of_int i
|
|
| Add (a, b) -> wrap (needs_paren_left e) (show_pretty_expr a) ^ "+" ^ wrap (needs_paren_right e) (show_pretty_expr b)
|
|
| Sub (a, b) -> wrap (needs_paren_left e) (show_pretty_expr a) ^ "-" ^ wrap (needs_paren_right e) (show_pretty_expr b)
|
|
| Mul (a, b) -> wrap (needs_paren_left e) (show_pretty_expr a) ^ "*" ^ wrap (needs_paren_right e) (show_pretty_expr b)
|
|
| Div (a, b) -> wrap (needs_paren_left e) (show_pretty_expr a) ^ "/" ^ wrap (needs_paren_right e) (show_pretty_expr b)
|
|
|