(* Baseline: recursive-descent calculator for "+", "*", parens, ints. *) type expr = | Lit of int | Add of expr * expr | Mul of expr * expr ;; let parse_input src = let pos = ref 0 in let peek () = if !pos < String.length src then String.get src !pos else "" in let advance () = pos := !pos + 1 in let skip_ws () = while !pos < String.length src && peek () = " " do advance () done in let rec parse_atom () = skip_ws () ; if peek () = "(" then begin advance () ; let e = parse_expr () in skip_ws () ; advance () ; (* consume ')' *) e end else let start = !pos in let rec digits () = if !pos < String.length src then let c = peek () in if c >= "0" && c <= "9" then begin advance () ; digits () end else () in digits () ; let n = Int.of_string (String.sub src start (!pos - start)) in Lit n and parse_term () = skip_ws () ; let lhs = ref (parse_atom ()) in let rec loop () = skip_ws () ; if peek () = "*" then begin advance () ; lhs := Mul (!lhs, parse_atom ()) ; loop () end in loop () ; !lhs and parse_expr () = skip_ws () ; let lhs = ref (parse_term ()) in let rec loop () = skip_ws () ; if peek () = "+" then begin advance () ; lhs := Add (!lhs, parse_term ()) ; loop () end in loop () ; !lhs in parse_expr () ;; let rec eval e = match e with | Lit n -> n | Add (a, b) -> eval a + eval b | Mul (a, b) -> eval a * eval b ;; (* (1 + 2) * 3 + 4 = 9 + 4 = 13 *) eval (parse_input "(1 + 2) * 3 + 4")