E -> T | T + E | T - E
T -> F | F * T | F / T
F -> id | (E)

type token = Id of string | LParen | RParen | Times | Divide | Plus | Minus;;

type e = E2T of t | PlusExp of (t*e) | MinusExp of (t*e)
and t = T2F of f | MultExp of (f*t) | DivExp of (f*t)
and f = I of string | ParenExp of e;;

let rec e_parse tokens = 
           match (t_parse tokens) with
              (term, tok_after_term) -> (match tok_after_term with
                                             Plus :: tok_after_plus -> (match (e_parse tok_after_plus) with
                                                                            (e, tok_after_e) -> (PlusExp (term, e), tok_after_e))
                                           | Minus::tok_after_minus -> (match (e_parse tok_after_minus) with
                                                                            (e, tok_after_e) -> (MinusExp (term, e), tok_after_e)) 
                                           | _ -> (E2T term, tok_after_term))       
             | _ -> failwith "Error 1"
and t_parse tokens = 
            match (f_parse tokens) with
              (f, tok_after_f) -> (match tok_after_f with
                                            Times :: tok_after_times -> (match (t_parse tok_after_times) with
                                                                            (t, tok_after_t) -> (MultExp (f, t), tok_after_t))    
                                           | Divide::tok_after_div -> (match (t_parse tok_after_div) with
                                                                            (t, tok_after_t) -> (DivExp (f, t), tok_after_t))
                                           | _ -> (T2F f, tok_after_f))
             | _ -> failwith "Error 2"
and f_parse tokens = 
            match tokens with
               Id s :: tok_after_id -> (I s, tok_after_id)
             |  LParen::tok_after_lparen -> (match (e_parse tok_after_lparen) with
                                               (e, tok_after_e) -> (match tok_after_e with 
                                                                        RParen::tok_after_rparen -> (ParenExp e, tok_after_rparen) 
                                                                       | _ -> failwith "Error 3")
                                               | _ -> failwith "Error 4" )
            | _ -> failwith "Error 5";;   
    

[LParen;Id "x"; Times; Id "y";RParen]