xref: /onnv-gate/usr/src/cmd/perl/5.8.4/distrib/lib/Pod/Parser.pm (revision 0:68f95e015346)
1*0Sstevel@tonic-gate#############################################################################
2*0Sstevel@tonic-gate# Pod/Parser.pm -- package which defines a base class for parsing POD docs.
3*0Sstevel@tonic-gate#
4*0Sstevel@tonic-gate# Copyright (C) 1996-2000 by Bradford Appleton. All rights reserved.
5*0Sstevel@tonic-gate# This file is part of "PodParser". PodParser is free software;
6*0Sstevel@tonic-gate# you can redistribute it and/or modify it under the same terms
7*0Sstevel@tonic-gate# as Perl itself.
8*0Sstevel@tonic-gate#############################################################################
9*0Sstevel@tonic-gate
10*0Sstevel@tonic-gatepackage Pod::Parser;
11*0Sstevel@tonic-gate
12*0Sstevel@tonic-gateuse vars qw($VERSION);
13*0Sstevel@tonic-gate$VERSION = 1.14;  ## Current version of this package
14*0Sstevel@tonic-gaterequire  5.005;    ## requires this Perl version or later
15*0Sstevel@tonic-gate
16*0Sstevel@tonic-gate#############################################################################
17*0Sstevel@tonic-gate
18*0Sstevel@tonic-gate=head1 NAME
19*0Sstevel@tonic-gate
20*0Sstevel@tonic-gatePod::Parser - base class for creating POD filters and translators
21*0Sstevel@tonic-gate
22*0Sstevel@tonic-gate=head1 SYNOPSIS
23*0Sstevel@tonic-gate
24*0Sstevel@tonic-gate    use Pod::Parser;
25*0Sstevel@tonic-gate
26*0Sstevel@tonic-gate    package MyParser;
27*0Sstevel@tonic-gate    @ISA = qw(Pod::Parser);
28*0Sstevel@tonic-gate
29*0Sstevel@tonic-gate    sub command {
30*0Sstevel@tonic-gate        my ($parser, $command, $paragraph, $line_num) = @_;
31*0Sstevel@tonic-gate        ## Interpret the command and its text; sample actions might be:
32*0Sstevel@tonic-gate        if ($command eq 'head1') { ... }
33*0Sstevel@tonic-gate        elsif ($command eq 'head2') { ... }
34*0Sstevel@tonic-gate        ## ... other commands and their actions
35*0Sstevel@tonic-gate        my $out_fh = $parser->output_handle();
36*0Sstevel@tonic-gate        my $expansion = $parser->interpolate($paragraph, $line_num);
37*0Sstevel@tonic-gate        print $out_fh $expansion;
38*0Sstevel@tonic-gate    }
39*0Sstevel@tonic-gate
40*0Sstevel@tonic-gate    sub verbatim {
41*0Sstevel@tonic-gate        my ($parser, $paragraph, $line_num) = @_;
42*0Sstevel@tonic-gate        ## Format verbatim paragraph; sample actions might be:
43*0Sstevel@tonic-gate        my $out_fh = $parser->output_handle();
44*0Sstevel@tonic-gate        print $out_fh $paragraph;
45*0Sstevel@tonic-gate    }
46*0Sstevel@tonic-gate
47*0Sstevel@tonic-gate    sub textblock {
48*0Sstevel@tonic-gate        my ($parser, $paragraph, $line_num) = @_;
49*0Sstevel@tonic-gate        ## Translate/Format this block of text; sample actions might be:
50*0Sstevel@tonic-gate        my $out_fh = $parser->output_handle();
51*0Sstevel@tonic-gate        my $expansion = $parser->interpolate($paragraph, $line_num);
52*0Sstevel@tonic-gate        print $out_fh $expansion;
53*0Sstevel@tonic-gate    }
54*0Sstevel@tonic-gate
55*0Sstevel@tonic-gate    sub interior_sequence {
56*0Sstevel@tonic-gate        my ($parser, $seq_command, $seq_argument) = @_;
57*0Sstevel@tonic-gate        ## Expand an interior sequence; sample actions might be:
58*0Sstevel@tonic-gate        return "*$seq_argument*"     if ($seq_command eq 'B');
59*0Sstevel@tonic-gate        return "`$seq_argument'"     if ($seq_command eq 'C');
60*0Sstevel@tonic-gate        return "_${seq_argument}_'"  if ($seq_command eq 'I');
61*0Sstevel@tonic-gate        ## ... other sequence commands and their resulting text
62*0Sstevel@tonic-gate    }
63*0Sstevel@tonic-gate
64*0Sstevel@tonic-gate    package main;
65*0Sstevel@tonic-gate
66*0Sstevel@tonic-gate    ## Create a parser object and have it parse file whose name was
67*0Sstevel@tonic-gate    ## given on the command-line (use STDIN if no files were given).
68*0Sstevel@tonic-gate    $parser = new MyParser();
69*0Sstevel@tonic-gate    $parser->parse_from_filehandle(\*STDIN)  if (@ARGV == 0);
70*0Sstevel@tonic-gate    for (@ARGV) { $parser->parse_from_file($_); }
71*0Sstevel@tonic-gate
72*0Sstevel@tonic-gate=head1 REQUIRES
73*0Sstevel@tonic-gate
74*0Sstevel@tonic-gateperl5.005, Pod::InputObjects, Exporter, Symbol, Carp
75*0Sstevel@tonic-gate
76*0Sstevel@tonic-gate=head1 EXPORTS
77*0Sstevel@tonic-gate
78*0Sstevel@tonic-gateNothing.
79*0Sstevel@tonic-gate
80*0Sstevel@tonic-gate=head1 DESCRIPTION
81*0Sstevel@tonic-gate
82*0Sstevel@tonic-gateB<Pod::Parser> is a base class for creating POD filters and translators.
83*0Sstevel@tonic-gateIt handles most of the effort involved with parsing the POD sections
84*0Sstevel@tonic-gatefrom an input stream, leaving subclasses free to be concerned only with
85*0Sstevel@tonic-gateperforming the actual translation of text.
86*0Sstevel@tonic-gate
87*0Sstevel@tonic-gateB<Pod::Parser> parses PODs, and makes method calls to handle the various
88*0Sstevel@tonic-gatecomponents of the POD. Subclasses of B<Pod::Parser> override these methods
89*0Sstevel@tonic-gateto translate the POD into whatever output format they desire.
90*0Sstevel@tonic-gate
91*0Sstevel@tonic-gate=head1 QUICK OVERVIEW
92*0Sstevel@tonic-gate
93*0Sstevel@tonic-gateTo create a POD filter for translating POD documentation into some other
94*0Sstevel@tonic-gateformat, you create a subclass of B<Pod::Parser> which typically overrides
95*0Sstevel@tonic-gatejust the base class implementation for the following methods:
96*0Sstevel@tonic-gate
97*0Sstevel@tonic-gate=over 2
98*0Sstevel@tonic-gate
99*0Sstevel@tonic-gate=item *
100*0Sstevel@tonic-gate
101*0Sstevel@tonic-gateB<command()>
102*0Sstevel@tonic-gate
103*0Sstevel@tonic-gate=item *
104*0Sstevel@tonic-gate
105*0Sstevel@tonic-gateB<verbatim()>
106*0Sstevel@tonic-gate
107*0Sstevel@tonic-gate=item *
108*0Sstevel@tonic-gate
109*0Sstevel@tonic-gateB<textblock()>
110*0Sstevel@tonic-gate
111*0Sstevel@tonic-gate=item *
112*0Sstevel@tonic-gate
113*0Sstevel@tonic-gateB<interior_sequence()>
114*0Sstevel@tonic-gate
115*0Sstevel@tonic-gate=back
116*0Sstevel@tonic-gate
117*0Sstevel@tonic-gateYou may also want to override the B<begin_input()> and B<end_input()>
118*0Sstevel@tonic-gatemethods for your subclass (to perform any needed per-file and/or
119*0Sstevel@tonic-gateper-document initialization or cleanup).
120*0Sstevel@tonic-gate
121*0Sstevel@tonic-gateIf you need to perform any preprocesssing of input before it is parsed
122*0Sstevel@tonic-gateyou may want to override one or more of B<preprocess_line()> and/or
123*0Sstevel@tonic-gateB<preprocess_paragraph()>.
124*0Sstevel@tonic-gate
125*0Sstevel@tonic-gateSometimes it may be necessary to make more than one pass over the input
126*0Sstevel@tonic-gatefiles. If this is the case you have several options. You can make the
127*0Sstevel@tonic-gatefirst pass using B<Pod::Parser> and override your methods to store the
128*0Sstevel@tonic-gateintermediate results in memory somewhere for the B<end_pod()> method to
129*0Sstevel@tonic-gateprocess. You could use B<Pod::Parser> for several passes with an
130*0Sstevel@tonic-gateappropriate state variable to control the operation for each pass. If
131*0Sstevel@tonic-gateyour input source can't be reset to start at the beginning, you can
132*0Sstevel@tonic-gatestore it in some other structure as a string or an array and have that
133*0Sstevel@tonic-gatestructure implement a B<getline()> method (which is all that
134*0Sstevel@tonic-gateB<parse_from_filehandle()> uses to read input).
135*0Sstevel@tonic-gate
136*0Sstevel@tonic-gateFeel free to add any member data fields you need to keep track of things
137*0Sstevel@tonic-gatelike current font, indentation, horizontal or vertical position, or
138*0Sstevel@tonic-gatewhatever else you like. Be sure to read L<"PRIVATE METHODS AND DATA">
139*0Sstevel@tonic-gateto avoid name collisions.
140*0Sstevel@tonic-gate
141*0Sstevel@tonic-gateFor the most part, the B<Pod::Parser> base class should be able to
142*0Sstevel@tonic-gatedo most of the input parsing for you and leave you free to worry about
143*0Sstevel@tonic-gatehow to intepret the commands and translate the result.
144*0Sstevel@tonic-gate
145*0Sstevel@tonic-gateNote that all we have described here in this quick overview is the
146*0Sstevel@tonic-gatesimplest most straightforward use of B<Pod::Parser> to do stream-based
147*0Sstevel@tonic-gateparsing. It is also possible to use the B<Pod::Parser::parse_text> function
148*0Sstevel@tonic-gateto do more sophisticated tree-based parsing. See L<"TREE-BASED PARSING">.
149*0Sstevel@tonic-gate
150*0Sstevel@tonic-gate=head1 PARSING OPTIONS
151*0Sstevel@tonic-gate
152*0Sstevel@tonic-gateA I<parse-option> is simply a named option of B<Pod::Parser> with a
153*0Sstevel@tonic-gatevalue that corresponds to a certain specified behavior. These various
154*0Sstevel@tonic-gatebehaviors of B<Pod::Parser> may be enabled/disabled by setting
155*0Sstevel@tonic-gateor unsetting one or more I<parse-options> using the B<parseopts()> method.
156*0Sstevel@tonic-gateThe set of currently accepted parse-options is as follows:
157*0Sstevel@tonic-gate
158*0Sstevel@tonic-gate=over 3
159*0Sstevel@tonic-gate
160*0Sstevel@tonic-gate=item B<-want_nonPODs> (default: unset)
161*0Sstevel@tonic-gate
162*0Sstevel@tonic-gateNormally (by default) B<Pod::Parser> will only provide access to
163*0Sstevel@tonic-gatethe POD sections of the input. Input paragraphs that are not part
164*0Sstevel@tonic-gateof the POD-format documentation are not made available to the caller
165*0Sstevel@tonic-gate(not even using B<preprocess_paragraph()>). Setting this option to a
166*0Sstevel@tonic-gatenon-empty, non-zero value will allow B<preprocess_paragraph()> to see
167*0Sstevel@tonic-gatenon-POD sections of the input as well as POD sections. The B<cutting()>
168*0Sstevel@tonic-gatemethod can be used to determine if the corresponding paragraph is a POD
169*0Sstevel@tonic-gateparagraph, or some other input paragraph.
170*0Sstevel@tonic-gate
171*0Sstevel@tonic-gate=item B<-process_cut_cmd> (default: unset)
172*0Sstevel@tonic-gate
173*0Sstevel@tonic-gateNormally (by default) B<Pod::Parser> handles the C<=cut> POD directive
174*0Sstevel@tonic-gateby itself and does not pass it on to the caller for processing. Setting
175*0Sstevel@tonic-gatethis option to a non-empty, non-zero value will cause B<Pod::Parser> to
176*0Sstevel@tonic-gatepass the C<=cut> directive to the caller just like any other POD command
177*0Sstevel@tonic-gate(and hence it may be processed by the B<command()> method).
178*0Sstevel@tonic-gate
179*0Sstevel@tonic-gateB<Pod::Parser> will still interpret the C<=cut> directive to mean that
180*0Sstevel@tonic-gate"cutting mode" has been (re)entered, but the caller will get a chance
181*0Sstevel@tonic-gateto capture the actual C<=cut> paragraph itself for whatever purpose
182*0Sstevel@tonic-gateit desires.
183*0Sstevel@tonic-gate
184*0Sstevel@tonic-gate=item B<-warnings> (default: unset)
185*0Sstevel@tonic-gate
186*0Sstevel@tonic-gateNormally (by default) B<Pod::Parser> recognizes a bare minimum of
187*0Sstevel@tonic-gatepod syntax errors and warnings and issues diagnostic messages
188*0Sstevel@tonic-gatefor errors, but not for warnings. (Use B<Pod::Checker> to do more
189*0Sstevel@tonic-gatethorough checking of POD syntax.) Setting this option to a non-empty,
190*0Sstevel@tonic-gatenon-zero value will cause B<Pod::Parser> to issue diagnostics for
191*0Sstevel@tonic-gatethe few warnings it recognizes as well as the errors.
192*0Sstevel@tonic-gate
193*0Sstevel@tonic-gate=back
194*0Sstevel@tonic-gate
195*0Sstevel@tonic-gatePlease see L<"parseopts()"> for a complete description of the interface
196*0Sstevel@tonic-gatefor the setting and unsetting of parse-options.
197*0Sstevel@tonic-gate
198*0Sstevel@tonic-gate=cut
199*0Sstevel@tonic-gate
200*0Sstevel@tonic-gate#############################################################################
201*0Sstevel@tonic-gate
202*0Sstevel@tonic-gateuse vars qw(@ISA);
203*0Sstevel@tonic-gateuse strict;
204*0Sstevel@tonic-gate#use diagnostics;
205*0Sstevel@tonic-gateuse Pod::InputObjects;
206*0Sstevel@tonic-gateuse Carp;
207*0Sstevel@tonic-gateuse Exporter;
208*0Sstevel@tonic-gateBEGIN {
209*0Sstevel@tonic-gate   if ($] < 5.6) {
210*0Sstevel@tonic-gate      require Symbol;
211*0Sstevel@tonic-gate      import Symbol;
212*0Sstevel@tonic-gate   }
213*0Sstevel@tonic-gate}
214*0Sstevel@tonic-gate@ISA = qw(Exporter);
215*0Sstevel@tonic-gate
216*0Sstevel@tonic-gate## These "variables" are used as local "glob aliases" for performance
217*0Sstevel@tonic-gateuse vars qw(%myData %myOpts @input_stack);
218*0Sstevel@tonic-gate
219*0Sstevel@tonic-gate#############################################################################
220*0Sstevel@tonic-gate
221*0Sstevel@tonic-gate=head1 RECOMMENDED SUBROUTINE/METHOD OVERRIDES
222*0Sstevel@tonic-gate
223*0Sstevel@tonic-gateB<Pod::Parser> provides several methods which most subclasses will probably
224*0Sstevel@tonic-gatewant to override. These methods are as follows:
225*0Sstevel@tonic-gate
226*0Sstevel@tonic-gate=cut
227*0Sstevel@tonic-gate
228*0Sstevel@tonic-gate##---------------------------------------------------------------------------
229*0Sstevel@tonic-gate
230*0Sstevel@tonic-gate=head1 B<command()>
231*0Sstevel@tonic-gate
232*0Sstevel@tonic-gate            $parser->command($cmd,$text,$line_num,$pod_para);
233*0Sstevel@tonic-gate
234*0Sstevel@tonic-gateThis method should be overridden by subclasses to take the appropriate
235*0Sstevel@tonic-gateaction when a POD command paragraph (denoted by a line beginning with
236*0Sstevel@tonic-gate"=") is encountered. When such a POD directive is seen in the input,
237*0Sstevel@tonic-gatethis method is called and is passed:
238*0Sstevel@tonic-gate
239*0Sstevel@tonic-gate=over 3
240*0Sstevel@tonic-gate
241*0Sstevel@tonic-gate=item C<$cmd>
242*0Sstevel@tonic-gate
243*0Sstevel@tonic-gatethe name of the command for this POD paragraph
244*0Sstevel@tonic-gate
245*0Sstevel@tonic-gate=item C<$text>
246*0Sstevel@tonic-gate
247*0Sstevel@tonic-gatethe paragraph text for the given POD paragraph command.
248*0Sstevel@tonic-gate
249*0Sstevel@tonic-gate=item C<$line_num>
250*0Sstevel@tonic-gate
251*0Sstevel@tonic-gatethe line-number of the beginning of the paragraph
252*0Sstevel@tonic-gate
253*0Sstevel@tonic-gate=item C<$pod_para>
254*0Sstevel@tonic-gate
255*0Sstevel@tonic-gatea reference to a C<Pod::Paragraph> object which contains further
256*0Sstevel@tonic-gateinformation about the paragraph command (see L<Pod::InputObjects>
257*0Sstevel@tonic-gatefor details).
258*0Sstevel@tonic-gate
259*0Sstevel@tonic-gate=back
260*0Sstevel@tonic-gate
261*0Sstevel@tonic-gateB<Note> that this method I<is> called for C<=pod> paragraphs.
262*0Sstevel@tonic-gate
263*0Sstevel@tonic-gateThe base class implementation of this method simply treats the raw POD
264*0Sstevel@tonic-gatecommand as normal block of paragraph text (invoking the B<textblock()>
265*0Sstevel@tonic-gatemethod with the command paragraph).
266*0Sstevel@tonic-gate
267*0Sstevel@tonic-gate=cut
268*0Sstevel@tonic-gate
269*0Sstevel@tonic-gatesub command {
270*0Sstevel@tonic-gate    my ($self, $cmd, $text, $line_num, $pod_para)  = @_;
271*0Sstevel@tonic-gate    ## Just treat this like a textblock
272*0Sstevel@tonic-gate    $self->textblock($pod_para->raw_text(), $line_num, $pod_para);
273*0Sstevel@tonic-gate}
274*0Sstevel@tonic-gate
275*0Sstevel@tonic-gate##---------------------------------------------------------------------------
276*0Sstevel@tonic-gate
277*0Sstevel@tonic-gate=head1 B<verbatim()>
278*0Sstevel@tonic-gate
279*0Sstevel@tonic-gate            $parser->verbatim($text,$line_num,$pod_para);
280*0Sstevel@tonic-gate
281*0Sstevel@tonic-gateThis method may be overridden by subclasses to take the appropriate
282*0Sstevel@tonic-gateaction when a block of verbatim text is encountered. It is passed the
283*0Sstevel@tonic-gatefollowing parameters:
284*0Sstevel@tonic-gate
285*0Sstevel@tonic-gate=over 3
286*0Sstevel@tonic-gate
287*0Sstevel@tonic-gate=item C<$text>
288*0Sstevel@tonic-gate
289*0Sstevel@tonic-gatethe block of text for the verbatim paragraph
290*0Sstevel@tonic-gate
291*0Sstevel@tonic-gate=item C<$line_num>
292*0Sstevel@tonic-gate
293*0Sstevel@tonic-gatethe line-number of the beginning of the paragraph
294*0Sstevel@tonic-gate
295*0Sstevel@tonic-gate=item C<$pod_para>
296*0Sstevel@tonic-gate
297*0Sstevel@tonic-gatea reference to a C<Pod::Paragraph> object which contains further
298*0Sstevel@tonic-gateinformation about the paragraph (see L<Pod::InputObjects>
299*0Sstevel@tonic-gatefor details).
300*0Sstevel@tonic-gate
301*0Sstevel@tonic-gate=back
302*0Sstevel@tonic-gate
303*0Sstevel@tonic-gateThe base class implementation of this method simply prints the textblock
304*0Sstevel@tonic-gate(unmodified) to the output filehandle.
305*0Sstevel@tonic-gate
306*0Sstevel@tonic-gate=cut
307*0Sstevel@tonic-gate
308*0Sstevel@tonic-gatesub verbatim {
309*0Sstevel@tonic-gate    my ($self, $text, $line_num, $pod_para) = @_;
310*0Sstevel@tonic-gate    my $out_fh = $self->{_OUTPUT};
311*0Sstevel@tonic-gate    print $out_fh $text;
312*0Sstevel@tonic-gate}
313*0Sstevel@tonic-gate
314*0Sstevel@tonic-gate##---------------------------------------------------------------------------
315*0Sstevel@tonic-gate
316*0Sstevel@tonic-gate=head1 B<textblock()>
317*0Sstevel@tonic-gate
318*0Sstevel@tonic-gate            $parser->textblock($text,$line_num,$pod_para);
319*0Sstevel@tonic-gate
320*0Sstevel@tonic-gateThis method may be overridden by subclasses to take the appropriate
321*0Sstevel@tonic-gateaction when a normal block of POD text is encountered (although the base
322*0Sstevel@tonic-gateclass method will usually do what you want). It is passed the following
323*0Sstevel@tonic-gateparameters:
324*0Sstevel@tonic-gate
325*0Sstevel@tonic-gate=over 3
326*0Sstevel@tonic-gate
327*0Sstevel@tonic-gate=item C<$text>
328*0Sstevel@tonic-gate
329*0Sstevel@tonic-gatethe block of text for the a POD paragraph
330*0Sstevel@tonic-gate
331*0Sstevel@tonic-gate=item C<$line_num>
332*0Sstevel@tonic-gate
333*0Sstevel@tonic-gatethe line-number of the beginning of the paragraph
334*0Sstevel@tonic-gate
335*0Sstevel@tonic-gate=item C<$pod_para>
336*0Sstevel@tonic-gate
337*0Sstevel@tonic-gatea reference to a C<Pod::Paragraph> object which contains further
338*0Sstevel@tonic-gateinformation about the paragraph (see L<Pod::InputObjects>
339*0Sstevel@tonic-gatefor details).
340*0Sstevel@tonic-gate
341*0Sstevel@tonic-gate=back
342*0Sstevel@tonic-gate
343*0Sstevel@tonic-gateIn order to process interior sequences, subclasses implementations of
344*0Sstevel@tonic-gatethis method will probably want to invoke either B<interpolate()> or
345*0Sstevel@tonic-gateB<parse_text()>, passing it the text block C<$text>, and the corresponding
346*0Sstevel@tonic-gateline number in C<$line_num>, and then perform any desired processing upon
347*0Sstevel@tonic-gatethe returned result.
348*0Sstevel@tonic-gate
349*0Sstevel@tonic-gateThe base class implementation of this method simply prints the text block
350*0Sstevel@tonic-gateas it occurred in the input stream).
351*0Sstevel@tonic-gate
352*0Sstevel@tonic-gate=cut
353*0Sstevel@tonic-gate
354*0Sstevel@tonic-gatesub textblock {
355*0Sstevel@tonic-gate    my ($self, $text, $line_num, $pod_para) = @_;
356*0Sstevel@tonic-gate    my $out_fh = $self->{_OUTPUT};
357*0Sstevel@tonic-gate    print $out_fh $self->interpolate($text, $line_num);
358*0Sstevel@tonic-gate}
359*0Sstevel@tonic-gate
360*0Sstevel@tonic-gate##---------------------------------------------------------------------------
361*0Sstevel@tonic-gate
362*0Sstevel@tonic-gate=head1 B<interior_sequence()>
363*0Sstevel@tonic-gate
364*0Sstevel@tonic-gate            $parser->interior_sequence($seq_cmd,$seq_arg,$pod_seq);
365*0Sstevel@tonic-gate
366*0Sstevel@tonic-gateThis method should be overridden by subclasses to take the appropriate
367*0Sstevel@tonic-gateaction when an interior sequence is encountered. An interior sequence is
368*0Sstevel@tonic-gatean embedded command within a block of text which appears as a command
369*0Sstevel@tonic-gatename (usually a single uppercase character) followed immediately by a
370*0Sstevel@tonic-gatestring of text which is enclosed in angle brackets. This method is
371*0Sstevel@tonic-gatepassed the sequence command C<$seq_cmd> and the corresponding text
372*0Sstevel@tonic-gateC<$seq_arg>. It is invoked by the B<interpolate()> method for each interior
373*0Sstevel@tonic-gatesequence that occurs in the string that it is passed. It should return
374*0Sstevel@tonic-gatethe desired text string to be used in place of the interior sequence.
375*0Sstevel@tonic-gateThe C<$pod_seq> argument is a reference to a C<Pod::InteriorSequence>
376*0Sstevel@tonic-gateobject which contains further information about the interior sequence.
377*0Sstevel@tonic-gatePlease see L<Pod::InputObjects> for details if you need to access this
378*0Sstevel@tonic-gateadditional information.
379*0Sstevel@tonic-gate
380*0Sstevel@tonic-gateSubclass implementations of this method may wish to invoke the
381*0Sstevel@tonic-gateB<nested()> method of C<$pod_seq> to see if it is nested inside
382*0Sstevel@tonic-gatesome other interior-sequence (and if so, which kind).
383*0Sstevel@tonic-gate
384*0Sstevel@tonic-gateThe base class implementation of the B<interior_sequence()> method
385*0Sstevel@tonic-gatesimply returns the raw text of the interior sequence (as it occurred
386*0Sstevel@tonic-gatein the input) to the caller.
387*0Sstevel@tonic-gate
388*0Sstevel@tonic-gate=cut
389*0Sstevel@tonic-gate
390*0Sstevel@tonic-gatesub interior_sequence {
391*0Sstevel@tonic-gate    my ($self, $seq_cmd, $seq_arg, $pod_seq) = @_;
392*0Sstevel@tonic-gate    ## Just return the raw text of the interior sequence
393*0Sstevel@tonic-gate    return  $pod_seq->raw_text();
394*0Sstevel@tonic-gate}
395*0Sstevel@tonic-gate
396*0Sstevel@tonic-gate#############################################################################
397*0Sstevel@tonic-gate
398*0Sstevel@tonic-gate=head1 OPTIONAL SUBROUTINE/METHOD OVERRIDES
399*0Sstevel@tonic-gate
400*0Sstevel@tonic-gateB<Pod::Parser> provides several methods which subclasses may want to override
401*0Sstevel@tonic-gateto perform any special pre/post-processing. These methods do I<not> have to
402*0Sstevel@tonic-gatebe overridden, but it may be useful for subclasses to take advantage of them.
403*0Sstevel@tonic-gate
404*0Sstevel@tonic-gate=cut
405*0Sstevel@tonic-gate
406*0Sstevel@tonic-gate##---------------------------------------------------------------------------
407*0Sstevel@tonic-gate
408*0Sstevel@tonic-gate=head1 B<new()>
409*0Sstevel@tonic-gate
410*0Sstevel@tonic-gate            my $parser = Pod::Parser->new();
411*0Sstevel@tonic-gate
412*0Sstevel@tonic-gateThis is the constructor for B<Pod::Parser> and its subclasses. You
413*0Sstevel@tonic-gateI<do not> need to override this method! It is capable of constructing
414*0Sstevel@tonic-gatesubclass objects as well as base class objects, provided you use
415*0Sstevel@tonic-gateany of the following constructor invocation styles:
416*0Sstevel@tonic-gate
417*0Sstevel@tonic-gate    my $parser1 = MyParser->new();
418*0Sstevel@tonic-gate    my $parser2 = new MyParser();
419*0Sstevel@tonic-gate    my $parser3 = $parser2->new();
420*0Sstevel@tonic-gate
421*0Sstevel@tonic-gatewhere C<MyParser> is some subclass of B<Pod::Parser>.
422*0Sstevel@tonic-gate
423*0Sstevel@tonic-gateUsing the syntax C<MyParser::new()> to invoke the constructor is I<not>
424*0Sstevel@tonic-gaterecommended, but if you insist on being able to do this, then the
425*0Sstevel@tonic-gatesubclass I<will> need to override the B<new()> constructor method. If
426*0Sstevel@tonic-gateyou do override the constructor, you I<must> be sure to invoke the
427*0Sstevel@tonic-gateB<initialize()> method of the newly blessed object.
428*0Sstevel@tonic-gate
429*0Sstevel@tonic-gateUsing any of the above invocations, the first argument to the
430*0Sstevel@tonic-gateconstructor is always the corresponding package name (or object
431*0Sstevel@tonic-gatereference). No other arguments are required, but if desired, an
432*0Sstevel@tonic-gateassociative array (or hash-table) my be passed to the B<new()>
433*0Sstevel@tonic-gateconstructor, as in:
434*0Sstevel@tonic-gate
435*0Sstevel@tonic-gate    my $parser1 = MyParser->new( MYDATA => $value1, MOREDATA => $value2 );
436*0Sstevel@tonic-gate    my $parser2 = new MyParser( -myflag => 1 );
437*0Sstevel@tonic-gate
438*0Sstevel@tonic-gateAll arguments passed to the B<new()> constructor will be treated as
439*0Sstevel@tonic-gatekey/value pairs in a hash-table. The newly constructed object will be
440*0Sstevel@tonic-gateinitialized by copying the contents of the given hash-table (which may
441*0Sstevel@tonic-gatehave been empty). The B<new()> constructor for this class and all of its
442*0Sstevel@tonic-gatesubclasses returns a blessed reference to the initialized object (hash-table).
443*0Sstevel@tonic-gate
444*0Sstevel@tonic-gate=cut
445*0Sstevel@tonic-gate
446*0Sstevel@tonic-gatesub new {
447*0Sstevel@tonic-gate    ## Determine if we were called via an object-ref or a classname
448*0Sstevel@tonic-gate    my $this = shift;
449*0Sstevel@tonic-gate    my $class = ref($this) || $this;
450*0Sstevel@tonic-gate    ## Any remaining arguments are treated as initial values for the
451*0Sstevel@tonic-gate    ## hash that is used to represent this object.
452*0Sstevel@tonic-gate    my %params = @_;
453*0Sstevel@tonic-gate    my $self = { %params };
454*0Sstevel@tonic-gate    ## Bless ourselves into the desired class and perform any initialization
455*0Sstevel@tonic-gate    bless $self, $class;
456*0Sstevel@tonic-gate    $self->initialize();
457*0Sstevel@tonic-gate    return $self;
458*0Sstevel@tonic-gate}
459*0Sstevel@tonic-gate
460*0Sstevel@tonic-gate##---------------------------------------------------------------------------
461*0Sstevel@tonic-gate
462*0Sstevel@tonic-gate=head1 B<initialize()>
463*0Sstevel@tonic-gate
464*0Sstevel@tonic-gate            $parser->initialize();
465*0Sstevel@tonic-gate
466*0Sstevel@tonic-gateThis method performs any necessary object initialization. It takes no
467*0Sstevel@tonic-gatearguments (other than the object instance of course, which is typically
468*0Sstevel@tonic-gatecopied to a local variable named C<$self>). If subclasses override this
469*0Sstevel@tonic-gatemethod then they I<must> be sure to invoke C<$self-E<gt>SUPER::initialize()>.
470*0Sstevel@tonic-gate
471*0Sstevel@tonic-gate=cut
472*0Sstevel@tonic-gate
473*0Sstevel@tonic-gatesub initialize {
474*0Sstevel@tonic-gate    #my $self = shift;
475*0Sstevel@tonic-gate    #return;
476*0Sstevel@tonic-gate}
477*0Sstevel@tonic-gate
478*0Sstevel@tonic-gate##---------------------------------------------------------------------------
479*0Sstevel@tonic-gate
480*0Sstevel@tonic-gate=head1 B<begin_pod()>
481*0Sstevel@tonic-gate
482*0Sstevel@tonic-gate            $parser->begin_pod();
483*0Sstevel@tonic-gate
484*0Sstevel@tonic-gateThis method is invoked at the beginning of processing for each POD
485*0Sstevel@tonic-gatedocument that is encountered in the input. Subclasses should override
486*0Sstevel@tonic-gatethis method to perform any per-document initialization.
487*0Sstevel@tonic-gate
488*0Sstevel@tonic-gate=cut
489*0Sstevel@tonic-gate
490*0Sstevel@tonic-gatesub begin_pod {
491*0Sstevel@tonic-gate    #my $self = shift;
492*0Sstevel@tonic-gate    #return;
493*0Sstevel@tonic-gate}
494*0Sstevel@tonic-gate
495*0Sstevel@tonic-gate##---------------------------------------------------------------------------
496*0Sstevel@tonic-gate
497*0Sstevel@tonic-gate=head1 B<begin_input()>
498*0Sstevel@tonic-gate
499*0Sstevel@tonic-gate            $parser->begin_input();
500*0Sstevel@tonic-gate
501*0Sstevel@tonic-gateThis method is invoked by B<parse_from_filehandle()> immediately I<before>
502*0Sstevel@tonic-gateprocessing input from a filehandle. The base class implementation does
503*0Sstevel@tonic-gatenothing, however, subclasses may override it to perform any per-file
504*0Sstevel@tonic-gateinitializations.
505*0Sstevel@tonic-gate
506*0Sstevel@tonic-gateNote that if multiple files are parsed for a single POD document
507*0Sstevel@tonic-gate(perhaps the result of some future C<=include> directive) this method
508*0Sstevel@tonic-gateis invoked for every file that is parsed. If you wish to perform certain
509*0Sstevel@tonic-gateinitializations once per document, then you should use B<begin_pod()>.
510*0Sstevel@tonic-gate
511*0Sstevel@tonic-gate=cut
512*0Sstevel@tonic-gate
513*0Sstevel@tonic-gatesub begin_input {
514*0Sstevel@tonic-gate    #my $self = shift;
515*0Sstevel@tonic-gate    #return;
516*0Sstevel@tonic-gate}
517*0Sstevel@tonic-gate
518*0Sstevel@tonic-gate##---------------------------------------------------------------------------
519*0Sstevel@tonic-gate
520*0Sstevel@tonic-gate=head1 B<end_input()>
521*0Sstevel@tonic-gate
522*0Sstevel@tonic-gate            $parser->end_input();
523*0Sstevel@tonic-gate
524*0Sstevel@tonic-gateThis method is invoked by B<parse_from_filehandle()> immediately I<after>
525*0Sstevel@tonic-gateprocessing input from a filehandle. The base class implementation does
526*0Sstevel@tonic-gatenothing, however, subclasses may override it to perform any per-file
527*0Sstevel@tonic-gatecleanup actions.
528*0Sstevel@tonic-gate
529*0Sstevel@tonic-gatePlease note that if multiple files are parsed for a single POD document
530*0Sstevel@tonic-gate(perhaps the result of some kind of C<=include> directive) this method
531*0Sstevel@tonic-gateis invoked for every file that is parsed. If you wish to perform certain
532*0Sstevel@tonic-gatecleanup actions once per document, then you should use B<end_pod()>.
533*0Sstevel@tonic-gate
534*0Sstevel@tonic-gate=cut
535*0Sstevel@tonic-gate
536*0Sstevel@tonic-gatesub end_input {
537*0Sstevel@tonic-gate    #my $self = shift;
538*0Sstevel@tonic-gate    #return;
539*0Sstevel@tonic-gate}
540*0Sstevel@tonic-gate
541*0Sstevel@tonic-gate##---------------------------------------------------------------------------
542*0Sstevel@tonic-gate
543*0Sstevel@tonic-gate=head1 B<end_pod()>
544*0Sstevel@tonic-gate
545*0Sstevel@tonic-gate            $parser->end_pod();
546*0Sstevel@tonic-gate
547*0Sstevel@tonic-gateThis method is invoked at the end of processing for each POD document
548*0Sstevel@tonic-gatethat is encountered in the input. Subclasses should override this method
549*0Sstevel@tonic-gateto perform any per-document finalization.
550*0Sstevel@tonic-gate
551*0Sstevel@tonic-gate=cut
552*0Sstevel@tonic-gate
553*0Sstevel@tonic-gatesub end_pod {
554*0Sstevel@tonic-gate    #my $self = shift;
555*0Sstevel@tonic-gate    #return;
556*0Sstevel@tonic-gate}
557*0Sstevel@tonic-gate
558*0Sstevel@tonic-gate##---------------------------------------------------------------------------
559*0Sstevel@tonic-gate
560*0Sstevel@tonic-gate=head1 B<preprocess_line()>
561*0Sstevel@tonic-gate
562*0Sstevel@tonic-gate          $textline = $parser->preprocess_line($text, $line_num);
563*0Sstevel@tonic-gate
564*0Sstevel@tonic-gateThis method should be overridden by subclasses that wish to perform
565*0Sstevel@tonic-gateany kind of preprocessing for each I<line> of input (I<before> it has
566*0Sstevel@tonic-gatebeen determined whether or not it is part of a POD paragraph). The
567*0Sstevel@tonic-gateparameter C<$text> is the input line; and the parameter C<$line_num> is
568*0Sstevel@tonic-gatethe line number of the corresponding text line.
569*0Sstevel@tonic-gate
570*0Sstevel@tonic-gateThe value returned should correspond to the new text to use in its
571*0Sstevel@tonic-gateplace.  If the empty string or an undefined value is returned then no
572*0Sstevel@tonic-gatefurther processing will be performed for this line.
573*0Sstevel@tonic-gate
574*0Sstevel@tonic-gatePlease note that the B<preprocess_line()> method is invoked I<before>
575*0Sstevel@tonic-gatethe B<preprocess_paragraph()> method. After all (possibly preprocessed)
576*0Sstevel@tonic-gatelines in a paragraph have been assembled together and it has been
577*0Sstevel@tonic-gatedetermined that the paragraph is part of the POD documentation from one
578*0Sstevel@tonic-gateof the selected sections, then B<preprocess_paragraph()> is invoked.
579*0Sstevel@tonic-gate
580*0Sstevel@tonic-gateThe base class implementation of this method returns the given text.
581*0Sstevel@tonic-gate
582*0Sstevel@tonic-gate=cut
583*0Sstevel@tonic-gate
584*0Sstevel@tonic-gatesub preprocess_line {
585*0Sstevel@tonic-gate    my ($self, $text, $line_num) = @_;
586*0Sstevel@tonic-gate    return  $text;
587*0Sstevel@tonic-gate}
588*0Sstevel@tonic-gate
589*0Sstevel@tonic-gate##---------------------------------------------------------------------------
590*0Sstevel@tonic-gate
591*0Sstevel@tonic-gate=head1 B<preprocess_paragraph()>
592*0Sstevel@tonic-gate
593*0Sstevel@tonic-gate            $textblock = $parser->preprocess_paragraph($text, $line_num);
594*0Sstevel@tonic-gate
595*0Sstevel@tonic-gateThis method should be overridden by subclasses that wish to perform any
596*0Sstevel@tonic-gatekind of preprocessing for each block (paragraph) of POD documentation
597*0Sstevel@tonic-gatethat appears in the input stream. The parameter C<$text> is the POD
598*0Sstevel@tonic-gateparagraph from the input file; and the parameter C<$line_num> is the
599*0Sstevel@tonic-gateline number for the beginning of the corresponding paragraph.
600*0Sstevel@tonic-gate
601*0Sstevel@tonic-gateThe value returned should correspond to the new text to use in its
602*0Sstevel@tonic-gateplace If the empty string is returned or an undefined value is
603*0Sstevel@tonic-gatereturned, then the given C<$text> is ignored (not processed).
604*0Sstevel@tonic-gate
605*0Sstevel@tonic-gateThis method is invoked after gathering up all the lines in a paragraph
606*0Sstevel@tonic-gateand after determining the cutting state of the paragraph,
607*0Sstevel@tonic-gatebut before trying to further parse or interpret them. After
608*0Sstevel@tonic-gateB<preprocess_paragraph()> returns, the current cutting state (which
609*0Sstevel@tonic-gateis returned by C<$self-E<gt>cutting()>) is examined. If it evaluates
610*0Sstevel@tonic-gateto true then input text (including the given C<$text>) is cut (not
611*0Sstevel@tonic-gateprocessed) until the next POD directive is encountered.
612*0Sstevel@tonic-gate
613*0Sstevel@tonic-gatePlease note that the B<preprocess_line()> method is invoked I<before>
614*0Sstevel@tonic-gatethe B<preprocess_paragraph()> method. After all (possibly preprocessed)
615*0Sstevel@tonic-gatelines in a paragraph have been assembled together and either it has been
616*0Sstevel@tonic-gatedetermined that the paragraph is part of the POD documentation from one
617*0Sstevel@tonic-gateof the selected sections or the C<-want_nonPODs> option is true,
618*0Sstevel@tonic-gatethen B<preprocess_paragraph()> is invoked.
619*0Sstevel@tonic-gate
620*0Sstevel@tonic-gateThe base class implementation of this method returns the given text.
621*0Sstevel@tonic-gate
622*0Sstevel@tonic-gate=cut
623*0Sstevel@tonic-gate
624*0Sstevel@tonic-gatesub preprocess_paragraph {
625*0Sstevel@tonic-gate    my ($self, $text, $line_num) = @_;
626*0Sstevel@tonic-gate    return  $text;
627*0Sstevel@tonic-gate}
628*0Sstevel@tonic-gate
629*0Sstevel@tonic-gate#############################################################################
630*0Sstevel@tonic-gate
631*0Sstevel@tonic-gate=head1 METHODS FOR PARSING AND PROCESSING
632*0Sstevel@tonic-gate
633*0Sstevel@tonic-gateB<Pod::Parser> provides several methods to process input text. These
634*0Sstevel@tonic-gatemethods typically won't need to be overridden (and in some cases they
635*0Sstevel@tonic-gatecan't be overridden), but subclasses may want to invoke them to exploit
636*0Sstevel@tonic-gatetheir functionality.
637*0Sstevel@tonic-gate
638*0Sstevel@tonic-gate=cut
639*0Sstevel@tonic-gate
640*0Sstevel@tonic-gate##---------------------------------------------------------------------------
641*0Sstevel@tonic-gate
642*0Sstevel@tonic-gate=head1 B<parse_text()>
643*0Sstevel@tonic-gate
644*0Sstevel@tonic-gate            $ptree1 = $parser->parse_text($text, $line_num);
645*0Sstevel@tonic-gate            $ptree2 = $parser->parse_text({%opts}, $text, $line_num);
646*0Sstevel@tonic-gate            $ptree3 = $parser->parse_text(\%opts, $text, $line_num);
647*0Sstevel@tonic-gate
648*0Sstevel@tonic-gateThis method is useful if you need to perform your own interpolation
649*0Sstevel@tonic-gateof interior sequences and can't rely upon B<interpolate> to expand
650*0Sstevel@tonic-gatethem in simple bottom-up order.
651*0Sstevel@tonic-gate
652*0Sstevel@tonic-gateThe parameter C<$text> is a string or block of text to be parsed
653*0Sstevel@tonic-gatefor interior sequences; and the parameter C<$line_num> is the
654*0Sstevel@tonic-gateline number curresponding to the beginning of C<$text>.
655*0Sstevel@tonic-gate
656*0Sstevel@tonic-gateB<parse_text()> will parse the given text into a parse-tree of "nodes."
657*0Sstevel@tonic-gateand interior-sequences.  Each "node" in the parse tree is either a
658*0Sstevel@tonic-gatetext-string, or a B<Pod::InteriorSequence>.  The result returned is a
659*0Sstevel@tonic-gateparse-tree of type B<Pod::ParseTree>. Please see L<Pod::InputObjects>
660*0Sstevel@tonic-gatefor more information about B<Pod::InteriorSequence> and B<Pod::ParseTree>.
661*0Sstevel@tonic-gate
662*0Sstevel@tonic-gateIf desired, an optional hash-ref may be specified as the first argument
663*0Sstevel@tonic-gateto customize certain aspects of the parse-tree that is created and
664*0Sstevel@tonic-gatereturned. The set of recognized option keywords are:
665*0Sstevel@tonic-gate
666*0Sstevel@tonic-gate=over 3
667*0Sstevel@tonic-gate
668*0Sstevel@tonic-gate=item B<-expand_seq> =E<gt> I<code-ref>|I<method-name>
669*0Sstevel@tonic-gate
670*0Sstevel@tonic-gateNormally, the parse-tree returned by B<parse_text()> will contain an
671*0Sstevel@tonic-gateunexpanded C<Pod::InteriorSequence> object for each interior-sequence
672*0Sstevel@tonic-gateencountered. Specifying B<-expand_seq> tells B<parse_text()> to "expand"
673*0Sstevel@tonic-gateevery interior-sequence it sees by invoking the referenced function
674*0Sstevel@tonic-gate(or named method of the parser object) and using the return value as the
675*0Sstevel@tonic-gateexpanded result.
676*0Sstevel@tonic-gate
677*0Sstevel@tonic-gateIf a subroutine reference was given, it is invoked as:
678*0Sstevel@tonic-gate
679*0Sstevel@tonic-gate  &$code_ref( $parser, $sequence )
680*0Sstevel@tonic-gate
681*0Sstevel@tonic-gateand if a method-name was given, it is invoked as:
682*0Sstevel@tonic-gate
683*0Sstevel@tonic-gate  $parser->method_name( $sequence )
684*0Sstevel@tonic-gate
685*0Sstevel@tonic-gatewhere C<$parser> is a reference to the parser object, and C<$sequence>
686*0Sstevel@tonic-gateis a reference to the interior-sequence object.
687*0Sstevel@tonic-gate[I<NOTE>: If the B<interior_sequence()> method is specified, then it is
688*0Sstevel@tonic-gateinvoked according to the interface specified in L<"interior_sequence()">].
689*0Sstevel@tonic-gate
690*0Sstevel@tonic-gate=item B<-expand_text> =E<gt> I<code-ref>|I<method-name>
691*0Sstevel@tonic-gate
692*0Sstevel@tonic-gateNormally, the parse-tree returned by B<parse_text()> will contain a
693*0Sstevel@tonic-gatetext-string for each contiguous sequence of characters outside of an
694*0Sstevel@tonic-gateinterior-sequence. Specifying B<-expand_text> tells B<parse_text()> to
695*0Sstevel@tonic-gate"preprocess" every such text-string it sees by invoking the referenced
696*0Sstevel@tonic-gatefunction (or named method of the parser object) and using the return value
697*0Sstevel@tonic-gateas the preprocessed (or "expanded") result. [Note that if the result is
698*0Sstevel@tonic-gatean interior-sequence, then it will I<not> be expanded as specified by the
699*0Sstevel@tonic-gateB<-expand_seq> option; Any such recursive expansion needs to be handled by
700*0Sstevel@tonic-gatethe specified callback routine.]
701*0Sstevel@tonic-gate
702*0Sstevel@tonic-gateIf a subroutine reference was given, it is invoked as:
703*0Sstevel@tonic-gate
704*0Sstevel@tonic-gate  &$code_ref( $parser, $text, $ptree_node )
705*0Sstevel@tonic-gate
706*0Sstevel@tonic-gateand if a method-name was given, it is invoked as:
707*0Sstevel@tonic-gate
708*0Sstevel@tonic-gate  $parser->method_name( $text, $ptree_node )
709*0Sstevel@tonic-gate
710*0Sstevel@tonic-gatewhere C<$parser> is a reference to the parser object, C<$text> is the
711*0Sstevel@tonic-gatetext-string encountered, and C<$ptree_node> is a reference to the current
712*0Sstevel@tonic-gatenode in the parse-tree (usually an interior-sequence object or else the
713*0Sstevel@tonic-gatetop-level node of the parse-tree).
714*0Sstevel@tonic-gate
715*0Sstevel@tonic-gate=item B<-expand_ptree> =E<gt> I<code-ref>|I<method-name>
716*0Sstevel@tonic-gate
717*0Sstevel@tonic-gateRather than returning a C<Pod::ParseTree>, pass the parse-tree as an
718*0Sstevel@tonic-gateargument to the referenced subroutine (or named method of the parser
719*0Sstevel@tonic-gateobject) and return the result instead of the parse-tree object.
720*0Sstevel@tonic-gate
721*0Sstevel@tonic-gateIf a subroutine reference was given, it is invoked as:
722*0Sstevel@tonic-gate
723*0Sstevel@tonic-gate  &$code_ref( $parser, $ptree )
724*0Sstevel@tonic-gate
725*0Sstevel@tonic-gateand if a method-name was given, it is invoked as:
726*0Sstevel@tonic-gate
727*0Sstevel@tonic-gate  $parser->method_name( $ptree )
728*0Sstevel@tonic-gate
729*0Sstevel@tonic-gatewhere C<$parser> is a reference to the parser object, and C<$ptree>
730*0Sstevel@tonic-gateis a reference to the parse-tree object.
731*0Sstevel@tonic-gate
732*0Sstevel@tonic-gate=back
733*0Sstevel@tonic-gate
734*0Sstevel@tonic-gate=cut
735*0Sstevel@tonic-gate
736*0Sstevel@tonic-gatesub parse_text {
737*0Sstevel@tonic-gate    my $self = shift;
738*0Sstevel@tonic-gate    local $_ = '';
739*0Sstevel@tonic-gate
740*0Sstevel@tonic-gate    ## Get options and set any defaults
741*0Sstevel@tonic-gate    my %opts = (ref $_[0]) ? %{ shift() } : ();
742*0Sstevel@tonic-gate    my $expand_seq   = $opts{'-expand_seq'}   || undef;
743*0Sstevel@tonic-gate    my $expand_text  = $opts{'-expand_text'}  || undef;
744*0Sstevel@tonic-gate    my $expand_ptree = $opts{'-expand_ptree'} || undef;
745*0Sstevel@tonic-gate
746*0Sstevel@tonic-gate    my $text = shift;
747*0Sstevel@tonic-gate    my $line = shift;
748*0Sstevel@tonic-gate    my $file = $self->input_file();
749*0Sstevel@tonic-gate    my $cmd  = "";
750*0Sstevel@tonic-gate
751*0Sstevel@tonic-gate    ## Convert method calls into closures, for our convenience
752*0Sstevel@tonic-gate    my $xseq_sub   = $expand_seq;
753*0Sstevel@tonic-gate    my $xtext_sub  = $expand_text;
754*0Sstevel@tonic-gate    my $xptree_sub = $expand_ptree;
755*0Sstevel@tonic-gate    if (defined $expand_seq  and  $expand_seq eq 'interior_sequence') {
756*0Sstevel@tonic-gate        ## If 'interior_sequence' is the method to use, we have to pass
757*0Sstevel@tonic-gate        ## more than just the sequence object, we also need to pass the
758*0Sstevel@tonic-gate        ## sequence name and text.
759*0Sstevel@tonic-gate        $xseq_sub = sub {
760*0Sstevel@tonic-gate            my ($self, $iseq) = @_;
761*0Sstevel@tonic-gate            my $args = join("", $iseq->parse_tree->children);
762*0Sstevel@tonic-gate            return  $self->interior_sequence($iseq->name, $args, $iseq);
763*0Sstevel@tonic-gate        };
764*0Sstevel@tonic-gate    }
765*0Sstevel@tonic-gate    ref $xseq_sub    or  $xseq_sub   = sub { shift()->$expand_seq(@_) };
766*0Sstevel@tonic-gate    ref $xtext_sub   or  $xtext_sub  = sub { shift()->$expand_text(@_) };
767*0Sstevel@tonic-gate    ref $xptree_sub  or  $xptree_sub = sub { shift()->$expand_ptree(@_) };
768*0Sstevel@tonic-gate
769*0Sstevel@tonic-gate    ## Keep track of the "current" interior sequence, and maintain a stack
770*0Sstevel@tonic-gate    ## of "in progress" sequences.
771*0Sstevel@tonic-gate    ##
772*0Sstevel@tonic-gate    ## NOTE that we push our own "accumulator" at the very beginning of the
773*0Sstevel@tonic-gate    ## stack. It's really a parse-tree, not a sequence; but it implements
774*0Sstevel@tonic-gate    ## the methods we need so we can use it to gather-up all the sequences
775*0Sstevel@tonic-gate    ## and strings we parse. Thus, by the end of our parsing, it should be
776*0Sstevel@tonic-gate    ## the only thing left on our stack and all we have to do is return it!
777*0Sstevel@tonic-gate    ##
778*0Sstevel@tonic-gate    my $seq       = Pod::ParseTree->new();
779*0Sstevel@tonic-gate    my @seq_stack = ($seq);
780*0Sstevel@tonic-gate    my ($ldelim, $rdelim) = ('', '');
781*0Sstevel@tonic-gate
782*0Sstevel@tonic-gate    ## Iterate over all sequence starts text (NOTE: split with
783*0Sstevel@tonic-gate    ## capturing parens keeps the delimiters)
784*0Sstevel@tonic-gate    $_ = $text;
785*0Sstevel@tonic-gate    my @tokens = split /([A-Z]<(?:<+\s)?)/;
786*0Sstevel@tonic-gate    while ( @tokens ) {
787*0Sstevel@tonic-gate        $_ = shift @tokens;
788*0Sstevel@tonic-gate        ## Look for the beginning of a sequence
789*0Sstevel@tonic-gate        if ( /^([A-Z])(<(?:<+\s)?)$/ ) {
790*0Sstevel@tonic-gate            ## Push a new sequence onto the stack of those "in-progress"
791*0Sstevel@tonic-gate            my $ldelim_orig;
792*0Sstevel@tonic-gate            ($cmd, $ldelim_orig) = ($1, $2);
793*0Sstevel@tonic-gate            ($ldelim = $ldelim_orig) =~ s/\s+$//;
794*0Sstevel@tonic-gate            ($rdelim = $ldelim) =~ tr/</>/;
795*0Sstevel@tonic-gate            $seq = Pod::InteriorSequence->new(
796*0Sstevel@tonic-gate                       -name   => $cmd,
797*0Sstevel@tonic-gate                       -ldelim => $ldelim_orig,  -rdelim => $rdelim,
798*0Sstevel@tonic-gate                       -file   => $file,    -line   => $line
799*0Sstevel@tonic-gate                   );
800*0Sstevel@tonic-gate            (@seq_stack > 1)  and  $seq->nested($seq_stack[-1]);
801*0Sstevel@tonic-gate            push @seq_stack, $seq;
802*0Sstevel@tonic-gate        }
803*0Sstevel@tonic-gate        ## Look for sequence ending
804*0Sstevel@tonic-gate        elsif ( @seq_stack > 1 ) {
805*0Sstevel@tonic-gate            ## Make sure we match the right kind of closing delimiter
806*0Sstevel@tonic-gate            my ($seq_end, $post_seq) = ("", "");
807*0Sstevel@tonic-gate            if ( ($ldelim eq '<'   and  /\A(.*?)(>)/s)
808*0Sstevel@tonic-gate                 or  /\A(.*?)(\s+$rdelim)/s )
809*0Sstevel@tonic-gate            {
810*0Sstevel@tonic-gate                ## Found end-of-sequence, capture the interior and the
811*0Sstevel@tonic-gate                ## closing the delimiter, and put the rest back on the
812*0Sstevel@tonic-gate                ## token-list
813*0Sstevel@tonic-gate                $post_seq = substr($_, length($1) + length($2));
814*0Sstevel@tonic-gate                ($_, $seq_end) = ($1, $2);
815*0Sstevel@tonic-gate                (length $post_seq)  and  unshift @tokens, $post_seq;
816*0Sstevel@tonic-gate            }
817*0Sstevel@tonic-gate            if (length) {
818*0Sstevel@tonic-gate                ## In the middle of a sequence, append this text to it, and
819*0Sstevel@tonic-gate                ## dont forget to "expand" it if that's what the caller wanted
820*0Sstevel@tonic-gate                $seq->append($expand_text ? &$xtext_sub($self,$_,$seq) : $_);
821*0Sstevel@tonic-gate                $_ .= $seq_end;
822*0Sstevel@tonic-gate            }
823*0Sstevel@tonic-gate            if (length $seq_end) {
824*0Sstevel@tonic-gate                ## End of current sequence, record terminating delimiter
825*0Sstevel@tonic-gate                $seq->rdelim($seq_end);
826*0Sstevel@tonic-gate                ## Pop it off the stack of "in progress" sequences
827*0Sstevel@tonic-gate                pop @seq_stack;
828*0Sstevel@tonic-gate                ## Append result to its parent in current parse tree
829*0Sstevel@tonic-gate                $seq_stack[-1]->append($expand_seq ? &$xseq_sub($self,$seq)
830*0Sstevel@tonic-gate                                                   : $seq);
831*0Sstevel@tonic-gate                ## Remember the current cmd-name and left-delimiter
832*0Sstevel@tonic-gate                if(@seq_stack > 1) {
833*0Sstevel@tonic-gate                    $cmd = $seq_stack[-1]->name;
834*0Sstevel@tonic-gate                    $ldelim = $seq_stack[-1]->ldelim;
835*0Sstevel@tonic-gate                    $rdelim = $seq_stack[-1]->rdelim;
836*0Sstevel@tonic-gate                } else {
837*0Sstevel@tonic-gate                    $cmd = $ldelim = $rdelim = '';
838*0Sstevel@tonic-gate                }
839*0Sstevel@tonic-gate            }
840*0Sstevel@tonic-gate        }
841*0Sstevel@tonic-gate        elsif (length) {
842*0Sstevel@tonic-gate            ## In the middle of a sequence, append this text to it, and
843*0Sstevel@tonic-gate            ## dont forget to "expand" it if that's what the caller wanted
844*0Sstevel@tonic-gate            $seq->append($expand_text ? &$xtext_sub($self,$_,$seq) : $_);
845*0Sstevel@tonic-gate        }
846*0Sstevel@tonic-gate        ## Keep track of line count
847*0Sstevel@tonic-gate        $line += tr/\n//;
848*0Sstevel@tonic-gate        ## Remember the "current" sequence
849*0Sstevel@tonic-gate        $seq = $seq_stack[-1];
850*0Sstevel@tonic-gate    }
851*0Sstevel@tonic-gate
852*0Sstevel@tonic-gate    ## Handle unterminated sequences
853*0Sstevel@tonic-gate    my $errorsub = (@seq_stack > 1) ? $self->errorsub() : undef;
854*0Sstevel@tonic-gate    while (@seq_stack > 1) {
855*0Sstevel@tonic-gate       ($cmd, $file, $line) = ($seq->name, $seq->file_line);
856*0Sstevel@tonic-gate       $ldelim  = $seq->ldelim;
857*0Sstevel@tonic-gate       ($rdelim = $ldelim) =~ tr/</>/;
858*0Sstevel@tonic-gate       $rdelim  =~ s/^(\S+)(\s*)$/$2$1/;
859*0Sstevel@tonic-gate       pop @seq_stack;
860*0Sstevel@tonic-gate       my $errmsg = "*** ERROR: unterminated ${cmd}${ldelim}...${rdelim}".
861*0Sstevel@tonic-gate                    " at line $line in file $file\n";
862*0Sstevel@tonic-gate       (ref $errorsub) and &{$errorsub}($errmsg)
863*0Sstevel@tonic-gate           or (defined $errorsub) and $self->$errorsub($errmsg)
864*0Sstevel@tonic-gate               or  warn($errmsg);
865*0Sstevel@tonic-gate       $seq_stack[-1]->append($expand_seq ? &$xseq_sub($self,$seq) : $seq);
866*0Sstevel@tonic-gate       $seq = $seq_stack[-1];
867*0Sstevel@tonic-gate    }
868*0Sstevel@tonic-gate
869*0Sstevel@tonic-gate    ## Return the resulting parse-tree
870*0Sstevel@tonic-gate    my $ptree = (pop @seq_stack)->parse_tree;
871*0Sstevel@tonic-gate    return  $expand_ptree ? &$xptree_sub($self, $ptree) : $ptree;
872*0Sstevel@tonic-gate}
873*0Sstevel@tonic-gate
874*0Sstevel@tonic-gate##---------------------------------------------------------------------------
875*0Sstevel@tonic-gate
876*0Sstevel@tonic-gate=head1 B<interpolate()>
877*0Sstevel@tonic-gate
878*0Sstevel@tonic-gate            $textblock = $parser->interpolate($text, $line_num);
879*0Sstevel@tonic-gate
880*0Sstevel@tonic-gateThis method translates all text (including any embedded interior sequences)
881*0Sstevel@tonic-gatein the given text string C<$text> and returns the interpolated result. The
882*0Sstevel@tonic-gateparameter C<$line_num> is the line number corresponding to the beginning
883*0Sstevel@tonic-gateof C<$text>.
884*0Sstevel@tonic-gate
885*0Sstevel@tonic-gateB<interpolate()> merely invokes a private method to recursively expand
886*0Sstevel@tonic-gatenested interior sequences in bottom-up order (innermost sequences are
887*0Sstevel@tonic-gateexpanded first). If there is a need to expand nested sequences in
888*0Sstevel@tonic-gatesome alternate order, use B<parse_text> instead.
889*0Sstevel@tonic-gate
890*0Sstevel@tonic-gate=cut
891*0Sstevel@tonic-gate
892*0Sstevel@tonic-gatesub interpolate {
893*0Sstevel@tonic-gate    my($self, $text, $line_num) = @_;
894*0Sstevel@tonic-gate    my %parse_opts = ( -expand_seq => 'interior_sequence' );
895*0Sstevel@tonic-gate    my $ptree = $self->parse_text( \%parse_opts, $text, $line_num );
896*0Sstevel@tonic-gate    return  join "", $ptree->children();
897*0Sstevel@tonic-gate}
898*0Sstevel@tonic-gate
899*0Sstevel@tonic-gate##---------------------------------------------------------------------------
900*0Sstevel@tonic-gate
901*0Sstevel@tonic-gate=begin __PRIVATE__
902*0Sstevel@tonic-gate
903*0Sstevel@tonic-gate=head1 B<parse_paragraph()>
904*0Sstevel@tonic-gate
905*0Sstevel@tonic-gate            $parser->parse_paragraph($text, $line_num);
906*0Sstevel@tonic-gate
907*0Sstevel@tonic-gateThis method takes the text of a POD paragraph to be processed, along
908*0Sstevel@tonic-gatewith its corresponding line number, and invokes the appropriate method
909*0Sstevel@tonic-gate(one of B<command()>, B<verbatim()>, or B<textblock()>).
910*0Sstevel@tonic-gate
911*0Sstevel@tonic-gateFor performance reasons, this method is invoked directly without any
912*0Sstevel@tonic-gatedynamic lookup; Hence subclasses may I<not> override it!
913*0Sstevel@tonic-gate
914*0Sstevel@tonic-gate=end __PRIVATE__
915*0Sstevel@tonic-gate
916*0Sstevel@tonic-gate=cut
917*0Sstevel@tonic-gate
918*0Sstevel@tonic-gatesub parse_paragraph {
919*0Sstevel@tonic-gate    my ($self, $text, $line_num) = @_;
920*0Sstevel@tonic-gate    local *myData = $self;  ## alias to avoid deref-ing overhead
921*0Sstevel@tonic-gate    local *myOpts = ($myData{_PARSEOPTS} ||= {});  ## get parse-options
922*0Sstevel@tonic-gate    local $_;
923*0Sstevel@tonic-gate
924*0Sstevel@tonic-gate    ## See if we want to preprocess nonPOD paragraphs as well as POD ones.
925*0Sstevel@tonic-gate    my $wantNonPods = $myOpts{'-want_nonPODs'};
926*0Sstevel@tonic-gate
927*0Sstevel@tonic-gate    ## Update cutting status
928*0Sstevel@tonic-gate    $myData{_CUTTING} = 0 if $text =~ /^={1,2}\S/;
929*0Sstevel@tonic-gate
930*0Sstevel@tonic-gate    ## Perform any desired preprocessing if we wanted it this early
931*0Sstevel@tonic-gate    $wantNonPods  and  $text = $self->preprocess_paragraph($text, $line_num);
932*0Sstevel@tonic-gate
933*0Sstevel@tonic-gate    ## Ignore up until next POD directive if we are cutting
934*0Sstevel@tonic-gate    return if $myData{_CUTTING};
935*0Sstevel@tonic-gate
936*0Sstevel@tonic-gate    ## Now we know this is block of text in a POD section!
937*0Sstevel@tonic-gate
938*0Sstevel@tonic-gate    ##-----------------------------------------------------------------
939*0Sstevel@tonic-gate    ## This is a hook (hack ;-) for Pod::Select to do its thing without
940*0Sstevel@tonic-gate    ## having to override methods, but also without Pod::Parser assuming
941*0Sstevel@tonic-gate    ## $self is an instance of Pod::Select (if the _SELECTED_SECTIONS
942*0Sstevel@tonic-gate    ## field exists then we assume there is an is_selected() method for
943*0Sstevel@tonic-gate    ## us to invoke (calling $self->can('is_selected') could verify this
944*0Sstevel@tonic-gate    ## but that is more overhead than I want to incur)
945*0Sstevel@tonic-gate    ##-----------------------------------------------------------------
946*0Sstevel@tonic-gate
947*0Sstevel@tonic-gate    ## Ignore this block if it isnt in one of the selected sections
948*0Sstevel@tonic-gate    if (exists $myData{_SELECTED_SECTIONS}) {
949*0Sstevel@tonic-gate        $self->is_selected($text)  or  return ($myData{_CUTTING} = 1);
950*0Sstevel@tonic-gate    }
951*0Sstevel@tonic-gate
952*0Sstevel@tonic-gate    ## If we havent already, perform any desired preprocessing and
953*0Sstevel@tonic-gate    ## then re-check the "cutting" state
954*0Sstevel@tonic-gate    unless ($wantNonPods) {
955*0Sstevel@tonic-gate       $text = $self->preprocess_paragraph($text, $line_num);
956*0Sstevel@tonic-gate       return 1  unless ((defined $text) and (length $text));
957*0Sstevel@tonic-gate       return 1  if ($myData{_CUTTING});
958*0Sstevel@tonic-gate    }
959*0Sstevel@tonic-gate
960*0Sstevel@tonic-gate    ## Look for one of the three types of paragraphs
961*0Sstevel@tonic-gate    my ($pfx, $cmd, $arg, $sep) = ('', '', '', '');
962*0Sstevel@tonic-gate    my $pod_para = undef;
963*0Sstevel@tonic-gate    if ($text =~ /^(={1,2})(?=\S)/) {
964*0Sstevel@tonic-gate        ## Looks like a command paragraph. Capture the command prefix used
965*0Sstevel@tonic-gate        ## ("=" or "=="), as well as the command-name, its paragraph text,
966*0Sstevel@tonic-gate        ## and whatever sequence of characters was used to separate them
967*0Sstevel@tonic-gate        $pfx = $1;
968*0Sstevel@tonic-gate        $_ = substr($text, length $pfx);
969*0Sstevel@tonic-gate        ($cmd, $sep, $text) = split /(\s+)/, $_, 2;
970*0Sstevel@tonic-gate        ## If this is a "cut" directive then we dont need to do anything
971*0Sstevel@tonic-gate        ## except return to "cutting" mode.
972*0Sstevel@tonic-gate        if ($cmd eq 'cut') {
973*0Sstevel@tonic-gate           $myData{_CUTTING} = 1;
974*0Sstevel@tonic-gate           return  unless $myOpts{'-process_cut_cmd'};
975*0Sstevel@tonic-gate        }
976*0Sstevel@tonic-gate    }
977*0Sstevel@tonic-gate    ## Save the attributes indicating how the command was specified.
978*0Sstevel@tonic-gate    $pod_para = new Pod::Paragraph(
979*0Sstevel@tonic-gate          -name      => $cmd,
980*0Sstevel@tonic-gate          -text      => $text,
981*0Sstevel@tonic-gate          -prefix    => $pfx,
982*0Sstevel@tonic-gate          -separator => $sep,
983*0Sstevel@tonic-gate          -file      => $myData{_INFILE},
984*0Sstevel@tonic-gate          -line      => $line_num
985*0Sstevel@tonic-gate    );
986*0Sstevel@tonic-gate    # ## Invoke appropriate callbacks
987*0Sstevel@tonic-gate    # if (exists $myData{_CALLBACKS}) {
988*0Sstevel@tonic-gate    #    ## Look through the callback list, invoke callbacks,
989*0Sstevel@tonic-gate    #    ## then see if we need to do the default actions
990*0Sstevel@tonic-gate    #    ## (invoke_callbacks will return true if we do).
991*0Sstevel@tonic-gate    #    return  1  unless $self->invoke_callbacks($cmd, $text, $line_num, $pod_para);
992*0Sstevel@tonic-gate    # }
993*0Sstevel@tonic-gate    if (length $cmd) {
994*0Sstevel@tonic-gate        ## A command paragraph
995*0Sstevel@tonic-gate        $self->command($cmd, $text, $line_num, $pod_para);
996*0Sstevel@tonic-gate    }
997*0Sstevel@tonic-gate    elsif ($text =~ /^\s+/) {
998*0Sstevel@tonic-gate        ## Indented text - must be a verbatim paragraph
999*0Sstevel@tonic-gate        $self->verbatim($text, $line_num, $pod_para);
1000*0Sstevel@tonic-gate    }
1001*0Sstevel@tonic-gate    else {
1002*0Sstevel@tonic-gate        ## Looks like an ordinary block of text
1003*0Sstevel@tonic-gate        $self->textblock($text, $line_num, $pod_para);
1004*0Sstevel@tonic-gate    }
1005*0Sstevel@tonic-gate    return  1;
1006*0Sstevel@tonic-gate}
1007*0Sstevel@tonic-gate
1008*0Sstevel@tonic-gate##---------------------------------------------------------------------------
1009*0Sstevel@tonic-gate
1010*0Sstevel@tonic-gate=head1 B<parse_from_filehandle()>
1011*0Sstevel@tonic-gate
1012*0Sstevel@tonic-gate            $parser->parse_from_filehandle($in_fh,$out_fh);
1013*0Sstevel@tonic-gate
1014*0Sstevel@tonic-gateThis method takes an input filehandle (which is assumed to already be
1015*0Sstevel@tonic-gateopened for reading) and reads the entire input stream looking for blocks
1016*0Sstevel@tonic-gate(paragraphs) of POD documentation to be processed. If no first argument
1017*0Sstevel@tonic-gateis given the default input filehandle C<STDIN> is used.
1018*0Sstevel@tonic-gate
1019*0Sstevel@tonic-gateThe C<$in_fh> parameter may be any object that provides a B<getline()>
1020*0Sstevel@tonic-gatemethod to retrieve a single line of input text (hence, an appropriate
1021*0Sstevel@tonic-gatewrapper object could be used to parse PODs from a single string or an
1022*0Sstevel@tonic-gatearray of strings).
1023*0Sstevel@tonic-gate
1024*0Sstevel@tonic-gateUsing C<$in_fh-E<gt>getline()>, input is read line-by-line and assembled
1025*0Sstevel@tonic-gateinto paragraphs or "blocks" (which are separated by lines containing
1026*0Sstevel@tonic-gatenothing but whitespace). For each block of POD documentation
1027*0Sstevel@tonic-gateencountered it will invoke a method to parse the given paragraph.
1028*0Sstevel@tonic-gate
1029*0Sstevel@tonic-gateIf a second argument is given then it should correspond to a filehandle where
1030*0Sstevel@tonic-gateoutput should be sent (otherwise the default output filehandle is
1031*0Sstevel@tonic-gateC<STDOUT> if no output filehandle is currently in use).
1032*0Sstevel@tonic-gate
1033*0Sstevel@tonic-gateB<NOTE:> For performance reasons, this method caches the input stream at
1034*0Sstevel@tonic-gatethe top of the stack in a local variable. Any attempts by clients to
1035*0Sstevel@tonic-gatechange the stack contents during processing when in the midst executing
1036*0Sstevel@tonic-gateof this method I<will not affect> the input stream used by the current
1037*0Sstevel@tonic-gateinvocation of this method.
1038*0Sstevel@tonic-gate
1039*0Sstevel@tonic-gateThis method does I<not> usually need to be overridden by subclasses.
1040*0Sstevel@tonic-gate
1041*0Sstevel@tonic-gate=cut
1042*0Sstevel@tonic-gate
1043*0Sstevel@tonic-gatesub parse_from_filehandle {
1044*0Sstevel@tonic-gate    my $self = shift;
1045*0Sstevel@tonic-gate    my %opts = (ref $_[0] eq 'HASH') ? %{ shift() } : ();
1046*0Sstevel@tonic-gate    my ($in_fh, $out_fh) = @_;
1047*0Sstevel@tonic-gate    $in_fh = \*STDIN  unless ($in_fh);
1048*0Sstevel@tonic-gate    local *myData = $self;  ## alias to avoid deref-ing overhead
1049*0Sstevel@tonic-gate    local *myOpts = ($myData{_PARSEOPTS} ||= {});  ## get parse-options
1050*0Sstevel@tonic-gate    local $_;
1051*0Sstevel@tonic-gate
1052*0Sstevel@tonic-gate    ## Put this stream at the top of the stack and do beginning-of-input
1053*0Sstevel@tonic-gate    ## processing. NOTE that $in_fh might be reset during this process.
1054*0Sstevel@tonic-gate    my $topstream = $self->_push_input_stream($in_fh, $out_fh);
1055*0Sstevel@tonic-gate    (exists $opts{-cutting})  and  $self->cutting( $opts{-cutting} );
1056*0Sstevel@tonic-gate
1057*0Sstevel@tonic-gate    ## Initialize line/paragraph
1058*0Sstevel@tonic-gate    my ($textline, $paragraph) = ('', '');
1059*0Sstevel@tonic-gate    my ($nlines, $plines) = (0, 0);
1060*0Sstevel@tonic-gate
1061*0Sstevel@tonic-gate    ## Use <$fh> instead of $fh->getline where possible (for speed)
1062*0Sstevel@tonic-gate    $_ = ref $in_fh;
1063*0Sstevel@tonic-gate    my $tied_fh = (/^(?:GLOB|FileHandle|IO::\w+)$/  or  tied $in_fh);
1064*0Sstevel@tonic-gate
1065*0Sstevel@tonic-gate    ## Read paragraphs line-by-line
1066*0Sstevel@tonic-gate    while (defined ($textline = $tied_fh ? <$in_fh> : $in_fh->getline)) {
1067*0Sstevel@tonic-gate        $textline = $self->preprocess_line($textline, ++$nlines);
1068*0Sstevel@tonic-gate        next  unless ((defined $textline)  &&  (length $textline));
1069*0Sstevel@tonic-gate        $_ = $paragraph;  ## save previous contents
1070*0Sstevel@tonic-gate
1071*0Sstevel@tonic-gate        if ((! length $paragraph) && ($textline =~ /^==/)) {
1072*0Sstevel@tonic-gate            ## '==' denotes a one-line command paragraph
1073*0Sstevel@tonic-gate            $paragraph = $textline;
1074*0Sstevel@tonic-gate            $plines    = 1;
1075*0Sstevel@tonic-gate            $textline  = '';
1076*0Sstevel@tonic-gate        } else {
1077*0Sstevel@tonic-gate            ## Append this line to the current paragraph
1078*0Sstevel@tonic-gate            $paragraph .= $textline;
1079*0Sstevel@tonic-gate            ++$plines;
1080*0Sstevel@tonic-gate        }
1081*0Sstevel@tonic-gate
1082*0Sstevel@tonic-gate        ## See if this line is blank and ends the current paragraph.
1083*0Sstevel@tonic-gate        ## If it isnt, then keep iterating until it is.
1084*0Sstevel@tonic-gate        next unless (($textline =~ /^([^\S\r\n]*)[\r\n]*$/)
1085*0Sstevel@tonic-gate                                     && (length $paragraph));
1086*0Sstevel@tonic-gate
1087*0Sstevel@tonic-gate        ## Issue a warning about any non-empty blank lines
1088*0Sstevel@tonic-gate        if (length($1) > 0 and $myOpts{'-warnings'} and ! $myData{_CUTTING}) {
1089*0Sstevel@tonic-gate            my $errorsub = $self->errorsub();
1090*0Sstevel@tonic-gate            my $file = $self->input_file();
1091*0Sstevel@tonic-gate            my $errmsg = "*** WARNING: line containing nothing but whitespace".
1092*0Sstevel@tonic-gate                         " in paragraph at line $nlines in file $file\n";
1093*0Sstevel@tonic-gate            (ref $errorsub) and &{$errorsub}($errmsg)
1094*0Sstevel@tonic-gate                or (defined $errorsub) and $self->$errorsub($errmsg)
1095*0Sstevel@tonic-gate                    or  warn($errmsg);
1096*0Sstevel@tonic-gate        }
1097*0Sstevel@tonic-gate
1098*0Sstevel@tonic-gate        ## Now process the paragraph
1099*0Sstevel@tonic-gate        parse_paragraph($self, $paragraph, ($nlines - $plines) + 1);
1100*0Sstevel@tonic-gate        $paragraph = '';
1101*0Sstevel@tonic-gate        $plines = 0;
1102*0Sstevel@tonic-gate    }
1103*0Sstevel@tonic-gate    ## Dont forget about the last paragraph in the file
1104*0Sstevel@tonic-gate    if (length $paragraph) {
1105*0Sstevel@tonic-gate       parse_paragraph($self, $paragraph, ($nlines - $plines) + 1)
1106*0Sstevel@tonic-gate    }
1107*0Sstevel@tonic-gate
1108*0Sstevel@tonic-gate    ## Now pop the input stream off the top of the input stack.
1109*0Sstevel@tonic-gate    $self->_pop_input_stream();
1110*0Sstevel@tonic-gate}
1111*0Sstevel@tonic-gate
1112*0Sstevel@tonic-gate##---------------------------------------------------------------------------
1113*0Sstevel@tonic-gate
1114*0Sstevel@tonic-gate=head1 B<parse_from_file()>
1115*0Sstevel@tonic-gate
1116*0Sstevel@tonic-gate            $parser->parse_from_file($filename,$outfile);
1117*0Sstevel@tonic-gate
1118*0Sstevel@tonic-gateThis method takes a filename and does the following:
1119*0Sstevel@tonic-gate
1120*0Sstevel@tonic-gate=over 2
1121*0Sstevel@tonic-gate
1122*0Sstevel@tonic-gate=item *
1123*0Sstevel@tonic-gate
1124*0Sstevel@tonic-gateopens the input and output files for reading
1125*0Sstevel@tonic-gate(creating the appropriate filehandles)
1126*0Sstevel@tonic-gate
1127*0Sstevel@tonic-gate=item *
1128*0Sstevel@tonic-gate
1129*0Sstevel@tonic-gateinvokes the B<parse_from_filehandle()> method passing it the
1130*0Sstevel@tonic-gatecorresponding input and output filehandles.
1131*0Sstevel@tonic-gate
1132*0Sstevel@tonic-gate=item *
1133*0Sstevel@tonic-gate
1134*0Sstevel@tonic-gatecloses the input and output files.
1135*0Sstevel@tonic-gate
1136*0Sstevel@tonic-gate=back
1137*0Sstevel@tonic-gate
1138*0Sstevel@tonic-gateIf the special input filename "-" or "<&STDIN" is given then the STDIN
1139*0Sstevel@tonic-gatefilehandle is used for input (and no open or close is performed). If no
1140*0Sstevel@tonic-gateinput filename is specified then "-" is implied.
1141*0Sstevel@tonic-gate
1142*0Sstevel@tonic-gateIf a second argument is given then it should be the name of the desired
1143*0Sstevel@tonic-gateoutput file. If the special output filename "-" or ">&STDOUT" is given
1144*0Sstevel@tonic-gatethen the STDOUT filehandle is used for output (and no open or close is
1145*0Sstevel@tonic-gateperformed). If the special output filename ">&STDERR" is given then the
1146*0Sstevel@tonic-gateSTDERR filehandle is used for output (and no open or close is
1147*0Sstevel@tonic-gateperformed). If no output filehandle is currently in use and no output
1148*0Sstevel@tonic-gatefilename is specified, then "-" is implied.
1149*0Sstevel@tonic-gate
1150*0Sstevel@tonic-gateThis method does I<not> usually need to be overridden by subclasses.
1151*0Sstevel@tonic-gate
1152*0Sstevel@tonic-gate=cut
1153*0Sstevel@tonic-gate
1154*0Sstevel@tonic-gatesub parse_from_file {
1155*0Sstevel@tonic-gate    my $self = shift;
1156*0Sstevel@tonic-gate    my %opts = (ref $_[0] eq 'HASH') ? %{ shift() } : ();
1157*0Sstevel@tonic-gate    my ($infile, $outfile) = @_;
1158*0Sstevel@tonic-gate    my ($in_fh,  $out_fh) = (gensym, gensym)  if ($] < 5.6);
1159*0Sstevel@tonic-gate    my ($close_input, $close_output) = (0, 0);
1160*0Sstevel@tonic-gate    local *myData = $self;
1161*0Sstevel@tonic-gate    local $_;
1162*0Sstevel@tonic-gate
1163*0Sstevel@tonic-gate    ## Is $infile a filename or a (possibly implied) filehandle
1164*0Sstevel@tonic-gate    $infile  = '-'  unless ((defined $infile)  && (length $infile));
1165*0Sstevel@tonic-gate    if (($infile  eq '-') || ($infile =~ /^<&(STDIN|0)$/i)) {
1166*0Sstevel@tonic-gate        ## Not a filename, just a string implying STDIN
1167*0Sstevel@tonic-gate        $myData{_INFILE} = "<standard input>";
1168*0Sstevel@tonic-gate        $in_fh = \*STDIN;
1169*0Sstevel@tonic-gate    }
1170*0Sstevel@tonic-gate    elsif (ref $infile) {
1171*0Sstevel@tonic-gate        ## Must be a filehandle-ref (or else assume its a ref to an object
1172*0Sstevel@tonic-gate        ## that supports the common IO read operations).
1173*0Sstevel@tonic-gate        $myData{_INFILE} = ${$infile};
1174*0Sstevel@tonic-gate        $in_fh = $infile;
1175*0Sstevel@tonic-gate    }
1176*0Sstevel@tonic-gate    else {
1177*0Sstevel@tonic-gate        ## We have a filename, open it for reading
1178*0Sstevel@tonic-gate        $myData{_INFILE} = $infile;
1179*0Sstevel@tonic-gate        open($in_fh, "< $infile")  or
1180*0Sstevel@tonic-gate             croak "Can't open $infile for reading: $!\n";
1181*0Sstevel@tonic-gate        $close_input = 1;
1182*0Sstevel@tonic-gate    }
1183*0Sstevel@tonic-gate
1184*0Sstevel@tonic-gate    ## NOTE: we need to be *very* careful when "defaulting" the output
1185*0Sstevel@tonic-gate    ## file. We only want to use a default if this is the beginning of
1186*0Sstevel@tonic-gate    ## the entire document (but *not* if this is an included file). We
1187*0Sstevel@tonic-gate    ## determine this by seeing if the input stream stack has been set-up
1188*0Sstevel@tonic-gate    ## already
1189*0Sstevel@tonic-gate    ##
1190*0Sstevel@tonic-gate    unless ((defined $outfile) && (length $outfile)) {
1191*0Sstevel@tonic-gate        (defined $myData{_TOP_STREAM}) && ($out_fh  = $myData{_OUTPUT})
1192*0Sstevel@tonic-gate                                       || ($outfile = '-');
1193*0Sstevel@tonic-gate    }
1194*0Sstevel@tonic-gate    ## Is $outfile a filename or a (possibly implied) filehandle
1195*0Sstevel@tonic-gate    if ((defined $outfile) && (length $outfile)) {
1196*0Sstevel@tonic-gate        if (($outfile  eq '-') || ($outfile =~ /^>&?(?:STDOUT|1)$/i)) {
1197*0Sstevel@tonic-gate            ## Not a filename, just a string implying STDOUT
1198*0Sstevel@tonic-gate            $myData{_OUTFILE} = "<standard output>";
1199*0Sstevel@tonic-gate            $out_fh  = \*STDOUT;
1200*0Sstevel@tonic-gate        }
1201*0Sstevel@tonic-gate        elsif ($outfile =~ /^>&(STDERR|2)$/i) {
1202*0Sstevel@tonic-gate            ## Not a filename, just a string implying STDERR
1203*0Sstevel@tonic-gate            $myData{_OUTFILE} = "<standard error>";
1204*0Sstevel@tonic-gate            $out_fh  = \*STDERR;
1205*0Sstevel@tonic-gate        }
1206*0Sstevel@tonic-gate        elsif (ref $outfile) {
1207*0Sstevel@tonic-gate            ## Must be a filehandle-ref (or else assume its a ref to an
1208*0Sstevel@tonic-gate            ## object that supports the common IO write operations).
1209*0Sstevel@tonic-gate            $myData{_OUTFILE} = ${$outfile};
1210*0Sstevel@tonic-gate            $out_fh = $outfile;
1211*0Sstevel@tonic-gate        }
1212*0Sstevel@tonic-gate        else {
1213*0Sstevel@tonic-gate            ## We have a filename, open it for writing
1214*0Sstevel@tonic-gate            $myData{_OUTFILE} = $outfile;
1215*0Sstevel@tonic-gate            (-d $outfile) and croak "$outfile is a directory, not POD input!\n";
1216*0Sstevel@tonic-gate            open($out_fh, "> $outfile")  or
1217*0Sstevel@tonic-gate                 croak "Can't open $outfile for writing: $!\n";
1218*0Sstevel@tonic-gate            $close_output = 1;
1219*0Sstevel@tonic-gate        }
1220*0Sstevel@tonic-gate    }
1221*0Sstevel@tonic-gate
1222*0Sstevel@tonic-gate    ## Whew! That was a lot of work to set up reasonably/robust behavior
1223*0Sstevel@tonic-gate    ## in the case of a non-filename for reading and writing. Now we just
1224*0Sstevel@tonic-gate    ## have to parse the input and close the handles when we're finished.
1225*0Sstevel@tonic-gate    $self->parse_from_filehandle(\%opts, $in_fh, $out_fh);
1226*0Sstevel@tonic-gate
1227*0Sstevel@tonic-gate    $close_input  and
1228*0Sstevel@tonic-gate        close($in_fh) || croak "Can't close $infile after reading: $!\n";
1229*0Sstevel@tonic-gate    $close_output  and
1230*0Sstevel@tonic-gate        close($out_fh) || croak "Can't close $outfile after writing: $!\n";
1231*0Sstevel@tonic-gate}
1232*0Sstevel@tonic-gate
1233*0Sstevel@tonic-gate#############################################################################
1234*0Sstevel@tonic-gate
1235*0Sstevel@tonic-gate=head1 ACCESSOR METHODS
1236*0Sstevel@tonic-gate
1237*0Sstevel@tonic-gateClients of B<Pod::Parser> should use the following methods to access
1238*0Sstevel@tonic-gateinstance data fields:
1239*0Sstevel@tonic-gate
1240*0Sstevel@tonic-gate=cut
1241*0Sstevel@tonic-gate
1242*0Sstevel@tonic-gate##---------------------------------------------------------------------------
1243*0Sstevel@tonic-gate
1244*0Sstevel@tonic-gate=head1 B<errorsub()>
1245*0Sstevel@tonic-gate
1246*0Sstevel@tonic-gate            $parser->errorsub("method_name");
1247*0Sstevel@tonic-gate            $parser->errorsub(\&warn_user);
1248*0Sstevel@tonic-gate            $parser->errorsub(sub { print STDERR, @_ });
1249*0Sstevel@tonic-gate
1250*0Sstevel@tonic-gateSpecifies the method or subroutine to use when printing error messages
1251*0Sstevel@tonic-gateabout POD syntax. The supplied method/subroutine I<must> return TRUE upon
1252*0Sstevel@tonic-gatesuccessful printing of the message. If C<undef> is given, then the B<warn>
1253*0Sstevel@tonic-gatebuiltin is used to issue error messages (this is the default behavior).
1254*0Sstevel@tonic-gate
1255*0Sstevel@tonic-gate            my $errorsub = $parser->errorsub()
1256*0Sstevel@tonic-gate            my $errmsg = "This is an error message!\n"
1257*0Sstevel@tonic-gate            (ref $errorsub) and &{$errorsub}($errmsg)
1258*0Sstevel@tonic-gate                or (defined $errorsub) and $parser->$errorsub($errmsg)
1259*0Sstevel@tonic-gate                    or  warn($errmsg);
1260*0Sstevel@tonic-gate
1261*0Sstevel@tonic-gateReturns a method name, or else a reference to the user-supplied subroutine
1262*0Sstevel@tonic-gateused to print error messages. Returns C<undef> if the B<warn> builtin
1263*0Sstevel@tonic-gateis used to issue error messages (this is the default behavior).
1264*0Sstevel@tonic-gate
1265*0Sstevel@tonic-gate=cut
1266*0Sstevel@tonic-gate
1267*0Sstevel@tonic-gatesub errorsub {
1268*0Sstevel@tonic-gate   return (@_ > 1) ? ($_[0]->{_ERRORSUB} = $_[1]) : $_[0]->{_ERRORSUB};
1269*0Sstevel@tonic-gate}
1270*0Sstevel@tonic-gate
1271*0Sstevel@tonic-gate##---------------------------------------------------------------------------
1272*0Sstevel@tonic-gate
1273*0Sstevel@tonic-gate=head1 B<cutting()>
1274*0Sstevel@tonic-gate
1275*0Sstevel@tonic-gate            $boolean = $parser->cutting();
1276*0Sstevel@tonic-gate
1277*0Sstevel@tonic-gateReturns the current C<cutting> state: a boolean-valued scalar which
1278*0Sstevel@tonic-gateevaluates to true if text from the input file is currently being "cut"
1279*0Sstevel@tonic-gate(meaning it is I<not> considered part of the POD document).
1280*0Sstevel@tonic-gate
1281*0Sstevel@tonic-gate            $parser->cutting($boolean);
1282*0Sstevel@tonic-gate
1283*0Sstevel@tonic-gateSets the current C<cutting> state to the given value and returns the
1284*0Sstevel@tonic-gateresult.
1285*0Sstevel@tonic-gate
1286*0Sstevel@tonic-gate=cut
1287*0Sstevel@tonic-gate
1288*0Sstevel@tonic-gatesub cutting {
1289*0Sstevel@tonic-gate   return (@_ > 1) ? ($_[0]->{_CUTTING} = $_[1]) : $_[0]->{_CUTTING};
1290*0Sstevel@tonic-gate}
1291*0Sstevel@tonic-gate
1292*0Sstevel@tonic-gate##---------------------------------------------------------------------------
1293*0Sstevel@tonic-gate
1294*0Sstevel@tonic-gate##---------------------------------------------------------------------------
1295*0Sstevel@tonic-gate
1296*0Sstevel@tonic-gate=head1 B<parseopts()>
1297*0Sstevel@tonic-gate
1298*0Sstevel@tonic-gateWhen invoked with no additional arguments, B<parseopts> returns a hashtable
1299*0Sstevel@tonic-gateof all the current parsing options.
1300*0Sstevel@tonic-gate
1301*0Sstevel@tonic-gate            ## See if we are parsing non-POD sections as well as POD ones
1302*0Sstevel@tonic-gate            my %opts = $parser->parseopts();
1303*0Sstevel@tonic-gate            $opts{'-want_nonPODs}' and print "-want_nonPODs\n";
1304*0Sstevel@tonic-gate
1305*0Sstevel@tonic-gateWhen invoked using a single string, B<parseopts> treats the string as the
1306*0Sstevel@tonic-gatename of a parse-option and returns its corresponding value if it exists
1307*0Sstevel@tonic-gate(returns C<undef> if it doesn't).
1308*0Sstevel@tonic-gate
1309*0Sstevel@tonic-gate            ## Did we ask to see '=cut' paragraphs?
1310*0Sstevel@tonic-gate            my $want_cut = $parser->parseopts('-process_cut_cmd');
1311*0Sstevel@tonic-gate            $want_cut and print "-process_cut_cmd\n";
1312*0Sstevel@tonic-gate
1313*0Sstevel@tonic-gateWhen invoked with multiple arguments, B<parseopts> treats them as
1314*0Sstevel@tonic-gatekey/value pairs and the specified parse-option names are set to the
1315*0Sstevel@tonic-gategiven values. Any unspecified parse-options are unaffected.
1316*0Sstevel@tonic-gate
1317*0Sstevel@tonic-gate            ## Set them back to the default
1318*0Sstevel@tonic-gate            $parser->parseopts(-warnings => 0);
1319*0Sstevel@tonic-gate
1320*0Sstevel@tonic-gateWhen passed a single hash-ref, B<parseopts> uses that hash to completely
1321*0Sstevel@tonic-gatereset the existing parse-options, all previous parse-option values
1322*0Sstevel@tonic-gateare lost.
1323*0Sstevel@tonic-gate
1324*0Sstevel@tonic-gate            ## Reset all options to default
1325*0Sstevel@tonic-gate            $parser->parseopts( { } );
1326*0Sstevel@tonic-gate
1327*0Sstevel@tonic-gateSee L<"PARSING OPTIONS"> for more information on the name and meaning of each
1328*0Sstevel@tonic-gateparse-option currently recognized.
1329*0Sstevel@tonic-gate
1330*0Sstevel@tonic-gate=cut
1331*0Sstevel@tonic-gate
1332*0Sstevel@tonic-gatesub parseopts {
1333*0Sstevel@tonic-gate   local *myData = shift;
1334*0Sstevel@tonic-gate   local *myOpts = ($myData{_PARSEOPTS} ||= {});
1335*0Sstevel@tonic-gate   return %myOpts  if (@_ == 0);
1336*0Sstevel@tonic-gate   if (@_ == 1) {
1337*0Sstevel@tonic-gate      local $_ = shift;
1338*0Sstevel@tonic-gate      return  ref($_)  ?  $myData{_PARSEOPTS} = $_  :  $myOpts{$_};
1339*0Sstevel@tonic-gate   }
1340*0Sstevel@tonic-gate   my @newOpts = (%myOpts, @_);
1341*0Sstevel@tonic-gate   $myData{_PARSEOPTS} = { @newOpts };
1342*0Sstevel@tonic-gate}
1343*0Sstevel@tonic-gate
1344*0Sstevel@tonic-gate##---------------------------------------------------------------------------
1345*0Sstevel@tonic-gate
1346*0Sstevel@tonic-gate=head1 B<output_file()>
1347*0Sstevel@tonic-gate
1348*0Sstevel@tonic-gate            $fname = $parser->output_file();
1349*0Sstevel@tonic-gate
1350*0Sstevel@tonic-gateReturns the name of the output file being written.
1351*0Sstevel@tonic-gate
1352*0Sstevel@tonic-gate=cut
1353*0Sstevel@tonic-gate
1354*0Sstevel@tonic-gatesub output_file {
1355*0Sstevel@tonic-gate   return $_[0]->{_OUTFILE};
1356*0Sstevel@tonic-gate}
1357*0Sstevel@tonic-gate
1358*0Sstevel@tonic-gate##---------------------------------------------------------------------------
1359*0Sstevel@tonic-gate
1360*0Sstevel@tonic-gate=head1 B<output_handle()>
1361*0Sstevel@tonic-gate
1362*0Sstevel@tonic-gate            $fhandle = $parser->output_handle();
1363*0Sstevel@tonic-gate
1364*0Sstevel@tonic-gateReturns the output filehandle object.
1365*0Sstevel@tonic-gate
1366*0Sstevel@tonic-gate=cut
1367*0Sstevel@tonic-gate
1368*0Sstevel@tonic-gatesub output_handle {
1369*0Sstevel@tonic-gate   return $_[0]->{_OUTPUT};
1370*0Sstevel@tonic-gate}
1371*0Sstevel@tonic-gate
1372*0Sstevel@tonic-gate##---------------------------------------------------------------------------
1373*0Sstevel@tonic-gate
1374*0Sstevel@tonic-gate=head1 B<input_file()>
1375*0Sstevel@tonic-gate
1376*0Sstevel@tonic-gate            $fname = $parser->input_file();
1377*0Sstevel@tonic-gate
1378*0Sstevel@tonic-gateReturns the name of the input file being read.
1379*0Sstevel@tonic-gate
1380*0Sstevel@tonic-gate=cut
1381*0Sstevel@tonic-gate
1382*0Sstevel@tonic-gatesub input_file {
1383*0Sstevel@tonic-gate   return $_[0]->{_INFILE};
1384*0Sstevel@tonic-gate}
1385*0Sstevel@tonic-gate
1386*0Sstevel@tonic-gate##---------------------------------------------------------------------------
1387*0Sstevel@tonic-gate
1388*0Sstevel@tonic-gate=head1 B<input_handle()>
1389*0Sstevel@tonic-gate
1390*0Sstevel@tonic-gate            $fhandle = $parser->input_handle();
1391*0Sstevel@tonic-gate
1392*0Sstevel@tonic-gateReturns the current input filehandle object.
1393*0Sstevel@tonic-gate
1394*0Sstevel@tonic-gate=cut
1395*0Sstevel@tonic-gate
1396*0Sstevel@tonic-gatesub input_handle {
1397*0Sstevel@tonic-gate   return $_[0]->{_INPUT};
1398*0Sstevel@tonic-gate}
1399*0Sstevel@tonic-gate
1400*0Sstevel@tonic-gate##---------------------------------------------------------------------------
1401*0Sstevel@tonic-gate
1402*0Sstevel@tonic-gate=begin __PRIVATE__
1403*0Sstevel@tonic-gate
1404*0Sstevel@tonic-gate=head1 B<input_streams()>
1405*0Sstevel@tonic-gate
1406*0Sstevel@tonic-gate            $listref = $parser->input_streams();
1407*0Sstevel@tonic-gate
1408*0Sstevel@tonic-gateReturns a reference to an array which corresponds to the stack of all
1409*0Sstevel@tonic-gatethe input streams that are currently in the middle of being parsed.
1410*0Sstevel@tonic-gate
1411*0Sstevel@tonic-gateWhile parsing an input stream, it is possible to invoke
1412*0Sstevel@tonic-gateB<parse_from_file()> or B<parse_from_filehandle()> to parse a new input
1413*0Sstevel@tonic-gatestream and then return to parsing the previous input stream. Each input
1414*0Sstevel@tonic-gatestream to be parsed is pushed onto the end of this input stack
1415*0Sstevel@tonic-gatebefore any of its input is read. The input stream that is currently
1416*0Sstevel@tonic-gatebeing parsed is always at the end (or top) of the input stack. When an
1417*0Sstevel@tonic-gateinput stream has been exhausted, it is popped off the end of the
1418*0Sstevel@tonic-gateinput stack.
1419*0Sstevel@tonic-gate
1420*0Sstevel@tonic-gateEach element on this input stack is a reference to C<Pod::InputSource>
1421*0Sstevel@tonic-gateobject. Please see L<Pod::InputObjects> for more details.
1422*0Sstevel@tonic-gate
1423*0Sstevel@tonic-gateThis method might be invoked when printing diagnostic messages, for example,
1424*0Sstevel@tonic-gateto obtain the name and line number of the all input files that are currently
1425*0Sstevel@tonic-gatebeing processed.
1426*0Sstevel@tonic-gate
1427*0Sstevel@tonic-gate=end __PRIVATE__
1428*0Sstevel@tonic-gate
1429*0Sstevel@tonic-gate=cut
1430*0Sstevel@tonic-gate
1431*0Sstevel@tonic-gatesub input_streams {
1432*0Sstevel@tonic-gate   return $_[0]->{_INPUT_STREAMS};
1433*0Sstevel@tonic-gate}
1434*0Sstevel@tonic-gate
1435*0Sstevel@tonic-gate##---------------------------------------------------------------------------
1436*0Sstevel@tonic-gate
1437*0Sstevel@tonic-gate=begin __PRIVATE__
1438*0Sstevel@tonic-gate
1439*0Sstevel@tonic-gate=head1 B<top_stream()>
1440*0Sstevel@tonic-gate
1441*0Sstevel@tonic-gate            $hashref = $parser->top_stream();
1442*0Sstevel@tonic-gate
1443*0Sstevel@tonic-gateReturns a reference to the hash-table that represents the element
1444*0Sstevel@tonic-gatethat is currently at the top (end) of the input stream stack
1445*0Sstevel@tonic-gate(see L<"input_streams()">). The return value will be the C<undef>
1446*0Sstevel@tonic-gateif the input stack is empty.
1447*0Sstevel@tonic-gate
1448*0Sstevel@tonic-gateThis method might be used when printing diagnostic messages, for example,
1449*0Sstevel@tonic-gateto obtain the name and line number of the current input file.
1450*0Sstevel@tonic-gate
1451*0Sstevel@tonic-gate=end __PRIVATE__
1452*0Sstevel@tonic-gate
1453*0Sstevel@tonic-gate=cut
1454*0Sstevel@tonic-gate
1455*0Sstevel@tonic-gatesub top_stream {
1456*0Sstevel@tonic-gate   return $_[0]->{_TOP_STREAM} || undef;
1457*0Sstevel@tonic-gate}
1458*0Sstevel@tonic-gate
1459*0Sstevel@tonic-gate#############################################################################
1460*0Sstevel@tonic-gate
1461*0Sstevel@tonic-gate=head1 PRIVATE METHODS AND DATA
1462*0Sstevel@tonic-gate
1463*0Sstevel@tonic-gateB<Pod::Parser> makes use of several internal methods and data fields
1464*0Sstevel@tonic-gatewhich clients should not need to see or use. For the sake of avoiding
1465*0Sstevel@tonic-gatename collisions for client data and methods, these methods and fields
1466*0Sstevel@tonic-gateare briefly discussed here. Determined hackers may obtain further
1467*0Sstevel@tonic-gateinformation about them by reading the B<Pod::Parser> source code.
1468*0Sstevel@tonic-gate
1469*0Sstevel@tonic-gatePrivate data fields are stored in the hash-object whose reference is
1470*0Sstevel@tonic-gatereturned by the B<new()> constructor for this class. The names of all
1471*0Sstevel@tonic-gateprivate methods and data-fields used by B<Pod::Parser> begin with a
1472*0Sstevel@tonic-gateprefix of "_" and match the regular expression C</^_\w+$/>.
1473*0Sstevel@tonic-gate
1474*0Sstevel@tonic-gate=cut
1475*0Sstevel@tonic-gate
1476*0Sstevel@tonic-gate##---------------------------------------------------------------------------
1477*0Sstevel@tonic-gate
1478*0Sstevel@tonic-gate=begin _PRIVATE_
1479*0Sstevel@tonic-gate
1480*0Sstevel@tonic-gate=head1 B<_push_input_stream()>
1481*0Sstevel@tonic-gate
1482*0Sstevel@tonic-gate            $hashref = $parser->_push_input_stream($in_fh,$out_fh);
1483*0Sstevel@tonic-gate
1484*0Sstevel@tonic-gateThis method will push the given input stream on the input stack and
1485*0Sstevel@tonic-gateperform any necessary beginning-of-document or beginning-of-file
1486*0Sstevel@tonic-gateprocessing. The argument C<$in_fh> is the input stream filehandle to
1487*0Sstevel@tonic-gatepush, and C<$out_fh> is the corresponding output filehandle to use (if
1488*0Sstevel@tonic-gateit is not given or is undefined, then the current output stream is used,
1489*0Sstevel@tonic-gatewhich defaults to standard output if it doesnt exist yet).
1490*0Sstevel@tonic-gate
1491*0Sstevel@tonic-gateThe value returned will be reference to the hash-table that represents
1492*0Sstevel@tonic-gatethe new top of the input stream stack. I<Please Note> that it is
1493*0Sstevel@tonic-gatepossible for this method to use default values for the input and output
1494*0Sstevel@tonic-gatefile handles. If this happens, you will need to look at the C<INPUT>
1495*0Sstevel@tonic-gateand C<OUTPUT> instance data members to determine their new values.
1496*0Sstevel@tonic-gate
1497*0Sstevel@tonic-gate=end _PRIVATE_
1498*0Sstevel@tonic-gate
1499*0Sstevel@tonic-gate=cut
1500*0Sstevel@tonic-gate
1501*0Sstevel@tonic-gatesub _push_input_stream {
1502*0Sstevel@tonic-gate    my ($self, $in_fh, $out_fh) = @_;
1503*0Sstevel@tonic-gate    local *myData = $self;
1504*0Sstevel@tonic-gate
1505*0Sstevel@tonic-gate    ## Initialize stuff for the entire document if this is *not*
1506*0Sstevel@tonic-gate    ## an included file.
1507*0Sstevel@tonic-gate    ##
1508*0Sstevel@tonic-gate    ## NOTE: we need to be *very* careful when "defaulting" the output
1509*0Sstevel@tonic-gate    ## filehandle. We only want to use a default value if this is the
1510*0Sstevel@tonic-gate    ## beginning of the entire document (but *not* if this is an included
1511*0Sstevel@tonic-gate    ## file).
1512*0Sstevel@tonic-gate    unless (defined  $myData{_TOP_STREAM}) {
1513*0Sstevel@tonic-gate        $out_fh  = \*STDOUT  unless (defined $out_fh);
1514*0Sstevel@tonic-gate        $myData{_CUTTING}       = 1;   ## current "cutting" state
1515*0Sstevel@tonic-gate        $myData{_INPUT_STREAMS} = [];  ## stack of all input streams
1516*0Sstevel@tonic-gate    }
1517*0Sstevel@tonic-gate
1518*0Sstevel@tonic-gate    ## Initialize input indicators
1519*0Sstevel@tonic-gate    $myData{_OUTFILE} = '(unknown)'  unless (defined  $myData{_OUTFILE});
1520*0Sstevel@tonic-gate    $myData{_OUTPUT}  = $out_fh      if (defined  $out_fh);
1521*0Sstevel@tonic-gate    $in_fh            = \*STDIN      unless (defined  $in_fh);
1522*0Sstevel@tonic-gate    $myData{_INFILE}  = '(unknown)'  unless (defined  $myData{_INFILE});
1523*0Sstevel@tonic-gate    $myData{_INPUT}   = $in_fh;
1524*0Sstevel@tonic-gate    my $input_top     = $myData{_TOP_STREAM}
1525*0Sstevel@tonic-gate                      = new Pod::InputSource(
1526*0Sstevel@tonic-gate                            -name        => $myData{_INFILE},
1527*0Sstevel@tonic-gate                            -handle      => $in_fh,
1528*0Sstevel@tonic-gate                            -was_cutting => $myData{_CUTTING}
1529*0Sstevel@tonic-gate                        );
1530*0Sstevel@tonic-gate    local *input_stack = $myData{_INPUT_STREAMS};
1531*0Sstevel@tonic-gate    push(@input_stack, $input_top);
1532*0Sstevel@tonic-gate
1533*0Sstevel@tonic-gate    ## Perform beginning-of-document and/or beginning-of-input processing
1534*0Sstevel@tonic-gate    $self->begin_pod()  if (@input_stack == 1);
1535*0Sstevel@tonic-gate    $self->begin_input();
1536*0Sstevel@tonic-gate
1537*0Sstevel@tonic-gate    return  $input_top;
1538*0Sstevel@tonic-gate}
1539*0Sstevel@tonic-gate
1540*0Sstevel@tonic-gate##---------------------------------------------------------------------------
1541*0Sstevel@tonic-gate
1542*0Sstevel@tonic-gate=begin _PRIVATE_
1543*0Sstevel@tonic-gate
1544*0Sstevel@tonic-gate=head1 B<_pop_input_stream()>
1545*0Sstevel@tonic-gate
1546*0Sstevel@tonic-gate            $hashref = $parser->_pop_input_stream();
1547*0Sstevel@tonic-gate
1548*0Sstevel@tonic-gateThis takes no arguments. It will perform any necessary end-of-file or
1549*0Sstevel@tonic-gateend-of-document processing and then pop the current input stream from
1550*0Sstevel@tonic-gatethe top of the input stack.
1551*0Sstevel@tonic-gate
1552*0Sstevel@tonic-gateThe value returned will be reference to the hash-table that represents
1553*0Sstevel@tonic-gatethe new top of the input stream stack.
1554*0Sstevel@tonic-gate
1555*0Sstevel@tonic-gate=end _PRIVATE_
1556*0Sstevel@tonic-gate
1557*0Sstevel@tonic-gate=cut
1558*0Sstevel@tonic-gate
1559*0Sstevel@tonic-gatesub _pop_input_stream {
1560*0Sstevel@tonic-gate    my ($self) = @_;
1561*0Sstevel@tonic-gate    local *myData = $self;
1562*0Sstevel@tonic-gate    local *input_stack = $myData{_INPUT_STREAMS};
1563*0Sstevel@tonic-gate
1564*0Sstevel@tonic-gate    ## Perform end-of-input and/or end-of-document processing
1565*0Sstevel@tonic-gate    $self->end_input()  if (@input_stack > 0);
1566*0Sstevel@tonic-gate    $self->end_pod()    if (@input_stack == 1);
1567*0Sstevel@tonic-gate
1568*0Sstevel@tonic-gate    ## Restore cutting state to whatever it was before we started
1569*0Sstevel@tonic-gate    ## parsing this file.
1570*0Sstevel@tonic-gate    my $old_top = pop(@input_stack);
1571*0Sstevel@tonic-gate    $myData{_CUTTING} = $old_top->was_cutting();
1572*0Sstevel@tonic-gate
1573*0Sstevel@tonic-gate    ## Dont forget to reset the input indicators
1574*0Sstevel@tonic-gate    my $input_top = undef;
1575*0Sstevel@tonic-gate    if (@input_stack > 0) {
1576*0Sstevel@tonic-gate       $input_top = $myData{_TOP_STREAM} = $input_stack[-1];
1577*0Sstevel@tonic-gate       $myData{_INFILE}  = $input_top->name();
1578*0Sstevel@tonic-gate       $myData{_INPUT}   = $input_top->handle();
1579*0Sstevel@tonic-gate    } else {
1580*0Sstevel@tonic-gate       delete $myData{_TOP_STREAM};
1581*0Sstevel@tonic-gate       delete $myData{_INPUT_STREAMS};
1582*0Sstevel@tonic-gate    }
1583*0Sstevel@tonic-gate
1584*0Sstevel@tonic-gate    return  $input_top;
1585*0Sstevel@tonic-gate}
1586*0Sstevel@tonic-gate
1587*0Sstevel@tonic-gate#############################################################################
1588*0Sstevel@tonic-gate
1589*0Sstevel@tonic-gate=head1 TREE-BASED PARSING
1590*0Sstevel@tonic-gate
1591*0Sstevel@tonic-gateIf straightforward stream-based parsing wont meet your needs (as is
1592*0Sstevel@tonic-gatelikely the case for tasks such as translating PODs into structured
1593*0Sstevel@tonic-gatemarkup languages like HTML and XML) then you may need to take the
1594*0Sstevel@tonic-gatetree-based approach. Rather than doing everything in one pass and
1595*0Sstevel@tonic-gatecalling the B<interpolate()> method to expand sequences into text, it
1596*0Sstevel@tonic-gatemay be desirable to instead create a parse-tree using the B<parse_text()>
1597*0Sstevel@tonic-gatemethod to return a tree-like structure which may contain an ordered
1598*0Sstevel@tonic-gatelist of children (each of which may be a text-string, or a similar
1599*0Sstevel@tonic-gatetree-like structure).
1600*0Sstevel@tonic-gate
1601*0Sstevel@tonic-gatePay special attention to L<"METHODS FOR PARSING AND PROCESSING"> and
1602*0Sstevel@tonic-gateto the objects described in L<Pod::InputObjects>. The former describes
1603*0Sstevel@tonic-gatethe gory details and parameters for how to customize and extend the
1604*0Sstevel@tonic-gateparsing behavior of B<Pod::Parser>. B<Pod::InputObjects> provides
1605*0Sstevel@tonic-gateseveral objects that may all be used interchangeably as parse-trees. The
1606*0Sstevel@tonic-gatemost obvious one is the B<Pod::ParseTree> object. It defines the basic
1607*0Sstevel@tonic-gateinterface and functionality that all things trying to be a POD parse-tree
1608*0Sstevel@tonic-gateshould do. A B<Pod::ParseTree> is defined such that each "node" may be a
1609*0Sstevel@tonic-gatetext-string, or a reference to another parse-tree.  Each B<Pod::Paragraph>
1610*0Sstevel@tonic-gateobject and each B<Pod::InteriorSequence> object also supports the basic
1611*0Sstevel@tonic-gateparse-tree interface.
1612*0Sstevel@tonic-gate
1613*0Sstevel@tonic-gateThe B<parse_text()> method takes a given paragraph of text, and
1614*0Sstevel@tonic-gatereturns a parse-tree that contains one or more children, each of which
1615*0Sstevel@tonic-gatemay be a text-string, or an InteriorSequence object. There are also
1616*0Sstevel@tonic-gatecallback-options that may be passed to B<parse_text()> to customize
1617*0Sstevel@tonic-gatethe way it expands or transforms interior-sequences, as well as the
1618*0Sstevel@tonic-gatereturned result. These callbacks can be used to create a parse-tree
1619*0Sstevel@tonic-gatewith custom-made objects (which may or may not support the parse-tree
1620*0Sstevel@tonic-gateinterface, depending on how you choose to do it).
1621*0Sstevel@tonic-gate
1622*0Sstevel@tonic-gateIf you wish to turn an entire POD document into a parse-tree, that process
1623*0Sstevel@tonic-gateis fairly straightforward. The B<parse_text()> method is the key to doing
1624*0Sstevel@tonic-gatethis successfully. Every paragraph-callback (i.e. the polymorphic methods
1625*0Sstevel@tonic-gatefor B<command()>, B<verbatim()>, and B<textblock()> paragraphs) takes
1626*0Sstevel@tonic-gatea B<Pod::Paragraph> object as an argument. Each paragraph object has a
1627*0Sstevel@tonic-gateB<parse_tree()> method that can be used to get or set a corresponding
1628*0Sstevel@tonic-gateparse-tree. So for each of those paragraph-callback methods, simply call
1629*0Sstevel@tonic-gateB<parse_text()> with the options you desire, and then use the returned
1630*0Sstevel@tonic-gateparse-tree to assign to the given paragraph object.
1631*0Sstevel@tonic-gate
1632*0Sstevel@tonic-gateThat gives you a parse-tree for each paragraph - so now all you need is
1633*0Sstevel@tonic-gatean ordered list of paragraphs. You can maintain that yourself as a data
1634*0Sstevel@tonic-gateelement in the object/hash. The most straightforward way would be simply
1635*0Sstevel@tonic-gateto use an array-ref, with the desired set of custom "options" for each
1636*0Sstevel@tonic-gateinvocation of B<parse_text>. Let's assume the desired option-set is
1637*0Sstevel@tonic-gategiven by the hash C<%options>. Then we might do something like the
1638*0Sstevel@tonic-gatefollowing:
1639*0Sstevel@tonic-gate
1640*0Sstevel@tonic-gate    package MyPodParserTree;
1641*0Sstevel@tonic-gate
1642*0Sstevel@tonic-gate    @ISA = qw( Pod::Parser );
1643*0Sstevel@tonic-gate
1644*0Sstevel@tonic-gate    ...
1645*0Sstevel@tonic-gate
1646*0Sstevel@tonic-gate    sub begin_pod {
1647*0Sstevel@tonic-gate        my $self = shift;
1648*0Sstevel@tonic-gate        $self->{'-paragraphs'} = [];  ## initialize paragraph list
1649*0Sstevel@tonic-gate    }
1650*0Sstevel@tonic-gate
1651*0Sstevel@tonic-gate    sub command {
1652*0Sstevel@tonic-gate        my ($parser, $command, $paragraph, $line_num, $pod_para) = @_;
1653*0Sstevel@tonic-gate        my $ptree = $parser->parse_text({%options}, $paragraph, ...);
1654*0Sstevel@tonic-gate        $pod_para->parse_tree( $ptree );
1655*0Sstevel@tonic-gate        push @{ $self->{'-paragraphs'} }, $pod_para;
1656*0Sstevel@tonic-gate    }
1657*0Sstevel@tonic-gate
1658*0Sstevel@tonic-gate    sub verbatim {
1659*0Sstevel@tonic-gate        my ($parser, $paragraph, $line_num, $pod_para) = @_;
1660*0Sstevel@tonic-gate        push @{ $self->{'-paragraphs'} }, $pod_para;
1661*0Sstevel@tonic-gate    }
1662*0Sstevel@tonic-gate
1663*0Sstevel@tonic-gate    sub textblock {
1664*0Sstevel@tonic-gate        my ($parser, $paragraph, $line_num, $pod_para) = @_;
1665*0Sstevel@tonic-gate        my $ptree = $parser->parse_text({%options}, $paragraph, ...);
1666*0Sstevel@tonic-gate        $pod_para->parse_tree( $ptree );
1667*0Sstevel@tonic-gate        push @{ $self->{'-paragraphs'} }, $pod_para;
1668*0Sstevel@tonic-gate    }
1669*0Sstevel@tonic-gate
1670*0Sstevel@tonic-gate    ...
1671*0Sstevel@tonic-gate
1672*0Sstevel@tonic-gate    package main;
1673*0Sstevel@tonic-gate    ...
1674*0Sstevel@tonic-gate    my $parser = new MyPodParserTree(...);
1675*0Sstevel@tonic-gate    $parser->parse_from_file(...);
1676*0Sstevel@tonic-gate    my $paragraphs_ref = $parser->{'-paragraphs'};
1677*0Sstevel@tonic-gate
1678*0Sstevel@tonic-gateOf course, in this module-author's humble opinion, I'd be more inclined to
1679*0Sstevel@tonic-gateuse the existing B<Pod::ParseTree> object than a simple array. That way
1680*0Sstevel@tonic-gateeverything in it, paragraphs and sequences, all respond to the same core
1681*0Sstevel@tonic-gateinterface for all parse-tree nodes. The result would look something like:
1682*0Sstevel@tonic-gate
1683*0Sstevel@tonic-gate    package MyPodParserTree2;
1684*0Sstevel@tonic-gate
1685*0Sstevel@tonic-gate    ...
1686*0Sstevel@tonic-gate
1687*0Sstevel@tonic-gate    sub begin_pod {
1688*0Sstevel@tonic-gate        my $self = shift;
1689*0Sstevel@tonic-gate        $self->{'-ptree'} = new Pod::ParseTree;  ## initialize parse-tree
1690*0Sstevel@tonic-gate    }
1691*0Sstevel@tonic-gate
1692*0Sstevel@tonic-gate    sub parse_tree {
1693*0Sstevel@tonic-gate        ## convenience method to get/set the parse-tree for the entire POD
1694*0Sstevel@tonic-gate        (@_ > 1)  and  $_[0]->{'-ptree'} = $_[1];
1695*0Sstevel@tonic-gate        return $_[0]->{'-ptree'};
1696*0Sstevel@tonic-gate    }
1697*0Sstevel@tonic-gate
1698*0Sstevel@tonic-gate    sub command {
1699*0Sstevel@tonic-gate        my ($parser, $command, $paragraph, $line_num, $pod_para) = @_;
1700*0Sstevel@tonic-gate        my $ptree = $parser->parse_text({<<options>>}, $paragraph, ...);
1701*0Sstevel@tonic-gate        $pod_para->parse_tree( $ptree );
1702*0Sstevel@tonic-gate        $parser->parse_tree()->append( $pod_para );
1703*0Sstevel@tonic-gate    }
1704*0Sstevel@tonic-gate
1705*0Sstevel@tonic-gate    sub verbatim {
1706*0Sstevel@tonic-gate        my ($parser, $paragraph, $line_num, $pod_para) = @_;
1707*0Sstevel@tonic-gate        $parser->parse_tree()->append( $pod_para );
1708*0Sstevel@tonic-gate    }
1709*0Sstevel@tonic-gate
1710*0Sstevel@tonic-gate    sub textblock {
1711*0Sstevel@tonic-gate        my ($parser, $paragraph, $line_num, $pod_para) = @_;
1712*0Sstevel@tonic-gate        my $ptree = $parser->parse_text({<<options>>}, $paragraph, ...);
1713*0Sstevel@tonic-gate        $pod_para->parse_tree( $ptree );
1714*0Sstevel@tonic-gate        $parser->parse_tree()->append( $pod_para );
1715*0Sstevel@tonic-gate    }
1716*0Sstevel@tonic-gate
1717*0Sstevel@tonic-gate    ...
1718*0Sstevel@tonic-gate
1719*0Sstevel@tonic-gate    package main;
1720*0Sstevel@tonic-gate    ...
1721*0Sstevel@tonic-gate    my $parser = new MyPodParserTree2(...);
1722*0Sstevel@tonic-gate    $parser->parse_from_file(...);
1723*0Sstevel@tonic-gate    my $ptree = $parser->parse_tree;
1724*0Sstevel@tonic-gate    ...
1725*0Sstevel@tonic-gate
1726*0Sstevel@tonic-gateNow you have the entire POD document as one great big parse-tree. You
1727*0Sstevel@tonic-gatecan even use the B<-expand_seq> option to B<parse_text> to insert
1728*0Sstevel@tonic-gatewhole different kinds of objects. Just don't expect B<Pod::Parser>
1729*0Sstevel@tonic-gateto know what to do with them after that. That will need to be in your
1730*0Sstevel@tonic-gatecode. Or, alternatively, you can insert any object you like so long as
1731*0Sstevel@tonic-gateit conforms to the B<Pod::ParseTree> interface.
1732*0Sstevel@tonic-gate
1733*0Sstevel@tonic-gateOne could use this to create subclasses of B<Pod::Paragraphs> and
1734*0Sstevel@tonic-gateB<Pod::InteriorSequences> for specific commands (or to create your own
1735*0Sstevel@tonic-gatecustom node-types in the parse-tree) and add some kind of B<emit()>
1736*0Sstevel@tonic-gatemethod to each custom node/subclass object in the tree. Then all you'd
1737*0Sstevel@tonic-gateneed to do is recursively walk the tree in the desired order, processing
1738*0Sstevel@tonic-gatethe children (most likely from left to right) by formatting them if
1739*0Sstevel@tonic-gatethey are text-strings, or by calling their B<emit()> method if they
1740*0Sstevel@tonic-gateare objects/references.
1741*0Sstevel@tonic-gate
1742*0Sstevel@tonic-gate=head1 SEE ALSO
1743*0Sstevel@tonic-gate
1744*0Sstevel@tonic-gateL<Pod::InputObjects>, L<Pod::Select>
1745*0Sstevel@tonic-gate
1746*0Sstevel@tonic-gateB<Pod::InputObjects> defines POD input objects corresponding to
1747*0Sstevel@tonic-gatecommand paragraphs, parse-trees, and interior-sequences.
1748*0Sstevel@tonic-gate
1749*0Sstevel@tonic-gateB<Pod::Select> is a subclass of B<Pod::Parser> which provides the ability
1750*0Sstevel@tonic-gateto selectively include and/or exclude sections of a POD document from being
1751*0Sstevel@tonic-gatetranslated based upon the current heading, subheading, subsubheading, etc.
1752*0Sstevel@tonic-gate
1753*0Sstevel@tonic-gate=for __PRIVATE__
1754*0Sstevel@tonic-gateB<Pod::Callbacks> is a subclass of B<Pod::Parser> which gives its users
1755*0Sstevel@tonic-gatethe ability the employ I<callback functions> instead of, or in addition
1756*0Sstevel@tonic-gateto, overriding methods of the base class.
1757*0Sstevel@tonic-gate
1758*0Sstevel@tonic-gate=for __PRIVATE__
1759*0Sstevel@tonic-gateB<Pod::Select> and B<Pod::Callbacks> do not override any
1760*0Sstevel@tonic-gatemethods nor do they define any new methods with the same name. Because
1761*0Sstevel@tonic-gateof this, they may I<both> be used (in combination) as a base class of
1762*0Sstevel@tonic-gatethe same subclass in order to combine their functionality without
1763*0Sstevel@tonic-gatecausing any namespace clashes due to multiple inheritance.
1764*0Sstevel@tonic-gate
1765*0Sstevel@tonic-gate=head1 AUTHOR
1766*0Sstevel@tonic-gate
1767*0Sstevel@tonic-gatePlease report bugs using L<http://rt.cpan.org>.
1768*0Sstevel@tonic-gate
1769*0Sstevel@tonic-gateBrad Appleton E<lt>bradapp@enteract.comE<gt>
1770*0Sstevel@tonic-gate
1771*0Sstevel@tonic-gateBased on code for B<Pod::Text> written by
1772*0Sstevel@tonic-gateTom Christiansen E<lt>tchrist@mox.perl.comE<gt>
1773*0Sstevel@tonic-gate
1774*0Sstevel@tonic-gate=cut
1775*0Sstevel@tonic-gate
1776*0Sstevel@tonic-gate1;
1777