【发布时间】:2020-04-06 11:02:40
【问题描述】:
我想将包含有效 Erlang 表达式的字符串转换为其抽象语法树表示,但目前没有任何成功。
下面是我想做的一个例子。编译后,所有z:z().生成模块zed,通过调用zed:zed().返回在给定列表上应用lists:reverse的结果。
-module(z).
-export([z/0]).
z() ->
ModuleAST = erl_syntax:attribute(erl_syntax:atom(module),
[erl_syntax:atom("zed")]),
ExportAST = erl_syntax:attribute(erl_syntax:atom(export),
[erl_syntax:list(
[erl_syntax:arity_qualifier(
erl_syntax:atom("zed"),
erl_syntax:integer(0))])]),
%ListAST = ?(String), % This is where I would put my AST
ListAST = erl_syntax:list([erl_syntax:integer(1), erl_syntax:integer(2)]),
FunctionAST = erl_syntax:function(erl_syntax:atom("zed"),
[erl_syntax:clause(
[], none,
[erl_syntax:application(
erl_syntax:atom(lists),
erl_syntax:atom(reverse),
[ListAST]
)])]),
Forms = [erl_syntax:revert(AST) || AST <- [ModuleAST, ExportAST, FunctionAST]],
case compile:forms(Forms) of
{ok,ModuleName,Binary} -> code:load_binary(ModuleName, "z", Binary);
{ok,ModuleName,Binary,_Warnings} -> code:load_binary(ModuleName, "z", Binary)
end.
String 可以是"[1,2,3].",或"begin A=4, B=2+3, [A,B] end.",或任何类似的东西。
(请注意,这只是我想做的一个例子,所以评估String 对我来说不是一个选项。)
编辑:
如下指定 ListAST 会生成一个巨大的 dict-digraph-error-monster,并显示“lint_module 中的内部错误”。
String = "[1,2,3].",
{ok, Ts, _} = erl_scan:string(String),
{ok, ListAST} = erl_parse:parse_exprs(Ts),
EDIT2:
此解决方案适用于简单的术语:
{ok, Ts, _} = erl_scan:string(String),
{ok, Term} = erl_parse:parse_term(Ts),
ListAST = erl_syntax:abstract(Term),
【问题讨论】:
-
现在我查看了代码,显然我混淆了 erl_syntax 和 erl_parse 格式......但仍然无法弄清楚如何做到这一点(典型的太多 bejgli 错误)。
-
是的,如果您将 ListAST 与 erl_syntax 制作的 ListAST 进行比较,它们看起来并不那么相似 :( 42> ListAST. [{cons,1,{integer,1,1},{cons, 1,{integer,1,2},{nil,1}}}] 43> erl_syntax:list([1, 2, 3], []). {tree,list,{attr,0,[],none },{列表,[1,2,3],[]}} 44>
-
所以我要么需要一种方法来从字符串中创建一个与
erl_syntax兼容的 AST,要么需要一种方法将一个占位符放在erl_syntax的东西上,并在调用revert()后替换它。或者我遗漏了一些明显的东西...... -
添加以下来自 erl_syntax 手册的注释:“这意味着所有 erl_parse 树都是有效的抽象语法树......”
-
不,我只是认为它没有正确标记,所以你输入 [{cons, 1, ...]] 并且它期望 {tree, something} 与 [{缺点,1,...}] :(
标签: erlang abstract-syntax-tree