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

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

updated version number
added Class::Base to dependancies
laid groundwork for using !groups directly in a form line

File size: 5.3 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
51#TODO: get this working
52sub parse_handle {
53    my ($self, $fh) = @_;
54   
55    # so it can be called as a class method
56    $self = $self->new unless ref $self;
57   
58    my $src;
59    while ($_ = readline($fh)) { $src .= $_ }
60    warn $src;
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_array
155
156    $p->parse_array(@lines);
157
158Joins C<@lines> with newlines and parses. Returns the parser object.
159
160=head2 parse_text
161
162    $p->parse_text($source);
163
164Parse the literal C<$source>. Returns the parser object.
165
166=head2 parse
167
168    $p->parse($src);
169
170Automagic method that tries to pick the correct C<parse_*> 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
178Passing other ref types in C<$src> (e.g. C<HASH>) will cause C<parse> to die.
179
180=head1 SUBCLASSING
181
182This class is definitely intended to be subclassed. The only method you should
183need to override is the C<init> method, to set the parser object that will do the
184actual work.
185
186=head2 init
187
188The following properties of the object should be set:
189
190=over
191
192=item C<parser>
193
194The Parse::RecDescent derived parser object to use.
195
196=item C<start_rule>
197
198The name of the initial rule to start parsing with. The results of
199the parse are stored in the object with this same name as their key.
200
201=item C<ensure_newline>
202
203Set to true to ensure that the text to be parsed ends in a newline.
204
205=back
206
207I<Be sure that you explicitly return the object!> This is a bug that
208has bitten me a number of times.
209
210=head1 TODO
211
212C<parse_handle> method
213
214Expand to use other sorts of parsing modules (e.g. Parse::Yapp)
215
216=head1 AUTHOR
217
218Peter Eichman, C<< <peichman@cpan.org> >>
219
220=head1 COPYRIGHT AND LICENSE
221
222Copyright E<copy>2005 by Peter Eichman.
223
224This program is free software; you can redistribute it and/or
225modify it under the same terms as Perl itself.
226
227=cut
Note: See TracBrowser for help on using the repository browser.