<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>tests/controller_parser_test_data/collection_with_get.con</filename>
    </added>
    <added>
      <filename>tests/controller_parser_test_data/empty_collection_and_resource.con</filename>
    </added>
    <added>
      <filename>tests/controller_parser_test_data/empty_resource_and_collection.con</filename>
    </added>
    <added>
      <filename>tests/controller_parser_test_data/only_empty_collection.con</filename>
    </added>
    <added>
      <filename>tests/controller_parser_test_data/only_empty_resource.con</filename>
    </added>
    <added>
      <filename>tests/controller_parser_test_data/resource_with_get.con</filename>
    </added>
    <added>
      <filename>tests/ebin/.empty_file_for_git</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -5,14 +5,18 @@ all: subdirs
 	
 subdirs:
 	@for d in $(SUB_DIRECTORIES); do \
-	  	(cd $$d; $(MAKE)); \
+	  	($(MAKE) -C $$d ); \
 	done
 
 clean:
 	@for d in $(SUB_DIRECTORIES); do \
-	  	(cd $$d; $(MAKE) clean); \
+	  	($(MAKE) clean -C $$d); \
 	done
 
 test: all
-	cd tests &amp;&amp; $(MAKE) test
-	
+	$(MAKE) test -C tests
+
+retest: 
+	$(MAKE) clean -C src
+	$(MAKE) clean -C tests
+	$(MAKE) test</diff>
      <filename>Makefile</filename>
    </modified>
    <modified>
      <diff>@@ -4,10 +4,10 @@ all: subdirs
 	
 subdirs:
 	@for d in $(SUB_DIRECTORIES); do \
-	  	(cd $$d; $(MAKE)); \
+	  	($(MAKE) -C $$d); \
 	done
 
 clean:
 	@for d in $(SUB_DIRECTORIES); do \
-	  	(cd $$d; $(MAKE) clean); \
+	  	($(MAKE) clean -C $$d); \
 	done
\ No newline at end of file</diff>
      <filename>lib/Makefile</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,194 @@
 -module(controller_parser).
 -author('jeff@somethingsimilar.com').
--export([foobar/0]).
+-export([
+		parse_controller_file/1, collection/1, 
+		resource/1, resource_methods/1, collection_methods/1
+]).
 
