home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 10 / AU_CD10.iso / Updates / Perl / RPC / !Perl / lib / site_perl / POD / Parser.pm next >
Encoding:
Perl POD Document  |  1997-07-14  |  35.8 KB  |  1,108 lines

  1. #############################################################################
  2. # Parser.pm -- package which defines a base class for parsing pod docs.
  3. #
  4. # Based on Tom Christiansen's Pod::Text module
  5. # (with extensive modifications).
  6. #
  7. # Copyright (C) 1996 Tom Christiansen. All rights reserved.
  8. # This file is part of "PodParser". PodParser is free software;
  9. # you can redistribute it and/or modify it under the same terms
  10. # as Perl itself.
  11. #############################################################################
  12.  
  13. package Pod::Parser;
  14.  
  15. $VERSION = 1.00;   ## Current version of this package
  16. require  5.002;    ## requires Perl version 5.002 or later
  17.  
  18. =head1 NAME
  19.  
  20. Pod::Parser - base class for creating pod filters and translators
  21.  
  22. =head1 SYNOPSIS
  23.  
  24.     use Pod::Parser;
  25.     package MyParser;
  26.     @ISA = qw(Pod::Parser);
  27.  
  28.     sub new {
  29.         ## constructor code ...
  30.     }
  31.  
  32.     ## implementation of appropriate subclass methods ...
  33.  
  34.     package main;
  35.     $parser = new MyParser;
  36.     @ARGV = ('-')  unless (@ARGV > 0);
  37.     for (@ARGV) {
  38.         $parser->parse_from_file($_);
  39.     }
  40.  
  41. =head1 DESCRIPTION
  42.  
  43. B<Pod::Parser> is an abstract base class for implementing filters and/or
  44. translators to parse pod documentation into other formats. It handles
  45. most of the difficulty of parsing the pod sections in a file and leaves
  46. it to the subclasses to override various methods to provide the actual
  47. translation. The other thing that B<Pod::Parser> provides is the ability
  48. to process only selected sections of pod documentation from the input.
  49.  
  50. =head2 SECTION SPECIFICATIONS
  51.  
  52. Certain methods and functions provided by B<Pod::Parser> may be given
  53. one or more "section specifications" to restrict the text processed to
  54. only the desired set of sections and their corresponding subsections.  A
  55. section specification is a string containing one or more Perl-style
  56. regular expressions separated by forward slashes ("/").  If you need to
  57. use a forward slash literally within a section title you can escape it
  58. with a backslash ("\/"). 
  59.  
  60. The formal syntax of a section specification is:
  61.  
  62. =over 4
  63.  
  64. =item
  65.  
  66. I<head1-title-regexp>/I<head2-title-regexp>/...
  67.  
  68. =back
  69.  
  70. Any omitted or empty regular expressions will default to ".*".
  71. Please note that each regular expression given is implicitly
  72. anchored by adding "^" and "$" to the beginning and end.  Also, if a
  73. given regular expression starts with a "!" character, then the
  74. expression is negated (so C<!foo> would match anything I<except>
  75. C<foo>).
  76.  
  77. Some example section specifications follow.
  78.  
  79. =over 4
  80.  
  81. =item
  82. Match the C<NAME> and C<SYNOPSIS> sections and all of their subsections:
  83.  
  84. C<NAME|SYNOPSIS>
  85.  
  86. =item
  87. Match only the C<Question> and C<Answer> subsections of the C<DESCRIPTION>
  88. section:
  89.  
  90. C<DESCRIPTION/Question|Answer>
  91.  
  92. =item
  93. Match the C<Comments> subsection of I<all> sections:
  94.  
  95. C</Comments>
  96.  
  97. =item
  98. Match all subsections of C<DESCRIPTION> I<except> for C<Comments>:
  99.  
  100. C<DESCRIPTION/!Comments>
  101.  
  102. =item
  103. Match the C<DESCRIPTION> section but do I<not> match any of its subsections:
  104.  
  105. C<DESCRIPTION/!.+>
  106.  
  107. =item
  108. Match all top level sections but none of their subsections:
  109.  
  110. C</!.+>
  111.  
  112. =back 
  113.  
  114. =cut
  115.  
  116. #############################################################################
  117.  
  118. use strict;
  119. # use diagnostics;
  120. use Carp;
  121.  
  122. ## Maximum number of heading levels supported for '=headN' directives
  123. $Pod::Parser::MAX_HEAD_LEVEL = 3;
  124.  
  125. ##---------------------------------------------------------------------------
  126.  
  127. =head1 FUNCTIONS
  128.  
  129. B<Pod::Parser> provides the following functions (please note that these
  130. are functions and I<not> methods, they do not take an object reference
  131. as an implicit first parameter):
  132.  
  133. =cut
  134.  
  135. ##---------------------------------
  136. ## Function definitions begin here
  137. ##---------------------------------
  138.  
  139. =head2 version()
  140.  
  141. Return the current version of this package.
  142.  
  143. =cut
  144.  
  145. sub version {
  146.     no strict;
  147.     return  $VERSION;
  148. }
  149.  
  150. ##---------------------------------------------------------------------------
  151.  
  152. =head1 INSTANCE METHODS
  153.  
  154. B<Pod::Parser> provides several methods, some of which should be
  155. overridden by subclasses.  They are as follows:
  156.  
  157. =cut
  158.  
  159. ##-------------------------------
  160. ## Method definitions begin here
  161. ##-------------------------------
  162.  
  163. =head2 new()
  164.  
  165. This is the the constructor for the base class. You should only use it
  166. if you want to create an instance of a B<Pod::Parser> instead of one of
  167. its subclasses. The constructor for this class and all of its subclasses
  168. should return a blessed reference to an associative array (hash).
  169.  
  170. =cut
  171.  
  172. sub new {
  173.     my $this = shift;
  174.     my $class = ref($this) || $this;
  175.     my %params = @_;
  176.     my $self = {%params};
  177.     bless $self, $class;
  178.     $self->initialize();
  179.     return $self;
  180. }
  181.  
  182. =head2 initialize()
  183.  
  184. This method performs any necessary base class initialization.
  185. It takes no arguments (other than the object instance of course).
  186. If subclasses override this method then they I<must> be sure to
  187. invoke the superclass' B<initialize()> method.
  188.  
  189. =cut
  190.  
  191. sub initialize {
  192.     my $self = shift;
  193.     return;
  194. }
  195.  
  196. =head2 select($section_spec1, $section_spec2, ...)
  197.  
  198. This is the method that is used to select the particular sections and
  199. subsections of pod documentation that are to be printed and/or
  200. processed. If the I<first> I<argument> is the string "+", then the
  201. remaining section specifications are I<added> to the current list of
  202. selections; otherwise the given section specifications will I<replace>
  203. the current list of selections.
  204.  
  205. Each of the C<$section_spec> arguments should be a section
  206. specification as described in L<"SECTION SPECIFICATIONS">.  The section
  207. specifications are parsed by this method and the resulting regular
  208. expressions are stored in the array referenced by
  209. C<$self-E<gt>{SELECTED}> (please see the description of this member
  210. variable in L<"INSTANCE DATA">).
  211.  
  212. This method should I<not> normally be overridden by subclasses.
  213.  
  214. =cut
  215.  
  216. sub select {
  217.     my $self = shift;
  218.     my @sections = @_;
  219.     my $add = ($sections[0] eq "+") ? shift(@sections) : "";
  220.     ## reset the set of sections to use
  221.     unless (@sections > 0) {
  222.         undef $self->{SELECTED}  unless ($add);
  223.         return;
  224.     }
  225.     $self->{SELECTED} = []  unless ($add  &&  defined $self->{SELECTED});
  226.     local($_);
  227.     my ($spec, $errors);
  228.     my (@re, $i, $negated, %exprs);
  229.     ## Parse each spec
  230.     for $spec (@sections) {
  231.         $_ = $spec;
  232.         s|\\\\|\001|go;  ## handle escaped backward slashes
  233.         s|\\/|\002|go;   ## handle escaped forward slashes
  234.         ## Extract the regexps for the heading titles
  235.         @re = split('/', $_, $Pod::Parser::MAX_HEAD_LEVEL);
  236.         ## Modify the regexps as needed and check their syntax
  237.         for ($i = 0; $i < $Pod::Parser::MAX_HEAD_LEVEL; ++$i) {
  238.             $re[$i]  = '.*'  if ((! defined $re[$i]) || $re[$i] eq "");
  239.             $re[$i] .= '.+'  if ($re[$i] eq '!');
  240.             ## Put back any escape sequences we "handled"
  241.             $re[$i] =~ s|\001|\\\\|go;
  242.             $re[$i] =~ s|\002|\\/|go;
  243.             ## Check for negation
  244.             $negated = ($re[$i] =~ /^\!/o);
  245.             $re[$i] = $'  if ($negated);
  246.             ## Check regexp syntax
  247.             eval "/$re[$i]/";
  248.             if ($@) {
  249.                 ++$errors;
  250.                 carp "Invalid regular expression /$re[$i]/ in \"$spec\": $@\n";
  251.             }
  252.             else {
  253.                 ## Add the forward and rear anchors (and put the negator back)
  254.                 $re[$i] = '^' . $re[$i]  unless ($re[$i] =~ /^\^/o);
  255.                 $re[$i] = $re[$i] . '$'  unless ($re[$i] =~ /\$$/o);
  256.                 $re[$i] = '!' . $re[$i]  if ($negated);
  257.             }
  258.         }
  259.         if ($errors) {
  260.             carp "Ignoring section spec \"$spec\"!\n";
  261.         }
  262.         else {
  263.             ## Store them in our sections array
  264.             push(@{$self->{SELECTED}}, [ @re ]);
  265.         }
  266.     }
  267. }
  268.  
  269. =head2 want_section($head1_title, $head2_title, ...)
  270.  
  271. Returns a value of true if the given section and subsection titles match
  272. any of the section specifications passed to the B<select()> method (or
  273. if no section specifications were given). Returns a value of false
  274. otherwise. If C<$headN_title> is ommitted then it defaults to the current
  275. C<headN> section title in the input.
  276.  
  277. This method should I<not> normally be overridden by subclasses.
  278.  
  279. =cut
  280.  
  281. sub want_section {
  282.     my $self = shift;
  283.     my (@heads) = @_;
  284.     ## Return true if no restrictions were explicitly specified
  285.     return  1  unless ((defined $self->{SELECTED})
  286.                        && (@{$self->{SELECTED}} > 0));
  287.  
  288.     ## default any unspecified sections to the current one
  289.     my $i;
  290.     for ($i = 0; $i < $Pod::Parser::MAX_HEAD_LEVEL; ++$i) {
  291.         $heads[$i] = $self->{HEADINGS}->[$i]  unless (defined $heads[$i]);
  292.     }
  293.  
  294.     ## Look for a match against the specified section expressions
  295.     my ($sec_spec, $regexp, $negated, $match);
  296.     for $sec_spec (@{$self->{SELECTED}}) {
  297.         $match = 1;
  298.         for ($i = 0; $i < $Pod::Parser::MAX_HEAD_LEVEL; ++$i) {
  299.             $regexp  = $sec_spec->[$i];
  300.             $negated = ($regexp =~ /^\!/o);
  301.             $regexp  = $'  if ($negated);
  302.             $match  &= ($negated ? ($heads[$i] !~ /${regexp}/)
  303.                                  : ($heads[$i] =~ /${regexp}/));
  304.             last unless ($match);
  305.         }
  306.         return  1  if ($match);
  307.     }
  308.     return  0;  ## no match
  309. }
  310.  
  311. =head2 begin_input()
  312.  
  313. This method is invoked by B<parse_from_filehandle()> immediately I<before>
  314. processing input from a filehandle. The base class implementation does
  315. nothing but subclasses may override it to perform any per-file
  316. intializations.
  317.  
  318. =cut
  319.  
  320. sub begin_input {
  321.     my $self = shift;
  322.     #----------------------------------------------------
  323.     # Subclasses may wish to make use of some of the
  324.     # commented-out code below for initializing pragmas
  325.     #----------------------------------------------------
  326.     # $self->{PRAGMAS} = {
  327.     #     FILL     => 'on',
  328.     #     STYLE    => 'plain',
  329.     #     INDENT   => 0,
  330.     # };
  331.     # ## Initialize all PREVIOUS_XXX pragma values
  332.     # my ($name, $value);
  333.     # for (($name, $value) = each %{$self->{PRAGMAS}}) {
  334.     #     $self->{PRAGMAS}->{"PREVIOUS_${name}"} = $value;
  335.     # }
  336.     #----------------------------------------------------
  337.     return;
  338. }
  339.  
  340. =head2 end_input()
  341.  
  342. This method is invoked by B<parse_from_filehandle()> immediately I<after>
  343. processing input from a filehandle. The base class implementation does
  344. nothing but subclasses may override it to perform any per-file
  345. cleanup actions.
  346.  
  347. =cut
  348.  
  349. sub end_input {
  350.     my $self = shift;
  351.     return;
  352. }
  353.  
  354. =head2 preprocess_line($text)
  355.  
  356. This methods should be overridden by subclasses that wish to perform any
  357. kind of preprocessing for each I<line> of input (I<before> it has been
  358. determined whether or not it is part of a pod paragraph). The parameter
  359. C<$text> is the input line and the value returned should correspond to
  360. the new text to use in its place. If the empty string or an undefined
  361. value is returned then no further process will be performed for this
  362. line. If desired, this method can call the B<parse_paragraph()> method
  363. directly with any preprocessed text and return an empty string (to
  364. indicate that no further processing is needed).
  365.  
  366. Please note that the B<preprocess_line()> method is invoked I<before>
  367. the B<preprocess_paragraph()> method. After all (possibly preprocessed)
  368. lines in a paragraph have been assembled together and it has been
  369. determined that the paragraph is part of the pod documentation from one
  370. of the selected sections, then B<preprocess_paragraph()> is invoked.
  371.  
  372. The base class implementation of this method returns the given text.
  373.  
  374. =cut
  375.  
  376. sub preprocess_line($text) {
  377.     my $self = shift;
  378.     my $text = shift;
  379.     return  $text;
  380. }
  381.  
  382. =head2 preprocess_paragraph($text)
  383.  
  384. This method should be overridden by subclasses that wish to perform any
  385. kind of preprocessing for each block (paragraph) of pod documentation
  386. that appears in the input stream.  The parameter C<$text> is the pod
  387. paragraph from the input file and the value returned should correspond
  388. to the new text to use in its place.  If the empty string is returned or
  389. an undefined value is returned, then the given C<$text> is ignored (not
  390. processed).
  391.  
  392. This method is invoked by B<parse_paragraph()>. After it returns,
  393. B<parse_paragraph()> examines the current cutting state (which is
  394. stored in C<$self-E<gt>{CUTTING}>). If it evaluates to false then input text
  395. (including the given C<$text>) is cut (not processed) until the next pod
  396. directive is encountered.
  397.  
  398. Please note that the B<preprocess_line()> method is invoked I<before>
  399. the B<preprocess_paragraph()> method. After all (possibly preprocessed)
  400. lines in a paragraph have been assembled together and it has been
  401. determined that the paragraph is part of the pod documentation from one
  402. of the selected sections, then B<preprocess_paragraph()> is invoked.
  403.  
  404. The base class implementation of this method returns the given text.
  405.  
  406. =cut
  407.  
  408. sub preprocess_paragraph {
  409.     my $self = shift;
  410.     my $text = shift;
  411.     return  $text;
  412. }
  413.  
  414. =head2 parse_pragmas($cmd, $text, $sep)
  415.  
  416. This method is called when an C<=pod> directive is encountered. When
  417. such a pod directive is seen in the input, this method is called and is
  418. passed the command name C<$cmd> (which should be "pod") and the
  419. remainder of the text paragraph C<$text> which appeared immediately
  420. after the command name. If desired, the text which separated the C<=pod>
  421. directive from its corresponding text may be found in C<$sep>.  Each
  422. word in C<$text> is examined to see if it is a pragma specification.
  423. Pragma specifications are of the form C<pragma_name=pragma_value>.
  424.  
  425. Unless the given object is an instance of the B<Pod::Parser> class, the
  426. base class implementation of this method will invoke the B<pragma()> method for
  427. each pragma specification in C<$text>.  I<If and only if> the given
  428. object I<is> an instance of the B<Pod::Parser> class, the base class
  429. version of this method will simply reproduce the C<=pod> command exactly
  430. as it appeared in the input.
  431.  
  432. Derived classes should I<not> usually need to reimplement this method.
  433.  
  434. =cut
  435.  
  436. sub parse_pragmas {
  437.     my $self = shift;
  438.     my $cmd  = shift;
  439.     my $text = shift;
  440.     my $sep  = shift;
  441.     $cmd  = ''  unless (defined $cmd);
  442.     $text = ''  unless (defined $text);
  443.     $sep  = ' ' unless (defined $sep);
  444.     local($_);
  445.     if (ref($self) eq 'Pod::Parser') {
  446.         ## If and only if this is an instance of the base class, then
  447.         ## dump the '=pod' paragraph exactly as it appeared in the input.
  448.         my $out_fh = $self->{OUTPUT};
  449.         print $out_fh "=${cmd}${sep}${text}";
  450.     }
  451.     else {
  452.         ## otherwise invoke the pragma command for each word in $text
  453.         my @pragmas = split(" ", $text);
  454.         for (@pragmas) {
  455.             $self->pragma(lc $`, $')  if (/=/o);
  456.         }
  457.     }
  458. }
  459.  
  460. =head2 pragma($pragma_name, $pragma_value)
  461.  
  462. This method is invoked for each pragma encountered inside an C<=pod>
  463. paragraph (see the description of the B<parse_pragmas()> method). The
  464. pragma name is passed in C<$pragma_name> (which should always be
  465. lowercase) and the corresponding value is C<$pragma_value>.
  466.  
  467. The base class implementation of this method does nothing.  Derived
  468. class implementations of this method should be able to recognize at
  469. least the following pragmas and take any necessary actions when they are
  470. encountered:
  471.  
  472. =over 4
  473.  
  474. =item B<fill=value>
  475.  
  476. The argument I<value> should be one of C<on>, C<off>, or C<previous>.
  477. Specifies that "filling-mode" should set to 1, 0, or its previous value
  478. (respectively). If I<value> is omitted then the default is C<on>.
  479. Derived classes may use this to decide whether or not to perform any
  480. filling (wrapping) of subsequent text.
  481.  
  482. =item B<style=value>
  483.  
  484. The argument I<value> should be one of C<bold>, C<italic>, C<code>,
  485. C<plain>, or C<previous>. Specifies that the current default paragraph
  486. font should be set to C<bold>, C<italic>, C<code>, the empty string C<>,
  487. or its previous value (respectively).  If I<value> is omitted then the
  488. default is C<plain>.  Derived classes may use this to determine the
  489. default font style to use for subsequent text.
  490.  
  491. =item B<indent=value>
  492.  
  493. The argument I<value> should be an integer value (with an optional
  494. sign).  Specifies that the current indentation level should be reset to
  495. the given value. If a plus (minus) sign precedes the number then the
  496. indentation level should be incremented (decremented) by the given
  497. number. If only a plus or minus sign is given (without a number) then
  498. the current indentation level is incremented or decremented by some
  499. default amount (to be determined by subclasses).
  500.  
  501. =back
  502.  
  503. The value returned will be 1 if the pragma name was recognized and 0 if
  504. it wasnt (in which case the pragma was ignored).
  505.  
  506. Derived classes should override this method if they wish to implement
  507. any pragmas. The base class implementation of this method does nothing
  508. but it does contain some commented-out code which subclasses may want
  509. to make use of when implementing pragmas.
  510.  
  511. =cut
  512.  
  513. sub pragma {
  514.     my $self  = shift;
  515.     ## convert remaining args to lowercase
  516.     my $name  = lc shift;
  517.     my $value = lc shift;
  518.     my $rc = 1;
  519.     local($_);
  520.     #----------------------------------------------------
  521.     # Subclasses may wish to make use of some of the
  522.     # commented-out code below for processing pragmas
  523.     #----------------------------------------------------
  524.     # my ($abbrev, %abbrev_table);
  525.     # if ($name eq 'fill') {
  526.     #     %abbrev_table = ('on' => 'on',
  527.     #                      'of' => 'off',
  528.     #                      'p'  => 'previous');
  529.     #     $value = 'on' unless ((defined $value) && ($value ne ''));
  530.     #     return  $rc  unless ($value =~ /^(on|of|p)/io);
  531.     #     $abbrev = $1;
  532.     #     $value = $abbrev_table{$abbrev};
  533.     #     if ($value eq 'previous') {
  534.     #         $self->{PRAGMAS}->{FILL} = $self->{PRAGMAS}->{PREVIOUS_FILL};
  535.     #     }
  536.     #     else {
  537.     #         $self->{PRAGMAS}->{PREVIOUS_FILL} = $self->{PRAGMAS}->{FILL};
  538.     #         $self->{PRAGMAS}->{FILL} = $value;
  539.     #     }
  540.     # }
  541.     # elsif ($name eq 'style') {
  542.     #     %abbrev_table = ('b'  => 'bold',
  543.     #                      'i'  => 'italic',
  544.     #                      'c'  => 'code',
  545.     #                      'pl' => 'plain',
  546.     #                      'pr' => 'previous');
  547.     #     $value = 'plain' unless ((defined $value) && ($value ne ''));
  548.     #     return  $rc  unless ($value =~ /^(b|i|c|pl|pr)/io);
  549.     #     $abbrev = $1;
  550.     #     $value = $abbrev_table{$abbrev};
  551.     #     if ($value eq 'previous') {
  552.     #         $self->{PRAGMAS}->{STYLE} = $self->{PRAGMAS}->{PREVIOUS_STYLE};
  553.     #     }
  554.     #     else {
  555.     #         $self->{PRAGMAS}->{PREVIOUS_STYLE} = $self->{PRAGMAS}->{STYLE};
  556.     #         $self->{PRAGMAS}->{STYLE} = $value;
  557.     #     }
  558.     # }
  559.     # elsif ($name eq 'indent') {
  560.     #     return $rc unless ((defined $value) && ($value =~ /^([-+]?)(\d*)$/o));
  561.     #     my ($sign, $number) = ($1, $2);
  562.     #     $value .= "4"  unless ((defined $number) && ($number ne ''));
  563.     #     $self->{PRAGMAS}->{PREVIOUS_INDENT} = $self->{PRAGMAS}->{INDENT};
  564.     #     if ($sign) {
  565.     #         $self->{PRAGMAS}->{INDENT} += (0 + $value);
  566.     #     }
  567.     #     else {
  568.     #         $self->{PRAGMAS}->{INDENT} = $value;
  569.     #     } 
  570.     # }
  571.     # else {
  572.     #     $rc = 0;
  573.     # }
  574.     #----------------------------------------------------
  575.     return $rc;
  576. }
  577.  
  578. =head2 command($cmd, $text, $sep)
  579.  
  580. This method should be overridden by subclasses to take the appropriate
  581. action when a pod command paragraph (denoted by a line beginning with
  582. "=") is encountered.  When such a pod directive is seen in the input,
  583. this method is called and is passed the command name C<$cmd> and the
  584. remainder of the text paragraph C<$text> which appears immediately after
  585. the command name. If desired, the text which separated the command from
  586. its corresponding text may be found in C<$sep>.  Note that this method
  587. is I<not> called for C<=pod> paragraphs.
  588.  
  589. The base class implementation of this method simply prints the raw pod
  590. command to the output filehandle and then invokes the B<textblock()>
  591. method, passing it the C<$text> parameter.
  592.  
  593. =cut
  594.  
  595. sub command {
  596.     my $self = shift;
  597.     my $cmd  = shift;
  598.     my $text = shift;
  599.     my $sep  = shift;
  600.     $cmd  = ''  unless (defined $cmd);
  601.     $text = ''  unless (defined $text);
  602.     $sep  = ' ' unless (defined $sep);
  603.     my $out_fh = $self->{OUTPUT};
  604.     print $out_fh "=${cmd}${sep}";
  605.     $self->textblock($text);
  606. }
  607.  
  608. =head2 verbatim($text)
  609.  
  610. This method may be overridden by subclasses to take the appropriate
  611. action when a block of verbatim text is encountered. It is passed the
  612. text block C<$text> as a parameter.
  613.  
  614. The base class implementation of this method simply prints the textblock
  615. (unmodified) to the output filehandle.
  616.  
  617. =cut
  618.  
  619. sub verbatim {
  620.     my $self = shift;
  621.     my $text = shift;
  622.     my $out_fh = $self->{OUTPUT};
  623.     print $out_fh $text;
  624. }
  625.  
  626. =head2 textblock($text)
  627.  
  628. This method may be overridden by subclasses to take the appropriate
  629. action when a normal block of pod text is encountered (although the base
  630. class method will usually do what you want). It is passed the text block
  631. C<$text> as a parameter.
  632.  
  633. In order to process interior sequences, subclasses implementations of
  634. this method will probably want invoke the B<interpolate()> method,
  635. passing it the text block C<$text> as a parameter and then perform any
  636. desired processing upon the returned result.
  637.  
  638. The base class implementation of this method simply prints the text block
  639. as it occurred in the input stream).
  640.  
  641. =cut
  642.  
  643. sub textblock {
  644.     my $self  = shift;
  645.     my $text  = shift;
  646.     local($_) = $self->interpolate($text);
  647.     print  $_;
  648. }
  649.  
  650. =head2 interior_sequence($seq_cmd, $seq_arg)
  651.  
  652. This method should be overridden by subclasses to take the appropriate
  653. action when an interior sequence is encountered. An interior sequence is
  654. an embedded command within a block of text which appears as a command
  655. name (usually a single uppercase character) followed immediately by
  656. a string of text which is enclosed in angle brackets. This method is
  657. passed the sequence command C<$seq_cmd> and the corresponding text
  658. $seq_arg and is invoked by the B<interpolate()> method for each
  659. interior sequence that occurs in the string that it is passed.
  660. It should return the desired text string to be used in place of
  661. the interior sequence.
  662.  
  663. Subclass implementationss of this method may wish to examine the
  664. the array referenced by C<$self-E<gt>{SEQUENCES}> which is a
  665. stack of all the interior sequences that are currently being 
  666. processed (they may be nested). The current interior sequence
  667. (the one given by C<$seq_cmdE<lt>$seq_argE<gt>>) should always
  668. be at the top of this stack.
  669.  
  670. The base class implementation of the B<interior_sequence()> method simply
  671. returns the raw text of the of the interior sequence (as it occurred in
  672. the input) to the output filehandle.
  673.  
  674. =cut
  675.  
  676. sub interior_sequence {
  677.     my $self = shift;
  678.     my $seq_cmd = shift;
  679.     my $seq_arg = shift;
  680.     return  "${seq_cmd}<${seq_arg}>";
  681. }
  682.  
  683. =head2 interpolate($text, $end_re)
  684.  
  685. This method will translate all text (including any embedded interior
  686. sequences) in the given text string C<$text> and return the
  687. interpolated result.  If a second argument is given, then it is taken to
  688. be a regular expression that indicates when to quit interpolating the
  689. string.  Upon return, the C<$text> parameter will have been modified to
  690. contain only the un-processed portion of the given string (which will
  691. I<not> contain any text matched by C<$end_re>).
  692.  
  693. This method should probably I<not> be overridden by subclasses.
  694. It should be noted that this method invokes itself recursively
  695. to handle any nested interior sequences.
  696.  
  697. =cut
  698.  
  699. sub interpolate {
  700.     my $self = shift;
  701.     my ($text, $end_re) = @_;
  702.     $text   = ''   unless (defined $text);
  703.     $end_re = '$'  unless ((defined $end_re) && ($end_re ne ''));
  704.     local($_)  = $text;
  705.     my $result = '';
  706.     my ($seq_cmd, $seq_arg, $end) = ('', '', undef);
  707.     while (($_ ne '') && /([A-Z])<|($end_re)/) {
  708.         $result .= $`;  ## Append text before the match to the result
  709.         $_ = $';        ## Only text after the match remains to be processed
  710.         ## See if we matched an interior sequence or an end-expression
  711.         ($seq_cmd, $end) = ($1, $2);
  712.         last if (defined $end);  ## Saw the end - quit loop here
  713.         ## At this point we have found an interior sequence,
  714.         ## we need to obtain its argument
  715.         push(@{$self->{SEQUENCES}}, $seq_cmd);
  716.         $seq_arg = $self->interpolate($_, '>');
  717.         ## Now process the interior sequence
  718.         $result .= $self->interior_sequence($seq_cmd, $seq_arg);
  719.         pop(@{$self->{SEQUENCES}});
  720.     }
  721.     ## Handle whatever is left if we didnt match the ending regexp
  722.     unless ((defined $end) && ($end_re ne '$')) {
  723.         $result .= $_;
  724.         $_ = '';
  725.     }
  726.     ## Modify the input parameter to consume the text that was
  727.     ## processed so far.
  728.     $_[0] = $_;
  729.     ## Return the processed-text
  730.     return  $result;
  731. }
  732.  
  733. =head2 parse_paragraph($text)
  734.  
  735. This method takes the text of a pod paragraph to be processed and
  736. invokes the appropriate method (one of B<command()>, B<verbatim()>,
  737. or B<textblock()>).
  738.  
  739. This method does I<not> usually need to be overridden by subclasses.
  740.  
  741. =cut
  742.  
  743. sub parse_paragraph {
  744.     my $self = shift;
  745.     local $_ = shift;
  746.     my ($para);
  747.     my ($cmd, $arg, $sep);
  748.     ## Keep track of current paragraph number
  749.     ++$self->{PARAGRAPH}  if ((defined $_)  &&  ($_ ne ''));
  750.     ## Ignore up until next pod directive if we are cutting
  751.     if ($self->{CUTTING}) {
  752.         return  1  unless /^=/o;
  753.         $self->{CUTTING} = 0;
  754.     }
  755.     ## Keep track of current sections and their titles
  756.     my ($level, $title);
  757.     if (/^=((?:sub)*)(?:head(?:ing)?|sec(?:tion)?)(\d*)\s+(.*)\s*$/o) {
  758.         ## This is a section heading command
  759.         ($level, $title) = ($2, $3);
  760.         $level = 1 + (length($1) / 3)  if (($level eq '') || ($1 ne ''));
  761.         ## Reset the current section heading at this level
  762.         $self->{HEADINGS}->[$level - 1] = $title;
  763.         ## Reset subsection headings of this one to empty
  764.         my $i;
  765.         for ($i = $level; $i < $Pod::Parser::MAX_HEAD_LEVEL; ++$i) {
  766.             $self->{HEADINGS}->[$i] = '';
  767.         }
  768.     }
  769.     ## Ignore this block if it isnt in one of the selected sections
  770.     $self->{CUTTING} = 1   unless ($self->want_section());
  771.     return  1  if ($self->{CUTTING});
  772.  
  773.     ## Perform any desired preprocessing
  774.     $para = $self->preprocess_paragraph($_);
  775.     next unless ((defined $para) && ($para ne ""));
  776.     $_ = $para;
  777.     return  1  if ($self->{CUTTING});
  778.  
  779.     ## Look for one of the three types of paragraphs
  780.     if (s/^=//o) {
  781.         ## Looks like a command paragraph
  782.         ($cmd, $sep, $_) = /\s+/o ? ($`, $&, $') : ($_, '', '');
  783.         if ($cmd eq 'cut') {
  784.             $self->{CUTTING} = 1;
  785.         }
  786.         elsif ($cmd eq 'pod') {
  787.             ## This is a pod pragma paragraph
  788.             $self->parse_pragmas($cmd, $_, $sep);
  789.         }
  790.         else {
  791.             ## Some other command
  792.             $self->command($cmd, $_, $sep);
  793.         }
  794.     }
  795.     elsif (/^\s+/o) {
  796.         ## Indented text - must be a verbatim paragraph
  797.         $self->verbatim($_);
  798.     }
  799.     else {
  800.         ## Looks like an ordinary block of text
  801.         $self->textblock($_);
  802.     }
  803.     return  1;
  804. }
  805.  
  806. =head2 parse_from_filehandle($infilehandle, $outfilehandle)
  807.  
  808. This method takes a glob to a filehandle (which is assumed to already be
  809. opened for reading) and reads the entire input stream looking for blocks
  810. (paragraphs) of pod documentation to be processed. For each block of pod
  811. documentation encountered it will call the B<parse_paragraph()> method.
  812.  
  813. If a second argument is given then it should be a filehandle glob where
  814. output should be sent (otherwise the default output filehandle is
  815. C<STDOUT>). If no first argument is given the default input filehandle
  816. C<STDIN> is used.
  817.  
  818. The input filehandle that is currently in use is stored in the member
  819. variable whose key is "INPUT" (e.g. C<$self-E<gt>{INPUT}>).
  820.  
  821. The output filehandle that is currently in use is stored in the member
  822. variable whose key is "OUTPUT" (e.g. C<$self-E<gt>{OUTPUT}>).
  823.  
  824. Input is read line-by-line and assembled into paragraphs (which are
  825. separated by lines containing nothing but whitespace). The current line
  826. number is stored in the member variable whose key is "LINE" (e.g.
  827. C<$self-E<gt>{LINE}>) and the current paragraph number is stored in the
  828. member variable whose key is "PARAGRAPH" (e.g.  C<$self-E<gt>{PARAGRAPH}>).
  829.  
  830. This method does I<not> usually need to be overridden by subclasses.
  831.  
  832. =cut
  833.  
  834. sub parse_from_filehandle {
  835.     my $self = shift;
  836.     my $infilehandle = shift;
  837.     my $outfilehandle = shift;
  838.     local($_);
  839.  
  840.     $infilehandle  = \*STDIN   unless (defined $infilehandle);
  841.     $outfilehandle = \*STDOUT  unless (defined $outfilehandle);
  842.  
  843.     ## Initialize stuff for this input stream
  844.     $self->{INPUT}     = $infilehandle;
  845.     $self->{OUTPUT}    = $outfilehandle;
  846.     $self->{CUTTING}   = 1;   ## Keep track of when we are cutting
  847.     $self->{SEQUENCES} = [];  ## Keep track of nested interior sequences
  848.     ## Initialize section heading titles
  849.     {
  850.         $self->{HEADINGS}   = [];
  851.         my $i;
  852.         for ($i = 0; $i < $Pod::Parser::MAX_HEAD_LEVEL; ++$i) {
  853.             $self->{HEADINGS}->[$i] = '';
  854.         }
  855.     }
  856.  
  857.     $self->begin_input();
  858.  
  859.     my $paragraph = '';
  860.     while (<$infilehandle>) {
  861.         ++$self->{LINE};  ## Keep track of current line number
  862.         $_ = $self->preprocess_line($_);
  863.         next  unless ((defined $_)  &&  ($_ ne ''));
  864.         if (! /^\s*$/o) {
  865.             ## Append this line to the current paragraph
  866.             $paragraph .= $_;
  867.             next;
  868.         }
  869.         ## This line is blank line and ends the current paragraph
  870.         next  if ($paragraph eq '');
  871.         $paragraph .= "\n";
  872.         $self->parse_paragraph($paragraph);
  873.         $paragraph = '';
  874.     }
  875.     ## Dont forget about the last paragraph in the file
  876.     $self->parse_paragraph($paragraph)  unless ($paragraph eq '');
  877.  
  878.     $self->end_input();
  879. }
  880.  
  881. =head2 parse_from_file($filename, $outfile)
  882.  
  883. This method takes a filename and does the following:
  884.  
  885. =over 4
  886.  
  887. =item *
  888.  
  889. opens the input and output files for reading
  890. (creating the appropriate filehandles)
  891.  
  892. =item *
  893.  
  894. invokes the B<parse_from_filehandle()> method passing it the
  895. corresponding input and output filehandles.
  896.  
  897. =item *
  898.  
  899. closes the input and output files.
  900.  
  901. =back
  902.  
  903. If the special input filename "-" or "<&STDIN" is given then the STDIN
  904. filehandle is used for input (and no open or close is performed).  If no
  905. input filename is specified then "-" is implied.  If a reference is
  906. passed instead of a filename then it is assumed to be a glob-style
  907. reference to a filehandle.
  908.  
  909.  
  910. If a second argument is given then it should be the name of the desired
  911. output file.  If the special output filename "-" or ">&STDOUT" is given
  912. then the STDOUT filehandle is used for output (and no open or close is
  913. performed). If the special output filename ">&STDERR" is given then the
  914. STDERR filehandle is used for output (and no open or close is
  915. performed).  If no output filename is specified then "-" is implied.
  916. If a reference is passed instead of a filename then it is assumed to
  917. be a glob-style reference to a filehandle.
  918.  
  919. The name of the input file that is currently being read is stored in the
  920. member variable whose key is "INFILE" (e.g. C<$self-E<gt>{INFILE}>).
  921.  
  922. The name of the output file that is currently being written is stored in
  923. the member variable whose key is "OUTFILE" (e.g.  C<$self-E<gt>{OUTFILE}>).
  924.  
  925. This method does I<not> usually need to be overridden by subclasses.
  926.  
  927. =cut
  928.  
  929. sub parse_from_file {
  930.     my $self = shift;
  931.     my $infile = shift;
  932.     my $outfile = shift;
  933.     my ($in_fh,  $in_fh_name)  = (undef, undef);
  934.     my ($out_fh, $out_fh_name) = (undef, undef);
  935.  
  936.     $infile  = '-'  unless ((defined $infile)  && ($infile ne ''));
  937.     $outfile = '-'  unless ((defined $outfile) && ($outfile ne ''));
  938.  
  939.     if (($infile  eq '-') || ($infile =~ /^<&(STDIN|0)$/o)) {
  940.         $in_fh = \*STDIN;
  941.         $self->{INFILE} = "<standard input>";
  942.     }
  943.     elsif (ref $infile) {
  944.         $in_fh = $infile;
  945.         $self->{INFILE} = ${$infile};;
  946.     }
  947.     else {
  948.         $self->{INFILE} = $in_fh_name = $infile;
  949.         $in_fh_name =~ s/\W/_/g;
  950.         no strict "refs";
  951.         open($in_fh_name, "<$infile") || 
  952.              croak "Can't open $infile for reading: $!\n";
  953.         $in_fh = \*$in_fh_name;
  954.     }
  955.  
  956.     if (($outfile  eq '-') || ($outfile =~ /^>&?(STDOUT|1)$/o)) {
  957.         $out_fh  = \*STDOUT;
  958.         $self->{OUTFILE} = "<standard output>";
  959.     }
  960.     elsif ($outfile =~ /^>&(STDERR|2)$/o) {
  961.         $out_fh  = \*STDERR;
  962.         $self->{OUTFILE} = "<standard error>";
  963.     }
  964.     elsif (ref $outfile) {
  965.         $out_fh = $outfile;
  966.         $self->{OUTFILE} = ${$outfile};;
  967.     }
  968.     else {
  969.         $self->{OUTFILE} = $out_fh_name = $outfile;
  970.         $out_fh_name =~ s/\W/_/g;
  971.         no strict "refs";
  972.         open($out_fh_name, ">$outfile") || 
  973.              croak "Can't open $outfile for writing: $!\n";
  974.         $out_fh = \*$out_fh_name;
  975.     }
  976.  
  977.     $self->parse_from_filehandle($in_fh, $out_fh);
  978.  
  979.     if (defined $in_fh_name) {
  980.         close($in_fh) || croak "Can't close $infile after reading: $!\n";
  981.     }
  982.     if (defined $out_fh_name) {
  983.         close($out_fh) || croak "Can't close $outfile after writing: $!\n";
  984.     }
  985. }
  986.  
  987. ##---------------------------------------------------------------------------
  988.  
  989. =head1  INSTANCE DATA
  990.  
  991. B<Pod::Parser> uses the following data members for each of its
  992. instances (where C<$self> is a reference to such an instance):
  993.  
  994. =head2 $self->{INPUT}
  995.  
  996. The current input filehandle.
  997.  
  998. =head2 $self->{OUTPUT}
  999.  
  1000. The current output filehandle.
  1001.  
  1002. =head2 $self->{INFILE}
  1003.  
  1004. The name of the current input file.
  1005.  
  1006. =head2 $self->{OUTFILE}
  1007.  
  1008. The name of the current output file.
  1009.  
  1010. =head2 $self->{LINE}
  1011.  
  1012. The current line number from the input stream.
  1013.  
  1014. =head2 $self->{PARAGRAPH}
  1015.  
  1016. The current paragraph number from the input stream (which includes input
  1017. paragraphs that are I<not> part of the pod documentation).
  1018.  
  1019. =head2 $self->{HEADINGS}
  1020.  
  1021. A reference to an array of the current section heading titles for each
  1022. heading level (note that the first heading level title is at index 0).
  1023.  
  1024. =head2 $self->{SELECTED}
  1025.  
  1026. A reference to an array of references to arrays. Each subarray is a list
  1027. of anchored regular expressions (preceded by a "!" if the regexp is to be
  1028. negated). The index of the expression in the subarray should correspond
  1029. to the index of the heading title in B<$self-E<gt>{HEADINGS}> that it is
  1030. to be matched against.
  1031.  
  1032. =head2 $self->{CUTTING}
  1033.  
  1034. A boolean-valued scalar which evaluates to true if text from the
  1035. input file is currently being "cut".
  1036.  
  1037. =head2 $self->{SEQUENCES}
  1038.  
  1039. An array reference to the stack of interior sequence commands that are
  1040. currently in the middle of being processed.
  1041.  
  1042. =head1 NOTES
  1043.  
  1044. To create a pod translator to translate pod documentation to some other
  1045. format, you usually only need to create a subclass of B<Pod::Parser>
  1046. which overrides the base class implementation for the following methods:
  1047.  
  1048. =over 4
  1049.  
  1050. =item *
  1051.  
  1052. B<pragma()>
  1053.  
  1054. =item *
  1055.  
  1056. B<command()>
  1057.  
  1058. =item *
  1059.  
  1060. B<verbatim()>
  1061.  
  1062. =item *
  1063.  
  1064. B<textblock()>
  1065.  
  1066. =item *
  1067.  
  1068. B<interior_sequence()>
  1069.  
  1070. =back
  1071.  
  1072. You may also want to implement the B<begin_input()> and B<end_input()>
  1073. methods for your subclass (to perform any needed per-file intialization
  1074. or cleanup).
  1075.  
  1076. If you need to perform any preprocesssing of input before it is parsed
  1077. you may want to implement one or both of the B<preprocess_line()> and/or
  1078. B<preprocess_paragraph()> methods.
  1079.  
  1080. Also, don't forget to make sure your subclass constructor invokes the
  1081. base class' B<initialize()> method.
  1082.  
  1083. Sometimes it may be necessary to make more than one pass over the input
  1084. files. This isn't a problem as long as none of the input files correspond
  1085. to C<STDIN>. You can override either the B<parse_from_filehandle()>
  1086. method or the B<parse_from_file()> method to make the first pass yourself
  1087. to collect all the information you need and then invoke the base class
  1088. method to do the rest of the standard processing.
  1089.  
  1090. Feel free to add any member data fields you need to keep track of things
  1091. like current font, indentation, horizontal or vertical position, or
  1092. whatever else you like.
  1093.  
  1094. For the most part, the B<Pod::Parser> base class should be able to
  1095. do most of the input parsing for you and leave you free to worry about
  1096. how to intepret the commands and translate the result.
  1097.  
  1098. =head1 AUTHOR
  1099.  
  1100. Brad Appleton E<lt>Brad_Appleton-GBDA001@email.mot.comE<gt>
  1101.  
  1102. Based on code for B<Pod::Text> written by
  1103. Tom Christiansen E<lt>tchrist@mox.perl.comE<gt>
  1104.  
  1105. =cut
  1106.  
  1107. 1;
  1108.