Index: trunk/lib/Text/FormBuilder.pm
===================================================================
--- trunk/lib/Text/FormBuilder.pm	(revision 75)
+++ trunk/lib/Text/FormBuilder.pm	(revision 77)
@@ -821,5 +821,5 @@
 your server, and you don't have to parse the form spec each time you want 
 to display your form. The generated module is a subclass of L<CGI::FormBuilder>,
-that will passa long any constructor arguments to FormBuilder, and set up
+that will pass along any constructor arguments to FormBuilder, and set up
 the fields for you.
 
@@ -983,5 +983,5 @@
 =item C<!field>
 
-B<DEPRACATED> Include a named instance of a group defined with C<!group>.
+B<DEPRECATED> Include a named instance of a group defined with C<!group>.
 
 =item C<!title>
@@ -1223,5 +1223,5 @@
 =head2 Language/Parser
 
-Deprecate the C<!field> directive
+Make sure that multiple runs of the parser don't share data.
 
 Allow renaming of the submit button; allow renaming and inclusion of a 
@@ -1239,4 +1239,7 @@
 =head2 Code generation/Templates
 
+Expose some of the currently private functions to be able to get the generated
+code text directly, without printing.
+
 Revise the generated form constructing code to use the C<fieldopts>
 option to C<< FB->new >>; will require FB 3.02 to run.
Index: trunk/lib/Text/FormBuilder/grammar
===================================================================
--- trunk/lib/Text/FormBuilder/grammar	(revision 75)
+++ trunk/lib/Text/FormBuilder/grammar	(revision 77)
@@ -1,13 +1,14 @@
+# line directives
+# block directives
+# field lines
+# comments
+
 {
     #$::RD_TRACE = 1;
     my (
-	$context,      # line or group
 	@sections,     # master data structure
 	$section_head,
 	$section_id,
 	@lines,        # lines in each section
-	$title,
-	$author,
-	$description,
 	%lists,
 	%patterns,
@@ -24,8 +25,18 @@
 	$cols,
     );
-    $context = 'line';
+    my $context = 'line';	# start in line context by default
+    my %formspec;
+    
+    # TODO: helper sub?
+    sub alert ($) {
+	warn '[' . (split(/::/, (caller(1))[3]))[-1] . '] ' . shift() . "\n";
+    }
 }
 
-form_spec: (list_def | description_def | validate_def | group_def | note | line)(s)
+form_spec:
+    { 
+	%formspec = ();  # clear the old formspec data
+    }
+    (list_def | description_def | group_def | note | line)(s)
     {
 	# grab the last section, if there is any
@@ -39,11 +50,8 @@
 	}
 	
-	$section_id = $item{identifier};
-	$section_head = $item[3];
-	@lines = ();
 	$return = {
-	    title    => $title,
-	    author   => $author,
-	    description => $description,
+	    title    => $formspec{title},
+	    author   => $formspec{author},
+	    description => $formspec{description},
 	    lists    => \%lists,
 	    patterns => \%patterns,
@@ -60,16 +68,11 @@
 
 dynamic_list: '&' <perl_codeblock>
-    {
-	warn "[Text::FormBuilder] Dynamic lists have been removed from the formspec grammar";
-    }
+    { warn "[Text::FormBuilder] Dynamic lists have been removed from the formspec grammar"; }
 
 description_def: '!description' block
     {
-	warn "[Text::FormBuilder] Description redefined at input text line $thisline\n" if defined $description;
-	$description = $item{block};
-    }
-
-validate_def: '!validate' var_name <perl_codeblock>
-    { $subs{$item{var_name}} = eval "sub $item[3]" }
+	warn "[Text::FormBuilder] Description redefined at input text line $thisline\n" if defined $formspec{description};
+	$formspec{description} = $item{block};
+    }
 
 group_def: '!group' { $context = 'group' } var_name '{' field_line(s) '}' { $context = 'line' }
@@ -82,6 +85,4 @@
 note: '!note' block  { push @lines, [ 'note', $item{block} ]; }
 
-
-#TODO: allow \ escape for [] {} in these blocks
 
 # curly-brace delimited block, that can contain properly
@@ -109,12 +110,12 @@
 title: '!title' /.*/
     {
-	warn "[Text::FormBuilder] Title redefined at input text line $thisline\n" if defined $title;
-	$title = $item[2];
+	warn "[Text::FormBuilder] Title redefined at input text line $thisline\n" if defined $formspec{title};
+	$formspec{title} = $item[2];
     }
 
 author: '!author' /.*/
     {
-	warn "[Text::FormBuilder] Author redefined at input text line $thisline\n" if defined $author;
-	$author = $item[2];
+	warn "[Text::FormBuilder] Author redefined at input text line $thisline\n" if defined $formspec{author};
+	$formspec{author} = $item[2];
     }
 
@@ -147,5 +148,5 @@
 group_field: '!field' group_name name label(?)
     {
-	warn "[Text::FormBuilder] The !field directive has been DEPRECATED (input file line $thisline). Please use the name:GROUP style";
+	warn "WARNING line $thisline: The '!field' directive has been DEPRECATED. Use the 'name:GROUP' style instead.\n";
 	push @lines, [ 'group', { name => $item{name}, label => $item{'label(?)'}[0], group => $item{group_name} } ];
     }
@@ -227,5 +228,5 @@
 limit: /\d+/
 
-label: '|' (simple_multiword | quoted_string) { $item[2] }
+label: '|' string { $item[2] }
 
 hint: bracket_block
@@ -237,5 +238,7 @@
 other: '+' 'other' { 1 }
 
-default: '=' (simple_multiword | quoted_string) { $item[2] }
+default: '=' string { $item[2] }
+
+string: simple_multiword | quoted_string
 
 # for simple multiword values not involving punctuation
@@ -249,9 +252,9 @@
 option_list: options | list_var
     
-options: '{' option(s /,/) '}'
+options: '{' option(s /\s*,\s*/) '}'
 
 list_var: /@[A-Z_]+/ { $list_var = $item[1] }
 
-option: (simple_multiword | quoted_string) display_text(?)
+option: string display_text(?)
     { push @options, { $item[1] => $item{'display_text(?)'}[0] } }
 