-foobar() -&gt;
-	true.
\ No newline at end of file
+%% Matches a line ending in only whitespace or a new line (with whitespace 
+%% optionally before it) or the beginning of a comment (also with whitespace 
+%% optionally before it).
+
+-define(EndOfLineRegex, &quot;[\s\t]*(%|\n)?&quot;). 
+-define(CollectionRegex, &quot;^[\s\t]*collection[\s\t]*:?&quot; ++ ?EndOfLineRegex).
+-define(ResourceRegex, &quot;^[\s\t]*resource[\s\t]*:?&quot; ++ ?EndOfLineRegex).
+-define(MethodRegex, &quot;^[\s\t]*([a-z][a-zA-Z0-9])+:?&quot; ++ ?EndOfLineRegex).
+-define(EndRegex, &quot;^[\s\t]*:::&quot; ++ ?EndOfLineRegex).
+
+-import(regexp,[match/2]).
+-import(file, [open/2]).
+	
+parse_controller_file(ControllerFileName) -&gt;
+	{ok, File} = file:open(ControllerFileName, [read]),
+	start_top_level(File).
+	
+start_top_level(File) -&gt;
+	parse_top_level(File, []).
+	
+parse_top_level(File, ConHash) -&gt;
+	Line = io:get_line(File, ''),
+	
+	case match_top_level_line(Line) of
+		start_collection -&gt;
+			start_collection_group(File, ConHash);
+			
+		start_resource -&gt; 
+			start_resource_group(File, ConHash);
+		
+		end_found_outside_of_definition -&gt;
+			throw(end_found_outside_of_definition);
+		eof -&gt;
+			ConHash;
+		true -&gt; parse_top_level(File, ConHash)
+	end.
+
+match_top_level_line(eof) -&gt; eof;
+match_top_level_line(Line) -&gt;
+	CollStartLine = regexp:first_match(Line, ?CollectionRegex),
+	ResStartLine = regexp:first_match(Line, ?ResourceRegex),
+	EndLine = regexp:first_match(Line, ?EndRegex),
+	if
+		CollStartLine /= nomatch -&gt;
+			start_collection;
+		
+		ResStartLine /= nomatch -&gt;
+			start_resource;
+			
+		EndLine /= nomatch -&gt;
+			end_found_outside_of_definition;
+
+		true -&gt; true
+	end.
+	
+start_collection_group(File, ConHash) -&gt;
+	parse_collection_group(File, ConHash, []).
+	
+parse_collection_group(File, ConHash, Methods) -&gt;
+	Line = io:get_line(File, ''),
+
+	case match_line_in_collection_group(Line) of
+		end_found -&gt; finish_collection_group(File, ConHash, Methods);
+		
+		{method, MethodName} -&gt; 
+			start_method_group(File, ConHash, collection, Methods, MethodName);
+			
+		%% eof's shouldn't be seen if we haven't finished with the collection
+		eof -&gt; throw(unexpected_eof_in_collection);
+		
+		%% If it's not dangerous and hasn't been defined, just ignore it.
+	 	_ -&gt; parse_collection_group(File, ConHash, Methods)
+	end.
+
+match_line_in_collection_group(eof) -&gt; eof;
+match_line_in_collection_group(Line) -&gt;
+	MethodMatch = regexp:first_match(Line, ?MethodRegex),
+	
+	%% FIXME This line causes problems because we want to be greedy
+	EndLine = regexp:first_match(Line, ?EndRegex),
+
+	if
+		EndLine /= nomatch -&gt;
+			end_found;
+		
+		MethodMatch /= nomatch -&gt;
+			{match, Start, Len} = MethodMatch,
+			{method, lists:sublist(Line, Start+1, Len)};
+
+		true -&gt; true
+	end.
+
+finish_collection_group(File, ConHash, Methods) -&gt;
+	%% We're done with the collection, so we pop back out to the top level
+	parse_top_level(File, [{collection, [{methods, Methods}]}|ConHash]).
+	
+start_resource_group(File, ConHash) -&gt;
+	parse_resource_group(File, ConHash, []).
+	
+parse_resource_group(File, ConHash, Methods) -&gt;
+	Line = io:get_line(File, ''),
+	
+	case match_line_in_resource_group(Line) of
+		end_found -&gt; finish_resource_group(File, ConHash, Methods);
+		
+		{method, MethodName} -&gt; 
+			start_method_group(File, ConHash, resource, Methods, MethodName);
+		%% eof's shouldn't be seen if we haven't finished the resource
+		eof -&gt; throw(unexpected_eof_in_resource);
+		
+		%% If it's not dangerous and hasn't been defined, just ignore it.
+		_ -&gt; parse_resource_group(File, ConHash, Methods)
+	end.
+	
+	
+match_line_in_resource_group(eof) -&gt; eof;
+match_line_in_resource_group(Line) -&gt;
+	MethodMatch = regexp:first_match(Line, ?MethodRegex),
+	%% FIXME This line causes problems because we want to be greedy
+	EndMatch = regexp:first_match(Line, ?EndRegex),
+	
+	if
+		EndMatch /= nomatch -&gt;
+			end_found;
+			
+		MethodMatch /= nomatch -&gt;
+			{match, Start, Len} = MethodMatch,
+			{method, lists:sublist(Line, Start+1, Len)};
+
+		true -&gt; true
+	end.
+	
+finish_resource_group(File, ConHash, Methods) -&gt; 
+	%% TODO other nifty stuff
+	%% We're done with the resource, so we pop back out to the top level
+	parse_top_level(File, [{resource, [{methods, Methods}]}|ConHash]).
+	
+
+start_method_group(File, ConHash, GroupType, Methods, MethodName) -&gt;
+	parse_method_group(File, ConHash, GroupType, Methods, MethodName, []).
+	
+parse_method_group(File, ConHash, GroupType, Methods, MethodName, MethodBody) -&gt;
+	Line = io:get_line(File, ''),
+	
+	case match_line_in_method_group(Line) of
+		end_found -&gt; finish_method_group(File, ConHash, GroupType, Methods, MethodName, MethodBody);
+		eof -&gt; throw(unexpected_eof_in_method_body);
+		_ -&gt; parse_method_group(File, ConHash, GroupType, Methods, MethodName, [Line|MethodBody])
+	end.
+
+match_line_in_method_group(eof) -&gt; eof;
+match_line_in_method_group(Line) -&gt;
+	EndLine = regexp:first_match(Line, ?EndRegex),
+
+	if
+		EndLine /= nomatch -&gt;
+			end_found;
+		true -&gt; true
+	end.
+	
+finish_method_group(File, ConHash, GroupType, Methods, MethodName, MethodBody) -&gt;
+	Method = {MethodName, lists:concat(lists:reverse(MethodBody))},
+
+	case GroupType of
+		resource -&gt; parse_resource_group(File, ConHash, [Method|Methods]);
+		collection -&gt; parse_collection_group(File, ConHash, [Method|Methods]);
+		_ -&gt; throw(unsupported_group_type)
+	end.
+	
+collection(ConHash) -&gt;
+	{value, CollHash} = lists:keysearch(collection, 1, ConHash),
+	CollHash.
+	
+resource(ConHash) -&gt;
+	{value, ResHash} = lists:keysearch(resource, 1, ConHash),
+	ResHash.
+	
+collection_methods(ConHash) -&gt;
+	methods_from_group(collection(ConHash)).
+	
+resource_methods(ConHash) -&gt;
+	methods_from_group(resource(ConHash)).
+
+methods_from_group(ResOrCollHash) -&gt;
+	{_, AttrList} = ResOrCollHash,
+	{value, {methods, Methods}} = lists:keysearch(methods, 1, AttrList),
+	Methods.
\ No newline at end of file</diff>
      <filename>src/controller_parser.erl</filename>
    </modified>
    <modified>
      <diff>@@ -2,6 +2,7 @@ EMULATOR=beam
 EUNIT_EBIN=../lib/eunit/ebin
 EUNIT_INCLUDE=../lib/eunit/include
 EBIN=../ebin
