我试图进行一些简单的语义分析,并且很难正确设置模式匹配。这是我实际代码的一个淡化示例,但它仍然捕获了这个想法。
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
答案 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
还有更多代码,但这至少与回答这个问题有关。