字符串到抽象语法树

Zed*_*Zed 10 erlang abstract-syntax-tree

我想将包含有效Erlang表达式的字符串转换为其抽象语法树表示,到目前为止没有任何成功.

以下是我想做的一个例子.编译后,alling 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.
Run Code Online (Sandbox Code Playgroud)

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),
Run Code Online (Sandbox Code Playgroud)

编辑2:

此解决方案适用于简单的术语:

{ok, Ts, _} = erl_scan:string(String),
{ok, Term} = erl_parse:parse_term(Ts),
ListAST = erl_syntax:abstract(Term),
Run Code Online (Sandbox Code Playgroud)

Ric*_*rdC 5

在您的编辑示例中:

String = "[1,2,3].",
{ok, Ts, _} = erl_scan:string(String),
{ok, ListAST} = erl_parse:parse_exprs(Ts),
Run Code Online (Sandbox Code Playgroud)

ListAST实际上是AST:s的列表(因为parse_exprs,如名称所示,解析多个表达式(每个表达式以句点结尾).由于您的字符串包含单个表达式,因此您获得了一个元素的列表.所有您需要的do匹配出来:

{ok, [ListAST]} = erl_parse:parse_exprs(Ts),
Run Code Online (Sandbox Code Playgroud)

所以它与erl_syntax(接受所有erl_parse树)无关; 只是你在ListAST周围有一个额外的列表包装器,这导致编译器呕吐.