我在OCaml中實現了一種符號語言,並且一直在努力將我的s表達式樹翻譯成抽象語法樹。在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表達式樹更深?我甚至開放閱讀更好的解決方案來翻譯兩棵樹。
這是一個有趣的觀察。我認爲這也可能是解決這個問題的方法。在接受答案之前,我想清楚地理解你。實質上,你的建議是在兩棵樹之間創建一個一對一的映射關係?看起來很合理。但是爲什麼定義一個樹結構對於反覆的AST是非常必要的?我的印象是,對於符號語法來說,AST節點都是原子。我認爲s表達式列表類型只是作爲指令來深入到AST中。我誤解了這一點? – jdmartin86
定義節點與定義樹不同。因爲需要在語法樹中存儲無限量的信息,並且非遞歸類型只能存儲有限數量,所以需要遞歸。當然,你可以單獨定義一個參數化的'tree'類型,然後使用'node tree',其中'node'不是遞歸的,''tree''是。這就是'Sexp.expr'正在做兩個不同類型的聲明。 – chi