在OCaml中的S表达式树到抽象语法树

时间:2014-03-30 16:14:23

标签: compiler-construction ocaml abstract-syntax-tree s-expression

我在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树中更深入地递归?我甚至愿意阅读更好的解决方案来翻译两棵树。

2 个答案:

答案 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(恕我直言)开头的人来说这是一个概念上的困难。