Compiler construction OCaml中的S表达式树到抽象语法树
我正在用OCaml实现一种符号语言,并且一直在努力将我的s表达式树转换为抽象语法树 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
(* 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