二进制表达式的递归模式匹配,如此接近

时间:2014-08-14 23:53:14

标签: pattern-matching ocaml

我试图进行一些简单的语义分析,并且很难正确设置模式匹配。这是我实际代码的一个淡化示例,但它仍然捕获了这个想法。

type expr = LiteralInt of int 
      | LiteralString of string
      | Binop of expr * op * expr 
   and op = Add | Mult 

let rec expr_check = function 
    | Binop(LiteralInt(e1), _, LiteralString(e2)) -> false 
    | Binop(LiteralString(e1), _, LiteralInt(e2)) -> false
    | Binop(LiteralInt(e1), _, LiteralInt(e)) -> true
    | Binop(l, _, LiteralInt(a)) -> expr_check l 
    | Binop(l, _, LiteralString(a)) -> expr_check l
    | Binop(LiteralInt(e1), _, l) -> expr_check l
    | LiteralInt(a) -> true
    | LiteralString(a) -> true 

(* Should be false *)
let first_check = expr_check (Binop(LiteralInt(1), Add, LiteralString("hi")));;

(* Should be false for: 4 + 5 + "hello" *)
let second_check = expr_check (Binop(Binop(LiteralInt(4), Add, LiteralInt(5)), Add, LiteralString("hello")))

我也试过这个,但它也没有用。

let rec expr_check = function 
    | Binop(LiteralInt(e1), _, LiteralString(e2)) -> false 
    | Binop(LiteralString(e1), _, LiteralInt(e2)) -> false
    | Binop(LiteralInt(e1), _, LiteralInt(e)) -> true
    | Binop(l, _, b) -> expr_check l && expr_check b
    | LiteralInt(a) -> true
    | LiteralString(a) -> true 

2 个答案:

答案 0 :(得分:3)

在我看来,您需要传播有关子树类型(使用您的语言)的信息。你不能像你似乎正在做的那样只是与文字进行比较。有时候,子树都不是文字。

您可以使用花哨的OCaml类型将您的语言类型提取到OCaml类型系统中。但直接的方法是将类型作为值。

type mytype = Mystring | Myinteger

<强>更新

这就是我所说的。我是否正确是另一回事: - )

让我们说你的输入看起来像这样(通常的表达形式):

(&#34; abc&#34; +&#34; def&#34;)+(3 + 5)

据我所知,你的模式都不会注意到这是错误的。内部节点的正确性不仅仅基于子节点的正确性。它取决于子节点的类型

答案 1 :(得分:0)

好的,基于Jeffrey的答案以及对IRC的一些帮助,感谢Drup!,这是我最终做的一部分。

exception SemanticError of string 
type typ = TInt | TString
(* Not an exhaustive match *)
let rec infer_typ = function
  | LiteralInt _ -> TInt
  | LiteralString _ -> TString
  | Binop (e1, op, e2) ->
      let (t1, t2, ret_typ) = infer_op_typ op in
      if check_expr e1 t1 && check_expr e2 t2
      then ret_typ (* Make this more informative *)
      else raise (SemanticError "Type problem with: ")
  | _ -> TInt 

and infer_op_typ = function
  | Add | Mult | Sub | Mult | Div | Equal | Neq | Less | Leq | Greater | Geq -> (TInt, TInt, TInt)

and check_expr e typ =
  let inf_typ = infer_typ e in
  typ = inf_typ

还有更多代码,但这至少与回答这个问题有关。