source: text-formbuilder/trunk/lib/Class/ParseText/Base.pm @ 75

Last change on this file since 75 was 75, checked in by peichman, 19 years ago

completed and documented the parse_handle method

File size: 5.4 KB
Line 
1package Class::ParseText::Base;
2
3use strict;
4use warnings;
5use Carp;
6
7use base qw(Class::Base);
8use vars qw($VERSION);
9
10$VERSION = '0.01';
11
12# (caller(0))[3] => fully qualified subname (e.g. My::Package::function)
13
14sub parse {
15    my ($self, $source) = @_;
16    if (my $type = ref $source) {
17        if ($type eq 'SCALAR') {
18            $self->parse_text($$source);
19        } elsif ($type eq 'ARRAY') {
20            $self->parse_array(@$source);
21        } else {
22            croak '[' . (caller(0))[3] . "] Unknown ref type $type passed as source";
23        }
24    } else {
25        $self->parse_file($source);
26    }
27}
28
29sub parse_array {
30    my ($self, @lines) = @_;
31    # so it can be called as a class method
32    $self = $self->new unless ref $self;   
33    $self->parse_text(join("\n", @lines));   
34    return $self;
35}
36
37sub parse_file {
38    my ($self, $filename) = @_;
39   
40    # so it can be called as a class method
41    $self = $self->new unless ref $self;
42   
43    local $/ = undef;
44    open SRC, "< $filename" or croak '[' . (caller(0))[3] . "] Can't open $filename: $!";
45    my $src = <SRC>;
46    close SRC;
47   
48    return $self->parse_text($src);
49}
50
51sub parse_handle {
52    my ($self, $fh) = @_;
53   
54    # so it can be called as a class method
55    $self = $self->new unless ref $self;
56   
57    my $src;
58    local $/ = undef;
59    $src = readline($fh);
60    close $fh;
61    return $self->parse_text($src);
62}
63
64sub parse_text {
65    my ($self, $src) = @_;
66   
67    # so it can be called as a class method
68    $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        unless defined $self->{parser};
72   
73    # optionally ensure that the source text ends in a newline
74    $src =~ /\n$/ or $src .= "\n" if $self->{ensure_newline};
75   
76    # get the name of the start rule
77    my $start_rule = $self->{start_rule};
78    croak '[' . (caller(0))[3] . '] No start rule given for the parser' unless defined $start_rule;
79   
80    $self->{$start_rule} = $self->{parser}->$start_rule($src);
81   
82    # mark structures as not built (newly parsed text)
83    $self->{built} = 0;
84   
85    return $self;
86}
87
88
89# module return
901;
91
92=head1 NAME
93
94Class::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
130This base class is in turn based on L<Class::Base>.
131
132=head1 DESCRIPTION
133
134All of the parse rules set C<< $self->{built} >> to false, to indicate that
135a fresh source has been read, and (probably) needs to be analyzed.
136
137=head2 new
138
139    my $p = My::Parser->new;
140
141Creates a new parser object. In general, calling C<new> explicitly is not
142necessary, since all of the C<parse> methods will invoke the constructor
143for 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
152Parses the contents of of the file C<$filename>. Returns the parser object.
153
154=head2 parse_handle
155
156    $p->parse_handle($fh);
157
158Slurps the remainder of the file handle C<$fh> and parses the contents.
159Returns the parser object.
160
161=head2 parse_array
162
163    $p->parse_array(@lines);
164
165Joins C<@lines> with newlines and parses. Returns the parser object.
166
167=head2 parse_text
168
169    $p->parse_text($source);
170
171Parse the literal C<$source>. Returns the parser object.
172
173=head2 parse
174
175    $p->parse($src);
176
177Automagic method that tries to pick the correct C<parse_*> method to use.
178
179    ref $src            method
180    ========            ==================
181    ARRAY               parse_array(@$src)
182    SCALAR              parse_text($$src)
183    undef               parse_file($src)
184
185Passing other ref types in C<$src> (e.g. C<HASH>) will cause C<parse> to die.
186
187=head1 SUBCLASSING
188
189This class is definitely intended to be subclassed. The only method you should
190need to override is the C<init> method, to set the parser object that will do the
191actual work.
192
193=head2 init
194
195The following properties of the object should be set:
196
197=over
198
199=item C<parser>
200
201The Parse::RecDescent derived parser object to use.
202
203=item C<start_rule>
204
205The name of the initial rule to start parsing with. The results of
206the parse are stored in the object with this same name as their key.
207
208=item C<ensure_newline>
209
210Set to true to ensure that the text to be parsed ends in a newline.
211
212=back
213
214I<Be sure that you explicitly return the object!> This is a bug that
215has bitten me a number of times.
216
217=head1 TODO
218
219C<parse_handle> method
220
221Expand to use other sorts of parsing modules (e.g. Parse::Yapp)
222
223=head1 AUTHOR
224
225Peter Eichman, C<< <peichman@cpan.org> >>
226
227=head1 COPYRIGHT AND LICENSE
228
229Copyright E<copy>2005 by Peter Eichman.
230
231This program is free software; you can redistribute it and/or
232modify it under the same terms as Perl itself.
233
234=cut
Note: See TracBrowser for help on using the repository browser.