/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 693 - (hide annotations)
Sun Sep 24 21:13:45 2006 UTC (17 years, 7 months ago) by dpavlin
File size: 6855 byte(s)
 r979@llin:  dpavlin | 2006-09-24 23:11:30 +0200
 nit-picking

1 dpavlin 686 package WebPAC::Parser;
2    
3     use warnings;
4     use strict;
5    
6    
7     use PPI;
8     use PPI::Dumper;
9     use Data::Dump qw/dump/;
10     use File::Slurp;
11    
12 dpavlin 691 use base qw/WebPAC::Common WebPAC::Normalize/;
13 dpavlin 686
14     =head1 NAME
15    
16     WebPAC::Parser - parse perl normalization configuration files and mungle it
17    
18     =head1 VERSION
19    
20 dpavlin 691 Version 0.03
21 dpavlin 686
22     =cut
23    
24 dpavlin 691 our $VERSION = '0.03';
25 dpavlin 686
26     =head1 SYNOPSIS
27    
28     FIXME
29    
30     =head1 FUNCTIONS
31    
32     =head2 new
33    
34     Create new parser object.
35    
36     my $parser = new WebPAC::Parser(
37     config => new WebPAC::Config(),
38     base_path => '/optional/path/to/conf',
39     );
40    
41     =cut
42    
43     sub new {
44     my $class = shift;
45     my $self = {@_};
46     bless($self, $class);
47    
48     my $log = $self->_get_logger();
49    
50     $log->logdie("config isn't WebPAC::Config") unless ($self->{config} && $self->{config}->isa('WebPAC::Config'));
51    
52     $log->logdie("can't iterate_inputs over this config object") unless ($self->{config}->can('iterate_inputs'));
53    
54 dpavlin 691 $self->read_sources;
55 dpavlin 686
56     $self->{config}->iterate_inputs( sub {
57 dpavlin 689 my ($input, $database) = @_;
58 dpavlin 691 return unless $self->valid_database_input($database, $input->{name});
59     $self->parse_lookups($database,$input->{name});
60     } );
61    
62     $self ? return $self : return undef;
63     }
64    
65     =head2 read_sources
66    
67     my $source_files = $parser->read_sources;
68    
69     Called by L</new>.
70    
71     =cut
72    
73     sub read_sources {
74     my $self = shift;
75    
76     my $log = $self->_get_logger();
77    
78     my $nr = 0;
79    
80     $self->{config}->iterate_inputs( sub {
81     my ($input, $database) = @_;
82    
83 dpavlin 686 my $path = $input->{normalize}->{path} || return;
84     my $full = $self->{base_path} ? $self->{base_path} . '/' . $path : $path;
85 dpavlin 691
86 dpavlin 686 $log->logdie("normalization input $full doesn't exist") unless (-e $full);
87 dpavlin 691
88 dpavlin 686 my $s = read_file( $full ) || $log->logdie("can't read $full: $!");
89 dpavlin 691
90 dpavlin 689 my $input_name = $input->{name} || $log->logdie("can't deduce name of input: ", dump( $input ));
91 dpavlin 691
92     $log->debug("$database/$input_name: adding $path");
93    
94     $self->{valid_inputs}->{$database}->{$input_name} = {
95     source => $s,
96     path => $full,
97     usage => 0,
98     } unless defined($self->{valid_inputs}->{$database}->{$input_name});
99    
100     $self->{valid_inputs}->{$database}->{$input_name}->{usage}++;
101    
102     $nr++;
103 dpavlin 686 } );
104    
105 dpavlin 691 $log->debug("found $nr source files");
106 dpavlin 686
107 dpavlin 691 return $nr;
108 dpavlin 686 }
109    
110 dpavlin 692 =head2 parse_lookups
111 dpavlin 686
112 dpavlin 691 $parser->parse_lookups($database,$input);
113    
114 dpavlin 686 =cut
115    
116 dpavlin 691 sub parse_lookups {
117 dpavlin 686 my $self = shift;
118 dpavlin 691 my ($database, $input) = @_;
119 dpavlin 686
120     my $log = $self->_get_logger();
121    
122 dpavlin 691 $log->logdie("invalid database $database" ) unless $self->valid_database( $database );
123     $log->logdie("invalid input $input of database $database", ) unless $self->valid_database_input( $database, $input );
124 dpavlin 686
125 dpavlin 691 my $source = $self->{valid_inputs}->{$database}->{$input}->{source};
126     my $path = $self->{valid_inputs}->{$database}->{$input}->{path};
127 dpavlin 689
128 dpavlin 691 $log->logdie("no source found for database $database input $input path $path") unless ($source);
129 dpavlin 686
130 dpavlin 692 $log->info("parsing lookups for $database/$input from $path");
131 dpavlin 691
132     my $Document = PPI::Document->new( \$source ) || $log->logdie("can't parse source:\n", $self->{source});
133    
134 dpavlin 686 $Document->prune('PPI::Token::Whitespace');
135     #$Document->prune('PPI::Token::Operator');
136    
137     # Find all the named subroutines
138    
139 dpavlin 691 $self->{_lookup_errors} = ();
140 dpavlin 686
141 dpavlin 691 sub _lookup_error {
142     my $self = shift;
143     my $msg = shift;
144     $self->_get_logger->logconfess("error without message?") unless ($msg);
145     push @{ $self->{_lookup_errors} }, $msg;
146 dpavlin 690 return '';
147     }
148    
149 dpavlin 686 $Document->find( sub {
150     my ($Document,$Element) = @_;
151    
152     $Element->isa('PPI::Token::Word') or return '';
153     $Element->content eq 'lookup' or return '';
154    
155 dpavlin 687 $log->debug("expansion: ", $Element->snext_sibling);
156 dpavlin 686
157     my $args = $Element->snext_sibling;
158    
159     my @e = $args->child(0)->elements;
160 dpavlin 687 $log->logdie("hum, expect at least 8 elements, got ", scalar @e, " in $args") if ($#e < 8);
161 dpavlin 686
162 dpavlin 687 if ($log->is_debug) {
163     my $report = "found " . scalar @e . " elements:\n";
164 dpavlin 686
165 dpavlin 687 foreach my $i ( 0 .. $#e ) {
166     $report .= sprintf("# %-2d: %-30s %s\n", $i, ( $e[$i] || 'undef' ), $e[$i]->class );
167     }
168    
169     $log->debug($report);
170 dpavlin 686 }
171    
172     my $key_element = $e[8]->clone;
173    
174 dpavlin 687 $log->logdie("key element must be PPI::Structure::Block") unless $key_element->isa('PPI::Structure::Block');
175 dpavlin 686
176 dpavlin 687 $log->debug("key part: ", $key_element);
177 dpavlin 686
178     my @key;
179    
180     $key_element->find( sub {
181     my $e = $_[1] || die "no element?";
182     $e->isa('PPI::Token::Word') or return '';
183     $e->content eq 'rec' or return '';
184    
185     my $kf = $e->snext_sibling;
186    
187 dpavlin 687 $log->debug("key fragment = $kf");
188 dpavlin 686
189     push @key, eval $kf;
190 dpavlin 687 $log->logdie("can't eval { $kf }: $@") if ($@);
191 dpavlin 686
192     return 1;
193     });
194    
195 dpavlin 687 my $key = join('-', @key ) || $log->logdie("no key found!");
196 dpavlin 686
197 dpavlin 687 $log->debug("key = $key");
198 dpavlin 686
199     my $create = '
200     $coderef = ' . $e[7] . $e[8] . ';
201     foreach my $v ($coderef->()) {
202     next unless (defined($v) && $v ne \'\');
203     push @{ $lookup->{\'' . $key . '\'}->{$v} }, $mfn;
204     }
205     ';
206    
207 dpavlin 687 $log->debug("create: $create");
208 dpavlin 686
209 dpavlin 691 return $self->_lookup_error("invalid database $e[3] in $path" ) unless $self->valid_database( $e[3] );
210     return $self->_lookup_error("invalid input $e[5] of database $e[3] in $path", ) unless $self->valid_database_input( $e[3], $e[5] );
211 dpavlin 689
212 dpavlin 692 $self->add_lookup_create( $e[3], $e[5], $create );
213 dpavlin 686
214     if ($#e < 10) {
215     $e[8]->insert_after( $e[8]->clone );
216     $e[8]->insert_after( $e[7]->clone );
217     $e[8]->insert_after( $e[6]->clone );
218     }
219    
220     $e[7]->remove;
221     $e[8]->insert_before( new PPI::Token::Quote::Single( "'$key'" ) );
222     $e[8]->remove;
223    
224    
225 dpavlin 687 $log->debug(">>> ", $Element->snext_sibling);
226 dpavlin 686 });
227    
228 dpavlin 693 my $normalize_source = $Document->serialize;
229 dpavlin 692 $log->debug("create: ", dump($self->{_lookup_create}) );
230 dpavlin 693 $log->debug("normalize: $normalize_source");
231 dpavlin 686
232 dpavlin 693 $self->{_normalize_source}->{$database}->{$input} = $normalize_source;
233 dpavlin 692
234 dpavlin 687 if ($self->{debug}) {
235     my $Dumper = PPI::Dumper->new( $Document );
236     $Dumper->print;
237     }
238 dpavlin 686
239 dpavlin 692 $log->error("Parser errors:\n", join("\n",@{ $self->{_lookup_errors} }) ) if ($self->{_lookup_errors});
240 dpavlin 690
241 dpavlin 687 return 1;
242 dpavlin 686 }
243    
244 dpavlin 692 =head2 add_lookup_create
245    
246     $parse->add_lookup_create($database,$input,$source);
247    
248     =cut
249    
250     sub add_lookup_create {
251     my $self = shift;
252     my ($database,$input,$source) = @_;
253     $self->{_lookup_create}->{$database}->{$input} .= $source;
254     }
255    
256    
257 dpavlin 689 =head2 valid_database
258    
259     my $ok = $parse->valid_database('key');
260    
261     =cut
262    
263     sub valid_database {
264     my $self = shift;
265    
266     my $database = shift || return;
267     $database =~ s/['"]//g;
268    
269     return defined($self->{valid_inputs}->{$database});
270     }
271    
272     =head2 valid_database_input
273    
274     my $ok = $parse->valid_database('database_key','input_name');
275    
276     =cut
277    
278     sub valid_database_input {
279     my $self = shift;
280    
281     my ($database,$input) = @_;
282     $database =~ s/['"]//g;
283     $input =~ s/['"]//g;
284    
285     return defined($self->{valid_inputs}->{$database}->{$input});
286     }
287    
288 dpavlin 686 =head1 AUTHOR
289    
290     Dobrica Pavlinusic, C<< <dpavlin@rot13.org> >>
291    
292     =head1 COPYRIGHT & LICENSE
293    
294     Copyright 2006 Dobrica Pavlinusic, All Rights Reserved.
295    
296     This program is free software; you can redistribute it and/or modify it
297     under the same terms as Perl itself.
298    
299     =cut
300    
301     1; # End of WebPAC::Parser

  ViewVC Help
Powered by ViewVC 1.1.26