Erlang (programming language)/Tutorials/Yecc: Difference between revisions
Jump to navigation
Jump to search
imported>Eric Evers No edit summary |
imported>Eric Evers mNo edit summary |
||
Line 38: | Line 38: | ||
% html_parser:parse(B). | % html_parser:parse(B). | ||
It can be a pain to build and run a parser each time we edit the source yrl file. To speed things up, we can use a build and run the parser for us. html_test.erl: | It can be a pain to build and run a parser each time we edit the source yrl file. To speed things up, we can use a program to | ||
build and run the parser for us. We call the build-runner program, | |||
html_test.erl: | |||
-module(html_test). | -module(html_test). | ||
-compile(export_all). | -compile(export_all). | ||
start() -> | start() -> | ||
yecc:yecc("html.yrl","html_parser.erl"), | yecc:yecc("html.yrl","html_parser.erl"), | ||
cover:compile(html_parser), | cover:compile(html_parser), | ||
{_,List_of_symbols,_}=erl_scan:string( | {_,List_of_symbols,_}=erl_scan:string( | ||
"<html><head><title>greating</title></head> | "<html><head><title>greating</title></head> | ||
<body> | <body> | ||
hello there world what is up | hello there world what is up | ||
</body> | </body> | ||
</html>"), | </html>"), | ||
{ok,L} = html_parser:parse(List_of_symbols), | {ok,L} = html_parser:parse(List_of_symbols), | ||
register(do_event, spawn(html_test,event_loop,[])), | register(do_event, spawn(html_test,event_loop,[])), | ||
Events = lists:flatten(L), | Events = lists:flatten(L), | ||
send_events(Events), | send_events(Events), | ||
Events. | Events. | ||
send_events([]) -> do_event ! {exit}; | send_events([]) -> do_event ! {exit}; | ||
send_events([H|T]) -> | send_events([H|T]) -> | ||
do_event ! H, | do_event ! H, | ||
%io:format(" ~w ~n",[H]), | %io:format(" ~w ~n",[H]), | ||
send_events(T). | send_events(T). | ||
event_loop() -> | event_loop() -> | ||
receive | receive | ||
{open,{atom,_Line_Number,html}} -> | {open,{atom,_Line_Number,html}} -> | ||
io:format("~n start scan ~n", []), | io:format("~n start scan ~n", []), | ||
event_loop(); | event_loop(); | ||
{contents,List} -> | {contents,List} -> | ||
Contents = get_contents(List,[]), | Contents = get_contents(List,[]), | ||
io:format("~n contents: ~w ~n", [Contents]); | io:format("~n contents: ~w ~n", [Contents]); | ||
{exit} -> exit(normal) | {exit} -> exit(normal) | ||
end, | end, | ||
event_loop(). | event_loop(). | ||
get_contents([],Items) -> Items; | get_contents([],Items) -> Items; | ||
get_contents([H|T],Items)-> | get_contents([H|T],Items)-> | ||
if | if | ||
length(T) > 0 -> | length(T) > 0 -> | ||
NT = hd(T); | NT = hd(T); | ||
true -> | true -> | ||
NT = T | NT = T | ||
end, | end, | ||
{atom,_N,Item} = H, | {atom,_N,Item} = H, | ||
NItems = Items++[Item], | NItems = Items++[Item], | ||
% io:format(" ~w ",[Item]), | % io:format(" ~w ",[Item]), | ||
get_contents(NT,NItems). | get_contents(NT,NItems). | ||
Line 135: | Line 94: | ||
% {ok,html_test} | % {ok,html_test} | ||
% 7> html_test:start(). | % 7> html_test:start(). | ||
% [greating] | |||
% [hello,there,world,what,is,up] | % [hello,there,world,what,is,up] | ||
% and events. | % and events. |
Revision as of 13:13, 1 May 2008
Making Parsers with yecc
Yecc is an erlang version of yacc.
We have a BNF grammar in a source file ending in .yrl yrl means yecc rule list. We can parse simple a simple xhtml file using yecc. (Of course a more powerful way to do xml in erlang is xmerl)
html.yrl source:
Nonterminals tag elements element start_tag end_tag . Terminals 'atom' '<' '>' '/'. Rootsymbol tag. tag -> start_tag tag end_tag : ['$1', '$2', '$3']. tag -> start_tag tag tag end_tag : ['$1', '$2', '$3', '$4']. tag -> start_tag elements end_tag : ['$1', {'contents','$2'}, '$3']. tag -> start_tag end_tag : ['$1','$2'].
start_tag -> '<' 'atom' '>' : {'open','$2'}. end_tag -> '<' '/' 'atom' '>' : {'close','$3'}. elements -> element : ['$1']. elements -> element elements : ['$1', '$2']. element -> atom : '$1'.
% yecc:yecc("html.yrl","html_parser.erl"). % c(html_parser). % f(B), {_,B,_} = % erl_scan:string( % "<html><head></head><body>hello_world</body></html>"). % html_parser:parse(B).
It can be a pain to build and run a parser each time we edit the source yrl file. To speed things up, we can use a program to build and run the parser for us. We call the build-runner program, html_test.erl:
-module(html_test). -compile(export_all).
start() -> yecc:yecc("html.yrl","html_parser.erl"), cover:compile(html_parser), {_,List_of_symbols,_}=erl_scan:string( "<html><head><title>greating</title></head> <body> hello there world what is up </body> </html>"), {ok,L} = html_parser:parse(List_of_symbols), register(do_event, spawn(html_test,event_loop,[])), Events = lists:flatten(L), send_events(Events), Events.
send_events([]) -> do_event ! {exit}; send_events([H|T]) -> do_event ! H, %io:format(" ~w ~n",[H]), send_events(T). event_loop() -> receive {open,{atom,_Line_Number,html}} -> io:format("~n start scan ~n", []), event_loop(); {contents,List} -> Contents = get_contents(List,[]), io:format("~n contents: ~w ~n", [Contents]); {exit} -> exit(normal) end, event_loop(). get_contents([],Items) -> Items; get_contents([H|T],Items)-> if length(T) > 0 -> NT = hd(T); true -> NT = T end, {atom,_N,Item} = H, NItems = Items++[Item], % io:format(" ~w ",[Item]), get_contents(NT,NItems). % 6> c(html_test). % {ok,html_test} % 7> html_test:start(). % [greating] % [hello,there,world,what,is,up] % and events.