File Coverage

blib/lib/Class/ParseText/Base.pm
Criterion Covered Total %
statement 33 50 66.0
branch 9 24 37.5
condition 2 2 100.0
subroutine 8 10 80.0
pod 5 5 100.0
total 57 91 62.6


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