2009-12-02 54 views
3

我正在写一个简单的小型ocaml程序,它从文件中读取代数语句,使用ocamllex/ocamlyacc将其解析为AST,将其缩小并打印出来。我减少表情的部分似乎有点......很难看。有什么办法可以简化它吗?如何简化这个ocaml模式匹配代码?

(* ocaml doesn't seem to be able to take arithmetic operators 
as functions, so define these wrappers for them *) 
let add x y = 
    x + y 

let sub x y = 
    x - y 

let mul x y = 
    x * y 

let div x y = 
    x/y 

(* Are term1 and term2 both ints? *) 
let both_ints term1 term2 = 
    match (term1, term2) with 
    | (Term (Number x), Term (Number y)) -> true 
    | (_, _) -> false 

(* We know that both terms are reducable to numbers, so combine 
    them *) 
let combine_terms func x y = 
    match (x, y) with 
     (Term (Number t1), Term (Number t2)) -> 
     (Term (Number (func t1 t2))) 
    | (_, _) -> raise InvalidArg 

(* Reduce the expression as much as possible *) 
let rec reduce_expr expr = 
    match expr with 
     Plus (x, y) -> 
     let reduced_x = reduce_expr x 
     and reduced_y = reduce_expr y in 
     if both_ints reduced_x reduced_y then 
     (combine_terms add reduced_x reduced_y) 
     else 
     Plus (reduced_x, reduced_y) 
    | Minus (x, y) -> 
     let reduced_x = reduce_expr x 
     and reduced_y = reduce_expr y in 
     if both_ints reduced_x reduced_y then 
     (combine_terms sub reduced_x reduced_y) 
     else 
     Minus (reduced_x, reduced_y) 
    | Multiply (x, y) -> 
     let reduced_x = reduce_expr x 
     and reduced_y = reduce_expr y in 
     if both_ints reduced_x reduced_y then 
     (combine_terms mul reduced_x reduced_y) 
     else 
     Multiply (reduced_x, reduced_y) 
    | Divide (x, y) -> 
     let reduced_x = reduce_expr x 
     and reduced_y = reduce_expr y in 
     if both_ints reduced_x reduced_y then 
     (combine_terms div reduced_x reduced_y) 
     else 
     Divide (reduced_x, reduced_y) 
    | Term x -> Term x 
+7

注意ocaml的确实需要的算术运算符作为函数:使用(/),(+)(*)和( - )...该()是强制性的,该空间只强制用于* – 2009-12-02 17:46:31

+0

仅供分析之用,menhir值得考虑。 http://cristal.inria.fr/~fpottier/menhir/ – LB40 2009-12-03 13:42:18

+0

其实,我一直在使用ocamlyacc,通常我会使用menhir,但是我想保持简单的依赖。 – 2009-12-03 14:43:43

回答

6

可以删除both_ints,和combine_terms功能以及一些if语句,通过匹配包含操作功能内Number,如类型:

let div x y = match x,y with 
    | Number x, Number y -> Number (x/y) 
    | _ -> Divide (x,y) 

... 
let rec reduce_expr expr = match expr with 
    ... 
    | Divide (x,y) -> div (reduce_expr x) (reduce_expr y) 
    ... 
+0

这是100%更清晰。谢谢! – 2009-12-02 19:29:56