r966@llin: dpavlin | 2006-09-24 19:22:45 +0200
[webpac2] / lib / WebPAC / Parser.pm
1 package WebPAC::Parser;
2
3 use warnings;
4 use strict;
5
6 use base qw/WebPAC::Common WebPAC::Normalize/;
7
8 use PPI;
9 use PPI::Dumper;
10 use Data::Dump qw/dump/;
11 use File::Slurp;
12
13
14 =head1 NAME
15
16 WebPAC::Parser - parse perl normalization configuration files and mungle it
17
18 =head1 VERSION
19
20 Version 0.01
21
22 =cut
23
24 our $VERSION = '0.01';
25
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         my $source;
55
56         $self->{config}->iterate_inputs( sub {
57                 my $input = shift;
58                 my $path = $input->{normalize}->{path} || return;
59                 my $full = $self->{base_path} ? $self->{base_path} . '/' . $path : $path;
60                 $log->logdie("normalization input $full doesn't exist") unless (-e $full);
61                 my $s = read_file( $full ) || $log->logdie("can't read $full: $!");
62                 $log->debug("adding $path to parser [",length($s)," bytes]");
63                 $source .= $s;
64         } );
65
66         $log->debug("collected ", length($source), " bytes of source");
67
68         $self->{source} = $source;
69
70         $self ? return $self : return undef;
71 }
72
73 =head2 parse
74
75 =cut
76
77 sub parse {
78         my $self = shift;
79
80         my $log = $self->_get_logger();
81
82         $log->logdie('no source found in object') unless ($self->{source});
83
84         my $Document = PPI::Document->new( \$self->{source} ) || $log->logdie("can't parse source:\n", $self->{source});
85
86         $Document->prune('PPI::Token::Whitespace');
87         #$Document->prune('PPI::Token::Operator');
88
89         # Find all the named subroutines
90
91         my $eval_create;
92
93         $Document->find( sub {
94                         my ($Document,$Element) = @_;
95
96                         $Element->isa('PPI::Token::Word') or return '';
97                         $Element->content eq 'lookup' or return '';
98
99                         print "#*** expansion: ", $Element->snext_sibling,$/;
100
101                         my $args = $Element->snext_sibling;
102                 
103                         my @e = $args->child(0)->elements;
104                         print "hum, expect at least 8 elements, got ", scalar @e, " in $args\n" if ($#e < 8);
105
106                         print "# found ", scalar @e, " elements:\n";
107
108                         foreach my $i ( 0 .. $#e ) {
109                                 printf("# %-2d: %-30s %s\n", $i, ( $e[$i] || 'undef' ), $e[$i]->class );
110                         }
111
112                         my $key_element = $e[8]->clone;
113
114                         die "key element must be PPI::Structure::Block" unless $key_element->isa('PPI::Structure::Block');
115
116                         print "## key part: ", $key_element, $/;
117
118                         my @key;
119
120                         $key_element->find( sub {
121                                 my $e = $_[1] || die "no element?";
122                                 $e->isa('PPI::Token::Word') or return '';
123                                 $e->content eq 'rec' or return '';
124
125                                 my $kf = $e->snext_sibling;
126
127                                 print "## key fragment = $kf\n";
128
129                                 push @key, eval $kf;
130                                 print "ERROR: can't eval { $kf }: $@" if ($@);
131
132                                 return 1;
133                         });
134
135                         my $key = join('-', @key ) || print "ERROR: no key found!";
136
137                         print "key = $key\n";
138
139                         my $create = ' 
140                                 $coderef = ' . $e[7] . $e[8] . ';
141                                 foreach my $v ($coderef->()) {
142                                         next unless (defined($v) && $v ne \'\');
143                                         push @{ $lookup->{\'' . $key . '\'}->{$v} }, $mfn;
144                                 }
145                         ';
146
147                         print "create: $create\n";
148
149                         $create =~ s/\s+/ /gs;
150                         $eval_create->{ $e[3] }->{ $e[5] } .= $create;
151
152                         if ($#e < 10) {
153                                 $e[8]->insert_after( $e[8]->clone );
154                                 $e[8]->insert_after( $e[7]->clone );
155                                 $e[8]->insert_after( $e[6]->clone );
156                         }
157
158                         $e[7]->remove;
159                         $e[8]->insert_before( new PPI::Token::Quote::Single( "'$key'" ) );
160                         $e[8]->remove;
161
162
163                         print "# >>> ", $Element->snext_sibling, "\n";
164         });
165
166         print "-----\ncreate: ", dump($eval_create), "\n";
167         print "-----\nlookup: ", $Document->serialize, "\n";
168         print "-----\n";
169
170         my $Dumper = PPI::Dumper->new( $Document );
171         $Dumper->print;
172
173 }
174
175 =head1 AUTHOR
176
177 Dobrica Pavlinusic, C<< <dpavlin@rot13.org> >>
178
179 =head1 COPYRIGHT & LICENSE
180
181 Copyright 2006 Dobrica Pavlinusic, All Rights Reserved.
182
183 This program is free software; you can redistribute it and/or modify it
184 under the same terms as Perl itself.
185
186 =cut
187
188 1; # End of WebPAC::Parser