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

Compiler construction OCaml中的S表达式树到抽象语法树,compiler-construction,ocaml,abstract-syntax-tree,s-expression,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 = str

我正在用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 )
_sexpr的函数
ast_需要与类型签名一致

val ast\u of_sexpr:sexpr.expr->expr

这是我的挑战;我无法找到一种符合类型签名的方法来递归到s表达式树(即嵌套列表)中,并将s表达式树节点转换为抽象语法树节点

在理想情况下,我可以在一个表达式中计算列表头并在尾部递归。我试着用排序来模拟这个理想。但这当然会忽略左侧值,并且在打印解析的令牌流时只输出最后一个值


有人能建议一种方法来计算列表头,而不忽略值,并递归到s表达式树的更深处吗?我甚至愿意阅读更好的在两棵树之间进行转换的解决方案。

一般来说,这里介绍了如何“不忽略它们”地计算一些值:

让v=in
让w=in

我不确定这是否是您要问的,但对于从OCaml(IMHO)开始的人来说,这是一个概念上的困难。

Ast.expr
类型定义看起来是错误的:它不表示抽象语法树,而仅表示原子表达式的语法。这是因为类型根本不是递归的,所以它很难被称为树。相比之下,
Sexp.expr
是一种递归类型

我猜您在类型定义中忘记了一个case,例如:

type expr =
   | Expr_unit
   | Expr_int    of int
   | Expr_sym    of sym
   | Expr_call   of expr list

一旦完成,这两种类型实际上是相同的,因此转换变得简单。

这是一个有趣的观察结果。我认为这也可能是解决这个问题的方法。在接受答案之前,我想清楚地了解你。本质上,您的建议是在两棵树之间创建一对一的映射?看起来很合理。但为什么定义树结构时必须严格使用递归呢?我的印象是,对于符号语法,AST节点都是原子。我认为s-expression列表类型只是作为递归到AST更深层次的指令。我是否误解了这一点?定义节点与定义树不是一回事。递归是必需的,因为您需要在语法树中存储无限量的信息,而非递归类型只能存储有限量的信息。当然,您可以单独定义一个参数化的
类型,然后使用
节点树
,其中
节点
不是递归的,而
是树
。这就是
Sexp.expr
使用两种不同类型声明所做的。
type expr =
   | Expr_unit
   | Expr_int    of int
   | Expr_sym    of sym
   | Expr_call   of expr list