erlang - How do I pass a string to epp_dodger? -
i'm writing process erlang source code. pretty first line of program is:
{ok, forms} = epp_dodger:parse_file(filename)
however, want simple unit testing. so: how persuade epp_dodger
take input string instead of file?
alternatively, has epp_dodger:parse_form/2,3
, takes iodevice
, how provide iodevice
on string?
the code below (which admittedly bit hackish) starts gen_server
takes string argument, , fulfills erlang i/o protocol enough satisfy epp_dodger:parse/2
able read , parse string process.
here's example of using it:
1> {ok,p} = iostr:start("-module(x).\n-export([f/0]).\nf() -> ok.\n"). 2> epp_dodger:parse(p,1). {ok,[{tree,attribute, {attr,1,[],none}, {attribute, {tree,atom,{attr,1,[],none},module}, [{tree,atom,{attr,1,[],none},x}]}}, {tree,attribute, {attr,2,[],none}, {attribute, {tree,atom,{attr,2,[],none},export}, [{tree,list, {attr,2,[],none}, {list, [{tree,arity_qualifier, {attr,2,[],none}, {arity_qualifier, {tree,atom,{attr,...},f}, {tree,integer,{...},...}}}], none}}]}}, {tree,function, {attr,3,[],none}, {func, {tree,atom,{attr,3,[],none},f}, [{tree,clause, {attr,3,[],none}, {clause,[],none,[{atom,3,ok}]}}]}}]}
the process dies once string exhausted.
note code misses few things — handling unicode properly, example — should give idea of how make more robust i/o server purpose if needed.
-module(iostr). -behaviour(gen_server). -export([start_link/1, start/1, stop/1]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -record(state, { data, line = 1, lines }). start_link(data) -> gen_server:start_link(?module, [data], []). start(data) -> gen_server:start(?module, [data], []). stop(pid) -> gen_server:cast(pid, stop). init([data0]) -> data = [line++"\n" || line <- string:tokens(data0, "\n")], {ok, #state{data=data,lines=length(data)}}. handle_call(_request, _from, state) -> {reply, ok, state}. handle_cast(stop, state) -> {stop, normal, state}; handle_cast(_msg, state) -> {noreply, state}. handle_info({io_request,from,replyas,{get_until,_,_,_,_,_}}, #state{data=[],lines=l}=state) -> ! {io_reply, replyas, {eof,l}}, {stop, normal, state}; handle_info({io_request,from,replyas,{get_until,_,_,m,f,args}}, #state{data=data,line=l}=state) -> case handler(data,l,[],m,f,args) of eof -> lines = state#state.lines, ! {io_reply, replyas, {eof,lines}}, {stop, normal, state#state{data=[]}}; {ok,result,rest,ndata,nl} -> ! {io_reply, replyas, result}, case rest of [] -> {noreply, state#state{data=ndata,line=nl}}; _ -> {noreply, state#state{data=[rest|ndata],line=nl}} end end; handle_info(_info, state) -> {noreply, state}. terminate(_reason, _state) -> ok. code_change(_oldvsn, state, _extra) -> {ok, state}. handler([input|data],l,cont,m,f,extra) -> case catch apply(m,f,[cont,input|extra]) of {done,eof,_} -> eof; {done,result,rest} -> {ok,result,rest,data,l+1}; {more,ncont} -> case data of [] -> eof; _ -> handler(data,l+1,ncont,m,f,extra) end end.
Comments
Post a Comment