File Coverage

blib/lib/Class/ParseText/Base.pm
Criterion Covered Total %
statement 28 49 57.1
branch 7 22 31.8
condition 2 2 100.0
subroutine 7 10 70.0
pod 4 5 80.0
total 48 88 54.5


line stmt bran cond sub pod time code
1             package Class::ParseText::Base;
2              
3 1     1   4 use strict;
  1         1  
  1         21  
4 1     1   3 use warnings;
  1         1  
  1         19  
5 1     1   3 use Carp;
  1         1  
  1         63  
6              
7 1     1   3 use base qw(Class::Base);
  1         1  
  1         455  
8 1     1   891 use vars qw($VERSION);
  1         1  
  1         450  
9              
10             $VERSION = '0.01';
11              
12             # (caller(0))[3] => fully qualified subname (e.g. My::Package::function)
13              
14             sub parse {
15 2     2 1 991 my ($self, $source) = @_;
16 2 50       11 if (my $type = ref $source) {
17 2 50       5 if ($type eq 'SCALAR') {
    0          
18 2         5 $self->parse_text($$source);
19             } elsif ($type eq 'ARRAY') {
20 0         0 $self->parse_array(@$source);
21             } else {
22 0         0 croak '[' . (caller(0))[3] . "] Unknown ref type $type passed as source";
23             }
24             } else {
25 0         0 $self->parse_file($source);
26             }
27             }
28              
29             sub parse_array {
30 0     0 1 0 my ($self, @lines) = @_;
31             # so it can be called as a class method
32 0 0       0 $self = $self->new unless ref $self;
33 0         0 $self->parse_text(join("\n", @lines));
34 0         0 return $self;
35             }
36              
37             sub parse_file {
38 0     0 1 0 my ($self, $filename) = @_;
39            
40             # so it can be called as a class method
41 0 0       0 $self = $self->new unless ref $self;
42            
43 0         0 local $/ = undef;
44 0 0       0 open SRC, "< $filename" or croak '[' . (caller(0))[3] . "] Can't open $filename: $!";
45 0         0 my $src = ;
46 0         0 close SRC;
47            
48 0         0 return $self->parse_text($src);
49             }
50              
51             #TODO: get this working
52             sub parse_handle {
53 0     0 0 0 my ($self, $fh) = @_;
54            
55             # so it can be called as a class method
56 0 0       0 $self = $self->new unless ref $self;
57            
58 0         0 my $src;
59 0         0 while ($_ = readline($fh)) { $src .= $_ }
  0         0  
60 0         0 warn $src;
61 0         0 return $self->parse_text($src);
62             }
63              
64             sub parse_text {
65 5     5 1 862 my ($self, $src) = @_;
66            
67             # so it can be called as a class method
68 5 100       18 $self = $self->new unless ref $self;
69            
70             croak '[' . (caller(0))[3] . '] No parser defined for this class (perhaps you need to override init?)'
71 5 50       18 unless defined $self->{parser};
72            
73             # optionally ensure that the source text ends in a newline
74 5 50 100     21 $src =~ /\n$/ or $src .= "\n" if $self->{ensure_newline};
75            
76             # get the name of the start rule
77 5         7 my $start_rule = $self->{start_rule};
78 5 50       12 croak '[' . (caller(0))[3] . '] No start rule given for the parser' unless defined $start_rule;
79            
80 5         47 $self->{$start_rule} = $self->{parser}->$start_rule($src);
81            
82             # mark structures as not built (newly parsed text)
83 5         70 $self->{built} = 0;
84            
85 5         22 return $self;
86             }
87              
88              
89             # module return
90             1;
91              
92             =head1 NAME
93              
94             Class::ParseText::Base - Base class for modules using Parse::RecDescent parsers
95              
96             =head1 SYNOPSIS
97              
98             package My::Parser;
99             use strict;
100            
101             use base qw(Class::ParseText::Base);
102            
103             # you need to provide an init method, to set the parser and start rule
104             sub init {
105             my $self = shift;
106            
107             # set the parser and start rule that should be used
108             $self->{parser} = Parse::RecDescent->new($grammar);
109             $self->{start_rule} = 'foo';
110             $self->{ensure_newline} = 1;
111            
112             return $self;
113             }
114            
115             package main;
116            
117             my $p = My::Parser->new;
118            
119             $p->parse_text($source_text);
120             $p->parse(\$source_text);
121            
122             $p->parse_array(@source_lines);
123             $p->parse(\@source_lines);
124            
125             $p->parse_file($filename);
126             $p->parse($filename);
127              
128             =head1 REQUIRES
129              
130             This base class is in turn based on L.
131              
132             =head1 DESCRIPTION
133              
134             All of the parse rules set C<< $self->{built} >> to false, to indicate that
135             a fresh source has been read, and (probably) needs to be analyzed.
136              
137             =head2 new
138              
139             my $p = My::Parser->new;
140              
141             Creates a new parser object. In general, calling C explicitly is not
142             necessary, since all of the C methods will invoke the constructor
143             for you if they are called as a class method.
144              
145             # as a class method
146             my $p = My::Parser->parse_file('some_source.txt');
147              
148             =head2 parse_file
149              
150             $p->parse_file($filename);
151              
152             Parses the contents of of the file C<$filename>. Returns the parser object.
153              
154             =head2 parse_array
155              
156             $p->parse_array(@lines);
157              
158             Joins C<@lines> with newlines and parses. Returns the parser object.
159              
160             =head2 parse_text
161              
162             $p->parse_text($source);
163              
164             Parse the literal C<$source>. Returns the parser object.
165              
166             =head2 parse
167              
168             $p->parse($src);
169              
170             Automagic method that tries to pick the correct C method to use.
171              
172             ref $src method
173             ======== ==================
174             ARRAY parse_array(@$src)
175             SCALAR parse_text($$src)
176             undef parse_file($src)
177              
178             Passing other ref types in C<$src> (e.g. C) will cause C to die.
179              
180             =head1 SUBCLASSING
181              
182             This class is definitely intended to be subclassed. The only method you should
183             need to override is the C method, to set the parser object that will do the
184             actual work.
185              
186             =head2 init
187              
188             The following properties of the object should be set:
189              
190             =over
191              
192             =item C
193              
194             The Parse::RecDescent derived parser object to use.
195              
196             =item C
197              
198             The name of the initial rule to start parsing with. The results of
199             the parse are stored in the object with this same name as their key.
200              
201             =item C
202              
203             Set to true to ensure that the text to be parsed ends in a newline.
204              
205             =back
206              
207             I This is a bug that
208             has bitten me a number of times.
209              
210             =head1 TODO
211              
212             C method
213              
214             Expand to use other sorts of parsing modules (e.g. Parse::Yapp)
215              
216             =head1 AUTHOR
217              
218             Peter Eichman, C<< >>
219              
220             =head1 COPYRIGHT AND LICENSE
221            
222             Copyright E2005 by Peter Eichman.
223            
224             This program is free software; you can redistribute it and/or
225             modify it under the same terms as Perl itself.
226            
227             =cut