Я хотел бы преобразовать строку, содержащую действительное выражение 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.
String
может быть "[1,2,3]."
, или "begin A=4, B=2+3, [A,B] end."
, или что-либо подобное.
(Обратите внимание, что это всего лишь пример того, что я хотел бы сделать, поэтому оценка String
для меня не вариант).
ИЗМЕНИТЬ
Указание ListAST, как показано ниже, генерирует огромную ошибку-орграфа-ошибки-монстра и говорит "внутренняя ошибка в 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),