erl_parse:parse_form 我做错了什么?
What am I doing wrong with erl_parse:parse_form?
我写了一个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很酷。
函数 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).
Robert 建议使用 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.
我写了一个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很酷。
函数 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).
Robert 建议使用 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.