Erlang 我对erl_parse:parse_form有什么错?

Erlang 我对erl_parse:parse_form有什么错?,erlang,Erlang,我编写了一个Hello World模块并成功编译了它。然后我试着通过使用erl_扫描和erl_解析来学习引擎盖下的东西 -module(useless). -export([hello/0]). hello() -> io:format("hello world\n"). 然后我输入erls

我编写了一个Hello World模块并成功编译了它。然后我试着通过使用erl_扫描和erl_解析来学习引擎盖下的东西

-module(useless).                                                    
-export([hello/0]).                                               

hello() -> io:format("hello world\n").
然后我输入
erl
shell

{ok, S} = file:read_file("useless.erl").

它显然很好用。但是,当我尝试使用
erl\u parse:parse\u form(T)时。

它给出了
{error,{2,erl_parse,[“前面的语法错误:”,“-”]}

我做错了什么

编辑: 该模块很有帮助


也很酷。

函数erl\u parse:parse\u form/1只在一种表单上工作。因此,您必须首先将erl_scan:string/1的结果拆分为各个表单

您可以使用erl_scan:tokens来实现这一点(此代码有效,但我不确定我是否正确使用了该函数):

-模块(无用)。
-出口([eval/1])。
评估(文件)->
{ok,B}=file:read_file(file),
表单=扫描(erl\U扫描:令牌([],二进制\U到\U列表(B),1),[]),
F=fun(X)->{ok,Y}=erl_parse:parse_form(X),Y end,
[F(X)| | X
扫描(erl|U扫描:令牌([],S,N),[T|Res]);
扫描(分辨率)->
列表:反向(Res)。

罗伯特建议使用
erl_scan:tokens/3
的重入功能。 此函数上的文档不明确,我花了一些时间才理解初始字符串需要通过
eof
关闭(如果不是,则tokens函数运行一个无止境的循环)

这是我终于想出的代码,希望能对别人有所帮助

eval(File)->
    {ok, Data} = file:read_file(File),
    String=erlang:binary_to_list(Data),
    scan(String).

scan(String) when is_list(String)->
    scan(String++eof,[]). %% appended eof

scan({done, Result, LeftOverChars},Acc)->
    scan_done(Result,LeftOverChars,Acc);
scan({more, Continuation},Acc)->
    scan(erl_scan:tokens(Continuation,[],1),Acc);
scan(String,Acc) when is_list(String)->
    scan(erl_scan:tokens([],String,1),Acc).

scan_done({error,ErrorMsg,_Location},_LeftOverChars,_Acc)->
    ErrorMsg;
scan_done({eof,Location},LeftOverChars,Acc)->
    Acc;
scan_done({ok,Tokens,Location},LeftOverChars,Acc)->
    case erl_parse:parse_form(Tokens) of
    {ok,R}->scan(LeftOverChars,Acc++[R]);
    {error,R}->scan(LeftOverChars,R)
    end.

erl_scan:tokens/3
是可重入的,因此它可以处理以块的形式输入字符,并继续收集,直到获得所需的所有字符(最多一个“.”)。您不以这种方式使用它,但您使用它的方式是有效的。您可以做的一个改进是在
{ok,Ts,line}中获取从
erl\u scan:tokens
返回的行号
返回值,并在下一次调用
erl\u scan:tokens
时使用该值。我根据Robert的建议修改了代码。希望它的效果更好:o)因为结果中的行号现在是正确的。
-module(useless).                                                    
-export([eval/1]).                                               

eval(File) -> 
    {ok, B} = file:read_file(File),
    Forms = scan(erl_scan:tokens([],binary_to_list(B),1),[]),
    F = fun(X) -> {ok,Y} = erl_parse:parse_form(X), Y end,
    [F(X) || X <- Forms].

scan({done,{ok,T,N},S},Res) ->
    scan(erl_scan:tokens([],S,N),[T|Res]);
scan(_,Res) ->
    lists:reverse(Res).
eval(File)->
    {ok, Data} = file:read_file(File),
    String=erlang:binary_to_list(Data),
    scan(String).

scan(String) when is_list(String)->
    scan(String++eof,[]). %% appended eof

scan({done, Result, LeftOverChars},Acc)->
    scan_done(Result,LeftOverChars,Acc);
scan({more, Continuation},Acc)->
    scan(erl_scan:tokens(Continuation,[],1),Acc);
scan(String,Acc) when is_list(String)->
    scan(erl_scan:tokens([],String,1),Acc).

scan_done({error,ErrorMsg,_Location},_LeftOverChars,_Acc)->
    ErrorMsg;
scan_done({eof,Location},LeftOverChars,Acc)->
    Acc;
scan_done({ok,Tokens,Location},LeftOverChars,Acc)->
    case erl_parse:parse_form(Tokens) of
    {ok,R}->scan(LeftOverChars,Acc++[R]);
    {error,R}->scan(LeftOverChars,R)
    end.