| Pod-Tree documentation | Contained in the Pod-Tree distribution. |
new Pod::Treeload_file($file, %options)load_fh($fh, %options)load_string($pod, %options)load_paragraphs(\@pod, %options)loadedget_rootset_root($node)push(@nodes)popwalk(\&sub)has_poddump
Pod::Tree - Create a static syntax tree for a POD
use Pod::Tree;
$tree = new Pod::Tree;
$tree->load_file ( $file, %options)
$tree->load_fh ( $fh , %options);
$tree->load_string ( $pod , %options);
$tree->load_paragraphs(\@pod , %options);
$loaded = $tree->loaded;
$node = $tree->get_root;
$tree->set_root ($node);
$node = $tree->pop;
$tree->push(@nodes);
$tree->walk(\&sub);
$tree->has_pod and ...
print $tree->dump;
Pod::Escapes
Nothing
Pod::Tree parses a POD into a static syntax tree.
Applications walk the tree to recover the structure and content of the POD.
See Pod::Tree::Node for a description of the tree.
new Pod::TreeCreates a new Pod::Tree object.
The syntax tree is initially empty.
load_file($file, %options)Parses a POD and creates a syntax tree for it. $file is the name of a file containing the POD. Returns null iff it can't open $file.
See OPTIONS for a description of %options
load_fh($fh, %options)Parses a POD and creates a syntax tree for it.
$fh is an IO::File object that is open on a file containing the POD.
See OPTIONS for a description of %options
load_string($pod, %options)Parses a POD and creates a syntax tree for it. $pod is a single string containing the POD.
See OPTIONS for a description of %options
load_paragraphs(\@pod, %options)Parses a POD and creates a syntax tree for it. \@pod is a reference to an array of strings. Each string is one paragraph of the POD.
See OPTIONS for a description of %options
loadedReturns true iff one of the load_* methods has been called on $tree.
get_rootReturns the root node of the syntax tree. See Pod::Tree::Node for a description of the syntax tree.
set_root($node)Sets the root of the syntax tree to $node.
push(@nodes)Pushes @nodes onto the end of the top-level list of nodes in $tree.
popPops $node off of the end of the top-level list of nodes in $tree.
walk(\&sub)Walks the syntax tree, depth first. Calls sub once for each node in the tree. The current node is passed as the first argument to sub.
walk descends to the children and siblings of $node iff
sub() returns true.
has_podReturns true iff $tree contains POD paragraphs.
dumpPretty prints the syntax tree.
This will show you how Pod::Tree interpreted your POD.
These options may be passed in the %options hash to the load_* methods.
in_pod => 0in_pod => 1Sets the initial value of in_pod.
When in_pod is false,
the parser ignores all text until the next =command paragraph.
The initial value of in_pod
defaults to false for load_file() and load_fh() calls
and true for load_string() and load_paragraphs() calls.
This is usually what you want, unless you want consistency.
If this isn't what you want,
pass different initial values in the %options hash.
limit => nOnly parse the first n paragraphs in the POD.
load_file($file)Returns null iff it can't open $file.
Currently, Pod::Tree does not provide a complete, exact
representation of its input. For example, it doesn't distingish
between
C<$foo-E<gt>bar>
and
C<< $foo->bar >>
As a result, it is not guaranteed that a file can be
exactly reconstructed from its Pod::Tree representation.
In the documentation of the
L<"sec"> section in this manual page
markup, perlpod has always claimed
(the quotes are optional)
However, there is no way to decide from the syntax alone whether
L<foo>
is a link to the foo man page or
a link to the foo section of this man page.
Pod::Tree parses L<foo> as a link to a section if
foo looks like a section name (e.g. contains whitespace),
and as a link to a man page otherswise.
In practice, this tends to break links to sections.
If you want your section links to work reliably,
write them as L<"foo"> or L</foo>.
perl(1), Pod::Tree::Node, Pod::Tree::HTML
Steven McDougall <swmcd@world.std.com>
Copyright (c) 1999-2009 by Steven McDougall. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
| Pod-Tree documentation | Contained in the Pod-Tree distribution. |
# Copyright (c) 1999-2009 by Steven McDougall. This module is free # software; you can redistribute it and/or modify it under the same # terms as Perl itself. package Pod::Tree::Stream; sub new { my($package, $fh) = @_; my $stream = { fh => $fh, line => '' }; bless $stream, $package } sub get_paragraph { my $stream = shift; my $fh = $stream->{fh}; my $line = $stream->{line}; defined $line or return undef; my(@lines) = ($line); while ($line = $fh->getline) { push @lines, $line; $line =~ /\S/ or last; } while ($line = $fh->getline) { $line =~ /\S/ and last; push @lines, $line; } $stream->{line} = $line; join '', @lines } package Pod::Tree; require Exporter; use strict; use IO::File; use Pod::Tree::Node; use base qw(Exporter); $Pod::Tree::VERSION = '1.17'; sub new { my $class = shift; my $tree = { loaded => 0, paragraphs => [] }; bless $tree, $class } sub load_file { my($tree, $file, %options) = @_; Pod::Tree::Node->set_filename($file); my $fh = new IO::File; $fh->open($file) or return ''; $tree->load_fh($fh, %options); Pod::Tree::Node->set_filename(""); 1 } sub load_fh { my($tree, $fh, %options) = @_; $tree->{in_pod} = 0; $tree->_load_options(%options); my $limit = $tree->{limit}; my $stream = new Pod::Tree::Stream $fh; my $paragraph; my @paragraphs; while ($paragraph = $stream->get_paragraph) { push @paragraphs, $paragraph; $limit and $limit==@paragraphs and last; } $tree->{paragraphs} = \@paragraphs; $tree->_parse; } sub load_string { my($tree, $string, %options) = @_; my @chunks = split /( \n\s*\n | \r\s*\r | \r\n\s*\r\n )/x, $string; my(@paragraphs); while (@chunks) { push @paragraphs, join '', splice @chunks, 0, 2; } $tree->load_paragraphs(\@paragraphs, %options); } sub load_paragraphs { my($tree, $paragraphs, %options) = @_; $tree->{in_pod} = 1; $tree->_load_options(%options); my $limit = $tree->{limit}; my @paragraphs = @$paragraphs; $limit and splice @paragraphs, $limit; $tree->{paragraphs} = \@paragraphs; $tree->_parse; } sub loaded { shift->{'loaded'} } sub _load_options { my($tree, %options) = @_; my($key, $value); while (($key, $value) = each %options) { $tree->{$key} = $value; } } sub _parse { my $tree = shift; $tree->_make_nodes; $tree->_make_for; $tree->_make_sequences; my $root = $tree->{root}; $root->parse_links; $root->unescape; $root->consolidate; $root->make_lists; $tree->{'loaded'} = 1; } sub _add_paragraph { my($tree, $paragraph) = @_; for ($paragraph) { /^=cut/ and do { $tree->{in_pod}=0; last }; $tree->{in_pod} and do { push @{$tree->{paragraphs}}, $paragraph; last }; /^=\w/ and do { $tree->{in_pod}=1; push @{$tree->{paragraphs}}, $paragraph; last }; } } my %Command = map { $_ => 1 } qw(=pod =cut =head1 =head2 =head3 =head4 =over =item =back =for =begin =end); sub _make_nodes { my $tree = shift; my $paragraphs = $tree->{paragraphs}; my $in_pod = $tree->{in_pod}; my @children; for my $paragraph (@$paragraphs) { my($word) = split(/\s/, $paragraph); my $node; if ($in_pod) { if ($paragraph =~ /^\s/) { $node = verbatim Pod::Tree::Node $paragraph; } elsif ($Command{$word}) { $node = command Pod::Tree::Node $paragraph; $in_pod = $word ne '=cut'; } else { $node = ordinary Pod::Tree::Node $paragraph; } } else { if ($Command{$word}) { $node = command Pod::Tree::Node $paragraph; $in_pod = $word ne '=cut'; } else { $node = code Pod::Tree::Node $paragraph; } } push @children, $node; } $tree->{root} = root Pod::Tree::Node \@children; } sub _make_for { my $tree = shift; my $root = $tree->{root}; my $old = $root->get_children; my @new; while (@$old) { my $node = shift @$old; is_c_for $node and $node->force_for; is_c_begin $node and $node->parse_begin($old); push @new, $node; } $root->set_children(\@new); } sub _make_sequences { my $tree = shift; my $root = $tree->{root}; my $nodes = $root->get_children; for my $node (@$nodes) { is_code $node and next; is_verbatim $node and next; is_for $node and next; $node->make_sequences; } } sub dump { my $tree = shift; $tree->{root}->dump } sub get_root { shift->{root} } sub set_root { my($tree, $root) = @_; $tree->{root} = $root; } sub push { my($tree, @nodes) = @_; my $root = $tree->{root}; my $children = $root->get_children; push @$children, @nodes; } sub pop { my $tree = shift; my $root = $tree->get_root; my $children = $root->get_children; pop @$children } sub walk { my($tree, $sub) = @_; my $root = $tree->get_root; _walk($root, $sub); } sub _walk { my $sub = $_[1]; my $descend = &$sub($_[0]); # :TRICKY: sub can modify node $descend or return; my $node = $_[0]; my $children = $node->get_children; for my $child (@$children) { _walk($child, $sub); } my $siblings = $node->get_siblings; for my $sibling (@$siblings) { _walk($sibling, $sub); } } sub has_pod { my $tree = shift; my $root = $tree->get_root; my $children = $root->get_children; scalar grep { $_->get_type ne 'code' } @$children; } 1 __END__