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