本文介绍了如何将具有有效 Erlang 表达式的字符串转换为抽象语法树 (AST)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I would like to convert a string containing a valid Erlang expression to its abstract syntax tree representation, without any success so far.

下面是我想做的一个例子.编译后,所有z:z().生成模块zed,通过调用zed:zed().返回应用lists:reverse 在给定的列表上.

Below is an example of what I would like to do. After compiling, alling z:z(). generates module zed, which by calling zed:zed(). returns the result of applying lists:reverse on the given list.

-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] 结束." 或类似的东西.

String could be "[1,2,3].", or "begin A=4, B=2+3, [A,B] end.", or anything alike.

(请注意,这只是我想做的一个例子,所以评估 String 对我来说不是一个选择.)

(Note that this is just an example of what I would like to do, so evaluating String is not an option for me.)

编辑:

如下指定 ListAST 会生成一个巨大的 dict-digraph-error-monster,并显示lint_module 中的内部错误".

Specifying ListAST as below generates a huge dict-digraph-error-monster, and says "internal error in lint_module".

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

EDIT2:

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

This solution works for simple terms:

{ok, Ts, _} = erl_scan:string(String),
{ok, Term} = erl_parse:parse_term(Ts),
ListAST = erl_syntax:abstract(Term),

推荐答案

在您的编辑示例中:

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

ListAST 实际上是一个 AST:s 列表(因为 parse_exprs,顾名思义,解析多个表达式(每个都以句点结尾).由于您的字符串包含单个表达式,因此您得到了一个包含一个元素的列表.所有你需要做的是匹配:

the ListAST is actually a list of AST:s (because parse_exprs, as the name indicates, parses multiple expressions (each terminated by a period). Since your string contained a single expression, you got a list of one element. All you need to do is match that out:

{ok, [ListAST]} = erl_parse:parse_exprs(Ts),

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

so it has nothing to do with erl_syntax (which accepts all erl_parse trees); it's just that you had an extra list wrapper around the ListAST, which caused the compiler to puke.

这篇关于如何将具有有效 Erlang 表达式的字符串转换为抽象语法树 (AST)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-03 18:00