我在OCaml中实现了一种符号语言,并且一直在努力将我的s表达式树转换为抽象语法树。
s表达式树是
(* sexpr.mli *)
type atom =
| Atom_unit
| Atom_int of int
| Atom_sym of string
type expr =
| Expr_atom of atom
| Expr_list of expr list
抽象语法树是
(* ast.ml *)
open Sexpr
type sym = string
(* abstract syntax tree nodes *)
type expr =
| Expr_unit
| Expr_int of int
| Expr_sym of sym
(* Sexp.atom -> Ast.expr *)
let ast_of_atom a =
match a with
| Atom_unit -> Expr_unit
| Atom_int n -> Expr_int n
| Atom_sym s -> Expr_sym s
(* Sexp.expr -> Ast.expr *)
let rec ast_of_sexpr sx = match sx with
| Expr_atom a -> ast_of_atom a
| Expr_list l ->
match l with
| [] -> ast_of_atom Atom_unit
| [x] -> ast_of_sexpr x
| h::t -> ignore ( ast_of_sexpr h ); ast_of_sexpr ( Expr_list t )
函数ast_of_sexpr
需要符合类型签名
val ast_of_sexpr : Sexpr.expr -> expr
。
这是我的挑战;我无法找到符合类型签名的方法来递归到s表达式树(即嵌套列表)并将s表达式树节点转换为抽象语法树节点。
在一个理想的世界中,我可以评估列表头并在一个表达式中对尾部进行递归。我试图通过测序来模仿这个理想。但是,当然,这会忽略左侧值,并且只会在打印经过分析的标记流时输出最后一个值。
任何人都可以建议一种评估列表头的方法,而不忽略值,并在s-expression树中更深入地递归?我甚至愿意阅读更好的解决方案来翻译两棵树。
答案 0 :(得分:4)
Ast.expr
类型定义看起来错误:它不代表抽象语法树,而只代表原子表达式的语法。这是因为类型根本不是递归的,所以很难称之为树。相比之下,Sexp.expr
是一种递归类型。
我的猜测是你忘记了类型定义中的一个案例,例如:
type expr =
| Expr_unit
| Expr_int of int
| Expr_sym of sym
| Expr_call of expr list
一旦完成,两种类型实际上是相同的,因此转换变得简单。
答案 1 :(得分:2)
非常一般,这里有如何计算某些值"而不忽略它们":
let v = <calculate> in
let w = <calculate> in
<expression using v and w>
我不确定这是你问的问题,但对于以OCaml(恕我直言)开头的人来说这是一个概念上的困难。