Erlang (programming language)/Tutorials/Yecc: Difference between revisions

From Citizendium
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 14: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.