+TEST_EBIN=ebin
 SRC=../src
 ERL_COMPILE_FLAGS += -I$(EUNIT_INCLUDE) +warn_unused_vars +nowarn_shadow_vars +warn_unused_import
 
@@ -9,15 +10,15 @@ SOURCES = \
 	test_runner.erl \
 	controller_parser_test.erl
 
-OBJECTS=$(SOURCES:%.erl=$(EBIN)/%.$(EMULATOR))
+OBJECTS=$(SOURCES:%.erl=$(TEST_EBIN)/%.$(EMULATOR))
 
 all: $(OBJECTS)
 	
-$(EBIN)/%.$(EMULATOR):%.erl
-	erlc -pa $(EUNIT_EBIN) -pa $(SRC) -W $(ERL_COMPILE_FLAGS) -o$(EBIN) $&lt;
+$(TEST_EBIN)/%.$(EMULATOR):%.erl
+	erlc -pa $(EUNIT_EBIN) -pa $(SRC) -pa $(EBIN)-W $(ERL_COMPILE_FLAGS) -o$(TEST_EBIN) $&lt;
 	
 clean:
 	rm -f $(OBJECTS)
 
 test: all
-	cd $(EBIN) &amp;&amp; erl -noshell -pa $(EUNIT_EBIN) -pa $(SRC) -s test_runner run_all
\ No newline at end of file
+	cd $(TEST_EBIN) &amp;&amp; erl -noshell -pa ../$(EUNIT_EBIN) -pa ../$(SRC) -pa ../$(EBIN) -s test_runner run_all
\ No newline at end of file</diff>
      <filename>tests/Makefile</filename>
    </modified>
    <modified>
      <diff>@@ -4,6 +4,50 @@
 %% installation directory.  The Makefile does this. 
 -include_lib(&quot;eunit/include/eunit.hrl&quot;).
 -import(eunit).
+-import(controller_parser).
+-import(filename, [join/1, dirname/1]).
 
