Index: /trunk/PS-IPP-Metadata-Config/lib/PS/IPP/Metadata/Config.pm
===================================================================
--- /trunk/PS-IPP-Metadata-Config/lib/PS/IPP/Metadata/Config.pm	(revision 3394)
+++ /trunk/PS-IPP-Metadata-Config/lib/PS/IPP/Metadata/Config.pm	(revision 3395)
@@ -1,5 +1,5 @@
 # Copyright (c) 2005  Joshua Hoblitt
 #
-# $Id: Config.pm,v 1.2 2005-03-01 23:45:21 jhoblitt Exp $
+# $Id: Config.pm,v 1.3 2005-03-09 23:44:18 jhoblitt Exp $
 
 package PS::IPP::Metadata::Config;
@@ -18,4 +18,5 @@
 #$::RD_TRACE = 1;
 #$::RD_HINT = 1;
+#use Data::Dumper;
 
 my $grammar = do{ local $/; <DATA> };
@@ -40,4 +41,8 @@
     my $tree = $self->{_parser}->startrule( $metadata );
 
+    return undef unless defined $tree;
+
+    #print Dumper($tree);
+    
     # remove comment only lines
     $self->_strip_comments( $tree ) or return undef;
@@ -61,5 +66,13 @@
         my $elem = $tree->[$i];
 
-        if ( $elem->{class} eq "comment_line" ) {
+        # recurse through nested metadata
+        if ( $elem->{class} eq "metadata" ) {
+            $self->_strip_comments( $elem->{value} );
+        }
+
+        # stop if the prevous pass removed the last element and called redo
+        last unless defined $elem;
+
+        if ( $elem->{class} =~ /comment_line|blank_line/ ) {
             # delete element from array
             splice @$tree, $i, 1;
@@ -85,4 +98,12 @@
     for (my $i = 0; $i < @{$tree}; $i++) {
         my $elem = $tree->[$i];
+
+        # recurse through nested metadata
+        if ( $elem->{class} eq "metadata" ) {
+            $self->_merge_multi_symbols( $elem->{value} );
+        }
+
+        # stop if the prevous pass removed the last element and called redo
+        last unless defined $elem;
 
         if ( $elem->{class} eq "multi_symbol" ) {
@@ -141,4 +162,9 @@
         my $elem = $tree->[$i];
 
+        # recurse through nested metadata
+        if ( $elem->{class} eq "metadata" ) {
+            $self->_merge_duplicates( $elem->{value} );
+        }
+
         if ( exists $names{ $elem->{name} } ) {
             carp "duplicate element name, ", $elem->{name}, "\n";
@@ -164,6 +190,8 @@
 __DATA__
 
-startrule:
-    statement(s) /\z/
+startrule: grammar
+
+grammar:
+    statement(s)
         { $item[1 .. -1] }
 
@@ -173,18 +201,14 @@
     | multi_symbol
     | comment_line
-
-comment_line:
-    comment
-        {{
-            class   => 'comment_line',
-            comment => $item{comment}
-        }}
-
-comment:
-    '#' end_of_line
-        { $item{end_of_line} }
+    | metadata
+    | blank_line
+#    | {
+#        use Carp qw( croak );
+#        $text =~ /([^\n]*)/;
+#        croak "Invalid statement at line $thisline near \"$1\"";
+#    }
 
 scalar:
-    name type value comment
+    <skip:'[ \t\r]*'> name type value comment "\n"
         {{
             class   => 'scalar',
@@ -194,5 +218,5 @@
             comment => $item{comment}
          }}
-    | name type value 
+    | <skip:'[ \t\r]*'> name type value "\n"
         {{
             class   => 'scalar',
@@ -203,6 +227,7 @@
 
 vector:
-    vname vtype vvalue comment
-        {{
+     <skip:'[ \t\r]*'> vname vtype vvalue comment "\n"
+        {{
+
             class   => 'vector',
             name    => $item{vname},
@@ -211,5 +236,5 @@
             comment => $item{comment}
          }}
-    | vname vtype vvalue 
+    | <skip:'[ \t\r]*'> vname vtype vvalue "\n"
         {{
             class   => 'vector',
@@ -220,10 +245,43 @@
 
 multi_symbol:
-    name '*' end_of_line
+    <skip:'[ \t\r]*'> name '*' to_end_of_line "\n"
         {{
             class   => 'multi_symbol',
             name    => $item{name}, 
-            comment => $item{end_of_line},
+            comment => $item{to_end_of_line},
         }}
+
+comment_line:
+    <skip:'[ \t\r]*'> comment "\n" 
+        {{
+            class   => 'comment_line',
+            comment => $item{comment},
+        }}
+
+metadata:
+    metadata_name grammar metadata_end
+        {{
+            class   => 'metadata',
+            name    => $item{metadata_name},
+            value   => $item{grammar},
+         }} 
+
+blank_line:
+    <skip:'[ \t\r]*'> "\n"
+        {{
+            class   => 'blank_line',
+            comment => $item{comment},
+        }}
+
+metadata_name:
+    <skip:'[ \t\r]*'> name /METADATA/i "\n"
+        { $item{name} } 
+    
+metadata_end:
+     <skip:'[ \t\r]*'> /END/i "\n"
+
+comment:
+    '#' to_end_of_line
+        { $item{to_end_of_line} }
 
 name:
@@ -256,9 +314,9 @@
 
 vvalue:
-    vvalue_(s)
+    _vvalue(s)
         { [ map { @$_ } @{$item[1]} ] }
 
 # backtracking optimization
-vvalue_:
+_vvalue:
     primitive vector_sep(?)
         { [ $item[1] ] }
@@ -285,4 +343,4 @@
     /\S[^#\n]*/
 
-end_of_line:
+to_end_of_line:
     /[^\n]*/
