/[webpac2]/trunk/lib/WebPAC/Parser.pm
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/lib/WebPAC/Parser.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 698 by dpavlin, Mon Sep 25 11:14:53 2006 UTC revision 755 by dpavlin, Sun Oct 8 20:28:17 2006 UTC
# Line 9  use PPI::Dumper; Line 9  use PPI::Dumper;
9  use Data::Dump qw/dump/;  use Data::Dump qw/dump/;
10  use File::Slurp;  use File::Slurp;
11    
12  use base qw/WebPAC::Common WebPAC::Normalize/;  use base qw/WebPAC::Common/;
13    
14  =head1 NAME  =head1 NAME
15    
16  WebPAC::Parser - parse perl normalization configuration files and mungle it  WebPAC::Parser - parse perl normalization configuration files (rules) and mungle it
17    
18  =head1 VERSION  =head1 VERSION
19    
20  Version 0.04  Version 0.08
21    
22  =cut  =cut
23    
24  our $VERSION = '0.04';  our $VERSION = '0.08';
25    
26  =head1 SYNOPSIS  =head1 SYNOPSIS
27    
28  This module will parse L<WebPAC::Normalize/lookup> directives and generate source  This module will parse L<WebPAC::Normalize/lookup> directives and generate source
29  to produce lookups and normalization.  to produce lookups and normalization. It will also parse other parts of
30    source to produce some of DWIM (I<Do What I Mean>) magic
31    (like producing MARC oputput using L<WebPAC::Output::MARC> if there are C<marc_*>
32    rules in normalisation).
33    
34  It's written using L<PPI>, pure-perl parser for perl and heavily influenced by  It's written using L<PPI>, pure-perl parser for perl and heavily influenced by
35  reading about LISP. It might be a bit over-the board, but at least it removed  reading about LISP. It might be a bit over-the board, but at least it removed
# Line 61  sub new { Line 64  sub new {
64    
65          $log->logdie("can't iterate_inputs over this config object") unless ($self->{config}->can('iterate_inputs'));          $log->logdie("can't iterate_inputs over this config object") unless ($self->{config}->can('iterate_inputs'));
66    
67          $self->read_sources;          $self->_read_sources;
   
         $self->{config}->iterate_inputs( sub {  
                 my ($input, $database) = @_;  
                 return unless $self->valid_database_input($database, _input_name($input));  
                 $self->parse_lookups($database, _input_name($input));  
         } );  