-simple_test() -&gt;
-	?assert(1+1=2).
+controller_filename(ControllerName) -&gt;
+	ConFile = ControllerName ++ &quot;.con&quot;,
+	filename:join([filename:dirname(?FILE), &quot;..&quot;, &quot;controller_parser_test_data&quot;, ConFile]).
+	
+only_empty_collection_test() -&gt;
+	ConHash = controller_parser:parse_controller_file(controller_filename(&quot;only_empty_collection&quot;)),
+	?assertEqual(0, length(controller_parser:collection_methods(ConHash))),
+	?assertNot(lists:keysearch(resource, 1, ConHash)).
+
+only_empty_resource_test() -&gt;	
+	ConHash = controller_parser:parse_controller_file(controller_filename(&quot;only_empty_resource&quot;)),
+	?assertNot(lists:keysearch(collection, 1, ConHash)),
+	?assertEqual(0, length(controller_parser:resource_methods(ConHash))).
+	
+empty_resource_and_collection_test() -&gt;
+	ConHash = controller_parser:parse_controller_file(controller_filename(&quot;empty_resource_and_collection&quot;)),
+	?assertEqual(0, length(controller_parser:resource_methods(ConHash))),
+	?assertEqual(0, length(controller_parser:collection_methods(ConHash))).
+	
+empty_collection_and_resource_test() -&gt;
+	ConHash = controller_parser:parse_controller_file(controller_filename(&quot;empty_collection_and_resource&quot;)),
+	?assertEqual(length(controller_parser:resource_methods(ConHash)), 0),
+	?assertEqual(length(controller_parser:collection_methods(ConHash)), 0).
+	
+resource_with_one_method_test() -&gt;
+	ConHash = controller_parser:parse_controller_file(controller_filename(&quot;resource_with_get&quot;)),
+	Methods = controller_parser:resource_methods(ConHash),
+	[{MethodName, MethodBody}] = Methods,
+	
+	?assertEqual(1, length(Methods)),
+	?assertEqual(&quot;get&quot;, MethodName),
+	?assertEqual(&quot;\t\t1,\n\t\t2\n&quot;, MethodBody).
+	
+	
+collection_with_one_method_test() -&gt;
+	ConHash = controller_parser:parse_controller_file(controller_filename(&quot;collection_with_get&quot;)),
+	Methods = controller_parser:collection_methods(ConHash),
+	
+	[{MethodName, MethodBody}] = Methods,
+	?assertEqual(1, length(Methods)),
+	?assertEqual(&quot;get&quot;, MethodName),
+	?assertEqual(&quot;\t\t\&quot;Bar\&quot;\n\t\t\&quot;Baz\&quot;\n&quot;, MethodBody).
+	
+	
\ No newline at end of file</diff>
      <filename>tests/controller_parser_test.erl</filename>
    </modified>
    <modified>
      <diff>@@ -1,16 +1,21 @@
 -module(test_runner).
 -import(smerl).
--import(filename, [basename/2]).
+-import(filename, [basename/2, absname/1]).
 -import(filelib, [wildcard/1]).
-
+-import(io, [format/2]).
 -export([run_all/0]).
 
 run_all() -&gt;
-	Mods = gather_test_modules()
+	Mods = lists:map(fun modulize_beam_filename/1, filelib:wildcard(&quot;*_test.beam&quot;)),
+	lists:foreach(fun test_module/1, Mods),
 	shutdown_clean().
 	
-gather_test_modules() -&gt;
-	lists:map(fun(Fn) -&gt; filename:basename(Fn, &quot;.erl&quot;) end, filelib:wildcard(&quot;*_test.erl&quot;)).
+modulize_beam_filename(Fn) -&gt;
+	list_to_atom(filename:basename(Fn, &quot;.beam&quot;)).
+	
+test_module(Mod) -&gt;
+	io:format(&quot;Testing ~s. ~n&quot;, [Mod]),
+	Mod:test().
 	
 shutdown_clean() -&gt;
 	spawn(fun() -&gt; init:stop() end),</diff>
      <filename>tests/test_runner.erl</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>df784c02001a4ee4e3f75e0b44556d3e293b56c7</id>
    </parent>
  </parents>
  <author>
    <name>Jeff Hodges</name>
    <email>jeff@somethingsimilar.com</email>
  </author>
  <url>http://github.com/jmhodges/recess/commit/f9cac286eb388493616a88878d596a2d95f94cbf</url>
  <id>f9cac286eb388493616a88878d596a2d95f94cbf</id>
  <committed-date>2008-04-27T03:13:44-07:00</committed-date>
  <authored-date>2008-04-27T03:13:44-07:00</authored-date>
  <message>a basic controller parsing.  handles methods for the collection and the resource.  also, wrote the make retest call to make my life easier</message>
  <tree>b7e501c3c45ac4a8feb7f2a378d1b739156a2698</tree>
  <committer>
    <name>Jeff Hodges</name>
    <email>jeff@somethingsimilar.com</email>
  </committer>
</commit>
