我在erl_parse:parse_form上做错了什么?

时间:2015-01-22 08:30:53

标签: erlang

我写了一个Hello-World模块并成功编译了它。然后我尝试使用erl_scan和erl_parse来学习幕后的东西。

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

hello() -> io:format("hello world\n").

然后输入erl shell

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

{ok, T, _} = erl_scan:string(binary_to_list(S)).

显然效果很好。但是当我尝试erl_parse:parse_form(T).

它提供{error,{2,erl_parse,["syntax error before: ","'-'"]}}

我做错了什么?

编辑: 模块compile很有帮助。

同样this很酷。

2 个答案:

答案 0 :(得分:3)

函数erl_parse:parse_form / 1仅适用于一个表单。因此,您必须首先将erl_scan:string / 1的结果拆分为单个表单。

你可以使用erl_scan:tokens来实现这个目标(这个代码很糟糕,但我不确定我是否以正确的方式使用该函数):

-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).

答案 1 :(得分:0)

罗伯特建议使用erl_scan:tokens/3的可重入特征。 关于这个函数的文档并不明确,我花了一些时间来理解初始字符串需要由eof关闭。 (如果不是令牌函数运行无限循环)。

以下是我最终提出的代码,希望能帮助他人。

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.