68    
69          $self ? return $self : return undef;          $self ? return $self : return undef;
70  }  }
71    
72  =head2 read_sources  =head2 valid_database
73    
74      my $ok = $parse->valid_database('key');
75    
76    my $source_files = $parser->read_sources;  =cut
77    
78  Called by L</new>.  sub valid_database {
79            my $self = shift;
80    
81            my $database = shift || return;
82    
83            return defined($self->{valid_inputs}->{ _q($database) });
84    }
85    
86    =head2 valid_database_input
87    
88      my $ok = $parse->valid_database('database_key','input_name');
89    
90    =cut
91    
92    sub valid_database_input {
93            my $self = shift;
94            my ($database,$input) = @_;
95            $input = _input_name($input);
96            return defined($self->{valid_inputs}->{ _q($database) }->{ _q($input) });
97    }
98    
99    =head2 depends
100    
101    Return all databases and inputs on which specified one depends
102    
103      $depends_on = $parser->depends('database','input');
104    
105    =cut
106    
107    sub depends {
108            my $self = shift;
109            my ($database,$input) = @_;
110            $input = _input_name($input);
111            $self->_get_logger->debug("depends($database,$input)");
112            return unless (
113                    defined( $self->{depends}->{ _q($database) } ) &&
114                    defined( $self->{depends}->{ _q($database) }->{ _q($input) } )
115            );
116            return $self->{depends}->{ _q($database) }->{ _q($input) };
117    }
118    
119    =head2 have_lookup_create
120    
121      my @keys = $parser->have_lookup_create($database, $input);
122    
123    =cut
124    
125    sub have_lookup_create {
126            my $self = shift;
127            my ($database,$input) = @_;
128            $input = _input_name($input);
129            return unless (
130                    defined( $self->{_lookup_create_key}->{ _q($database) } ) &&
131                    defined( $self->{_lookup_create_key}->{ _q($database) }->{ _q($input) } )
132            );
133            return keys %{ $self->{_lookup_create_key}->{ _q($database) }->{ _q($input) } };
134    }
135    
136    
137    =head2 lookup_create_rules
138    
139      my $source = $parser->lookup_create_rules($database, $input);
140    
141    =cut
142    
143    sub lookup_create_rules {
144            my $self = shift;
145            my ($database,$input) = @_;
146            $input = _input_name($input);
147            return unless (
148                    defined( $self->{_lookup_create}->{ _q($database) } ) &&
149                    defined( $self->{_lookup_create}->{ _q($database) }->{ _q($input) } )
150            );
151            return $self->{_lookup_create}->{ _q($database) }->{ _q($input) };
152    }
153    
154    =head2 normalize_rules
155    
156      my $source = $parser->normalize_rules($database, $input);
157    
158  =cut  =cut
159    
160  sub _input_name($);  sub normalize_rules {
161            my $self = shift;
162            my ($database,$input) = @_;
163            $input = _input_name($input);
164            return unless (
165                    defined( $self->{_normalize_source}->{ _q($database) } ) &&
166                    defined( $self->{_normalize_source}->{ _q($database) }->{ _q($input) } )
167            );
168            return $self->{_normalize_source}->{ _q($database) }->{ _q($input) };
169    }
170    
171    
172  sub read_sources {  =head2 have_rules
173    
174      my $do_marc = $parser->have_rules('marc', $database, $input);
175      my $do_index = $parser->have_rules('search', $database);
176    
177    This function will return hash containing count of all found C<marc_*> or
178    C<search> directives. Input name is optional.
179    
180    =cut
181    
182    sub have_rules {
183            my $self = shift;
184    
185            my $log = $self->_get_logger();
186            my $type = shift @_ || $log->logconfess("need at least type");
187            my $database = shift @_ || $log->logconfess("database is required");
188            my $input = shift @_;
189    
190            $input = _input_name($input);
191    
192    
193            return unless defined( $self->{_have_rules}->{ _q($database) } );
194    
195            my $database_rules = $self->{_have_rules}->{ _q($database ) };
196    
197            if (defined($input)) {
198    
199                    return unless (
200                            defined( $database_rules->{ _q($input) } ) &&
201                            defined( $database_rules->{ _q($input) }->{ $type } )
202                    );
203    
204                    return $database_rules->{ _q($input) }->{ $type };
205            }
206    
207            my $usage;
208    
209            foreach my $i (keys %{ $database_rules }) {
210                    next unless defined( $database_rules->{$i}->{$type} );
211    
212                    foreach my $t (keys %{ $database_rules->{ $i }->{$type} }) {
213                            $usage->{ $t } += $database_rules->{ $i }->{ $t };
214                    }
215            }
216    
217            return $usage;
218    
219    }
220    
221    
222    =head1 PRIVATE
223    
224    =head2 _read_sources
225    
226      my $source_files = $parser->_read_sources;
227    
228    Called by L</new>.
229    
230    =cut
231    
232    sub _read_sources {
233          my $self = shift;          my $self = shift;
234    
235          my $log = $self->_get_logger();          my $log = $self->_get_logger();
236    
237          my $nr = 0;          my $nr = 0;
238    
239            my @sources;
240    
241          $self->{config}->iterate_inputs( sub {          $self->{config}->iterate_inputs( sub {
242                  my ($input, $database) = @_;                  my ($input, $database) = @_;
243    
244                  my @normalize;                  $log->debug("database: $database input = ", dump($input));
   
                 if (ref($input->{normalize}) eq 'ARRAY') {  
                         @normalize = @{ $input->{normalize} };  
                 } else {  
                         @normalize = ( $input->{normalize} );  
                 }  
245    
246                  foreach my $normalize (@normalize) {                  foreach my $normalize (@{ $input->{normalize} }) {
247    
248                          my $path = $normalize->{path};                          my $path = $normalize->{path};
249                          return unless($path);                          return unless($path);
# Line 114  sub read_sources { Line 257  sub read_sources {
257    
258                          $log->debug("$database/$input_name: adding $path");                          $log->debug("$database/$input_name: adding $path");
259    
260                          $self->{valid_inputs}->{$database}->{$input_name} = {                          $self->{valid_inputs}->{$database}->{$input_name}++;
                                 source => $s,  
                                 path => $full,  
                                 usage => 0,  
                         } unless defined($self->{valid_inputs}->{$database}->{$input_name});  
261    
262                          $self->{valid_inputs}->{$database}->{$input_name}->{usage}++;                          push @sources, sub {
263                                    $self->_parse_source( $database, $input_name, $full, $s );
264                            };
265    
266                          $nr++;                          $nr++;
267                  }                  }
# Line 128  sub read_sources { Line 269  sub read_sources {
269    
270          $log->debug("found $nr source files");          $log->debug("found $nr source files");
271    
272            # parse all sources
273            $_->() foreach (@sources);
274    
275          return $nr;          return $nr;
276  }  }
277    
278  =head2 parse_lookups  =head2 _parse_source
279    
280    $parser->parse_lookups($database,$input);    $parser->_parse_source($database,$input,$path,$source);
281    
282  Called for each input by L</new>  Called for each normalize source (rules) in each input by L</_read_sources>
283    
284  It will report invalid databases and inputs in error log after parsing.  It will report invalid databases and inputs in error log after parsing.
285    
286  =cut  =cut
287    
288  sub parse_lookups {  sub _parse_source {
289          my $self = shift;          my $self = shift;
290          my ($database, $input) = @_;          my ($database, $input, $path, $source) = @_;
291    
292          $input = _input_name($input);          $input = _input_name($input);
293    
# Line 152  sub parse_lookups { Line 296  sub parse_lookups {
296          $log->logdie("invalid database $database" ) unless $self->valid_database( $database );          $log->logdie("invalid database $database" ) unless $self->valid_database( $database );
297          $log->logdie("invalid input $input of database $database", ) unless $self->valid_database_input( $database, $input );          $log->logdie("invalid input $input of database $database", ) unless $self->valid_database_input( $database, $input );
298    
         my $source = $self->{valid_inputs}->{$database}->{$input}->{source};  
         my $path = $self->{valid_inputs}->{$database}->{$input}->{path};  
   
299          $log->logdie("no source found for database $database input $input path $path") unless ($source);          $log->logdie("no source found for database $database input $input path $path") unless ($source);
300    
301          $log->info("parsing lookups for $database/$input from $path");          $log->info("parsing lookups for $database/$input from $path (",length($source)," bytes)");
302    
303          my $Document = PPI::Document->new( \$source ) || $log->logdie("can't parse source:\n", $self->{source});          my $Document = PPI::Document->new( \$source ) || $log->logdie("can't parse source:\n", $self->{source});
304    
305          $Document->prune('PPI::Token::Whitespace');          $Document->prune('PPI::Token::Whitespace');
306            $Document->prune('PPI::Token::Comment');
307          #$Document->prune('PPI::Token::Operator');          #$Document->prune('PPI::Token::Operator');
308    
309          # Find all the named subroutines          # Find all the named subroutines
# Line 226  sub parse_lookups { Line 368  sub parse_lookups {
368    
369                          $log->debug("key = $key");                          $log->debug("key = $key");
370    
                         my $create = '  
                                 $coderef = ' . $e[7] . $e[8] . ';  
                                 foreach my $v ($coderef->()) {  
                                         next unless (defined($v) && $v ne \'\');  
                                         push @{ $lookup->{\'' . $key . '\'}->{$v} }, $mfn;  
                                 }  
                         ';  
   
                         $log->debug("create: $create");  
   
371                          return $self->_lookup_error("invalid database $e[3] in $path" ) unless $self->valid_database( $e[3] );                          return $self->_lookup_error("invalid database $e[3] in $path" ) unless $self->valid_database( $e[3] );
372                          return $self->_lookup_error("invalid input $e[5] of database $e[3] in $path", ) unless $self->valid_database_input( $e[3], $e[5] );                          return $self->_lookup_error("invalid input $e[5] of database $e[3] in $path", ) unless $self->valid_database_input( $e[3], $e[5] );
373    
374                            my $create = qq{
375                                    save_into_lookup($e[3],$e[5],'$key', $e[7] $e[8] );
376                            };
377    
378                            $log->debug("create: $create");
379    
380                          # save code to create this lookup                          # save code to create this lookup
381                          $self->{_lookup_create}->{ _q($e[3]) }->{ _q($e[5]) }->{ _q($key) } .= $create;                          $self->{_lookup_create}->{ _q($e[3]) }->{ _q($e[5]) } .= $create;
382                            $self->{_lookup_create_key}->{ _q($e[3]) }->{ _q($e[5]) }->{ _q($key) }++;
383    
384    
385                          if (defined( $self->{depends}->{ $database }->{ $input }->{ _q($e[3]) }->{ _q($e[5]) } )) {                          if (defined( $self->{depends}->{ $database }->{ $input }->{ _q($e[3]) }->{ _q($e[5]) }->{ $key } )) {
386                                  my $dep_key = $self->{depends}->{ $database }->{ $input }->{ _q($e[3]) }->{ _q($e[5]) };                                  $log->warn("dependency of $database/$input on $e[3]/$e[5] with $key allready recorded");
                                 $log->warn("dependency of $database/$input on $e[3]/$e[5] allready recorded as $dep_key, now changed to $key") if ($dep_key ne $key);  
387                          }                          }
388    
389                          # save this dependency                          # save this dependency
390                          $self->{depends}->{ $database }->{ $input }->{ _q($e[3]) }->{ _q($e[5]) } .= $key;                          $self->{depends}->{ $database }->{ $input }->{ _q($e[3]) }->{ _q($e[5]) }->{$key}++;
391    
392                          if ($#e < 10) {                          if ($#e < 10) {
393                                  $e[8]->insert_after( $e[8]->clone );                                  $e[8]->insert_after( $e[8]->clone );
# Line 269  sub parse_lookups { Line 407  sub parse_lookups {
407          $log->debug("create: ", dump($self->{_lookup_create}) );          $log->debug("create: ", dump($self->{_lookup_create}) );
408          $log->debug("normalize: $normalize_source");          $log->debug("normalize: $normalize_source");
409    
410          $self->{_normalize_source}->{$database}->{$input} = $normalize_source;          $self->{_normalize_source}->{$database}->{$input} .= $normalize_source;
411    
412          if ($self->{debug}) {          if ($self->{debug}) {
413                  my $Dumper = PPI::Dumper->new( $Document );                  my $Dumper = PPI::Dumper->new( $Document );
# Line 278  sub parse_lookups { Line 416  sub parse_lookups {
416    
417          $log->error("Parser errors:\n", join("\n",@{ $self->{_lookup_errors} }) ) if ($self->{_lookup_errors});          $log->error("Parser errors:\n", join("\n",@{ $self->{_lookup_errors} }) ) if ($self->{_lookup_errors});
418    
419          return 1;          $Document->find( sub {
420  }                          my ($Document,$Element) = @_;
   
   
 =head2 lookup_create_rules  
   
   my $source = $parser->lookup_create_rules($database, $input);  
   
 =cut  
   
 sub lookup_create_rules {  
         my $self = shift;  
         my ($database,$input) = @_;  
         return $self->{_lookup_create}->{ _q($database) }->{ _q($input) };  
 }  
   
 =head2 valid_database  
   
   my $ok = $parse->valid_database('key');  
   
 =cut  
   
 sub valid_database {  
         my $self = shift;  
   
         my $database = shift || return;  
   
         return defined($self->{valid_inputs}->{ _q($database) });  
 }  
   
 =head2 valid_database_input  
   
   my $ok = $parse->valid_database('database_key','input_name');  
   
 =cut  
   
 sub valid_database_input {  
         my $self = shift;  
   
         my ($database,$input) = @_;  
         return defined($self->{valid_inputs}->{ _q($database) }->{ _q($input) });  
 }  
   
 =head2 depends  
   
 Return all databases and inputs on which specified one depends  
   
   $depends_on = $parser->depends('database','input');  
421    
422  =cut                          $Element->isa('PPI::Token::Word') or return '';
423                            if ($Element->content =~ m/^(marc|search)/) {
424                                    my $what = $1;
425                                    $log->debug("found $what rules in $database/$input");
426                                    $self->{_have_rules}->{ $database }->{ $input }->{ $what }->{ $Element->content }++;
427                            } else {
428                                    return '';
429                            }
430            });
431    
432  sub depends {          return 1;
         my $self = shift;  
         my ($database,$input) = @_;  
         $self->_get_logger->debug("depends($database,$input)");  
         return unless defined( $self->{depends}->{ _q($database) }->{ _q($input) } );  
         return $self->{depends}->{ _q($database) }->{ _q($input) };  
433  }  }
434    
 =head1 PRIVATE  
435    
436  =head2 _q  =head2 _q
437    

Legend:
Removed from v.698  
changed lines
  Added in v.755

  ViewVC Help
Powered by ViewVC 1.1.26