PPI::Node(3)

πŸ’– PPI::Node β€” the manual, but make it make sense πŸ’–

okay bestie, gather round, because this is PPI::Node, from the User Contributed Perl Documentation collection. It's the abstract PPI node class β€” the kind of Element that can hold other Elements inside it. It's giving mom friend energy. It's giving "I contain multitudes" fr fr. 🫢


🌸 INHERITANCE 🌸

PPI::Node
isa PPI::Element

so yeah, it's a child of PPI::Element, no cap. Everything Element can do, Node can do too (we'll get to that).


✨ SYNOPSIS ✨

here's the vibe in code form, bestie:

# Create a typical node (a Document in this case)
my $Node = PPI::Document->new;

# Add an element to the node( in this case, a token )
my $Token = PPI::Token::Word->new('my');
$Node->add_element( $Token );

# Get the elements for the Node
my @elements = $Node->children;

# Find all the barewords within a Node
my $barewords = $Node->find( 'PPI::Token::Word' );

# Find by more complex criteria
my $my_tokens = $Node->find( sub { $_[1]->content eq 'my' } );

# Remove all the whitespace
$Node->prune( 'PPI::Token::Whitespace' );

# Remove by more complex criteria
$Node->prune( sub { $_[1]->content eq 'my' } );

like… look at her go. iconic. πŸ’…


πŸ¦‹ DESCRIPTION πŸ¦‹

The PPI::Node class is an abstract base class for all the Element classes that can contain other elements β€” namely PPI::Document, PPI::Statement, and PPI::Structure. She's the blueprint, not the build. ✨

And listen: on top of everything listed below, all the methods that work on PPI::Element objects also work on PPI::Node objects. Every single one. so don't come for her.


πŸ‘‘ METHODS πŸ‘‘

🌈 scope

The scope method says true if this node is a lexical scope boundary, and false if it's not. that's it, that's the whole method, she's simple and she knows it.

🌈 add_element $Element

The add_element method chucks a PPI::Element object onto the end of a PPI::Node. and here's the tea: because Elements keep links back to their parent, an Element can only ever belong to one Node. monogamy era.

Returns true if the PPI::Element got added. Returns undef if the Element was already inside another Node, or if you didn't even hand it a PPI::Element object. rude of you, honestly.

🌈 elements

The elements method grabs all the child elements structurally within the PPI::Node. and heads up β€” for the PPI::Structure classes, this one DOES include the brace tokens at either end of the structure. yes really. brace tokens are invited to the party.

Returns a list of zero or more PPI::Element objects.

OR, if you call it in scalar context, elements returns a count of how many elements there are. two moods, one method. πŸ’–

🌈 first_element

The first_element method gets the first element structurally within the PPI::Node. same deal as elements β€” yes, it includes the brace tokens for PPI::Structure objects.

Returns a PPI::Element object, or undef if for some reason the PPI::Node is out here containing zero elements. 😭

🌈 last_element

The last_element method gets the last element structurally within the PPI::Node. again, just like elements, this includes the brace tokens for PPI::Structure objects.

Returns a PPI::Element object, or undef if for some reason the PPI::Node has no elements at all. empty node behavior, we don't stan.

🌈 children

The children method gets all the child elements lexically within the PPI::Node. and here's where it differs from elements β€” for the PPI::Structure classes, this one does NOT include the brace tokens at either end of the structure. braces are NOT in this group chat.

Returns a list of zero of more PPI::Element objects.

Alternatively, in scalar context, children returns a count of the number of lexical children. ✨

🌈 schildren

The schildren method is really just a convenience β€” it's the significant-only variation of the normal children method. the "s" is for significant, iykyk.

In list context, returns a list of significant children. In scalar context, returns the number of significant children. πŸ’…

🌈 child $index

The child method gets a child PPI::Element object by its position within the Node.

Returns a PPI::Element object, or undef if there's no child element at that node.

🌈 schild $index

okay so here's the lore: the lexical structure of the Perl language ignores 'insignificant' items like whitespace and comments, but PPI treats those items as valid tokens so it can reassemble the file at any time. Because of that, in many situations you need to find an Element within a Node by index while only counting the lexically significant Elements.

The schild method returns a child Element by index, ignoring the insignificant ones. The index works exactly like a normal array: the first Element is at index 0, and negative indexes mean "from the end." so -1 is last, periodt. πŸŽ€

🌈 contains $Element

The contains method figures out whether some other PPI::Element object is logically "within" a PPI::Node. and for the special case of the brace tokens sitting on either side of a PPI::Structure object β€” they're generally considered "within" the PPI::Structure object, even if they're not actually in the elements for that PPI::Structure. she contains them emotionally and structurally. πŸ’œ

Returns true if the PPI::Element is within us, false if not, or undef on error.

🌈 find $class | &wanted

The find method searches through a code tree for PPI::Element objects that meet a particular condition. scavenger hunt but make it syntax.

To specify the condition, you can hand the method either a simple class name (full or shortened), or a CODE/function reference. like so:

# Find all single quotes in a Document (which is a Node)
$Document->find('PPI::Quote::Single');

# The same thing with a shortened class name
$Document->find('Quote::Single');

# Anything more elaborate, we go with the sub
$Document->find( sub {
      # At the top level of the file...
      $_[1]->parent == $_[0]
      and (
              # ...find all comments and POD
              $_[1]->isa('PPI::Token::Pod')
              or
              $_[1]->isa('PPI::Token::Comment')
      )
} );

The function gets passed two arguments: the top-level PPI::Node you're searching in, and the current PPI::Element that the condition is testing. two args, no more, no notes.

The anonymous function should return one of three values. Returning true means condition match βœ…. Defined-false (0 or '') means no-match ❌. And undef means no-match AND no-descend β€” which is the spicy one.

In that last case, the tree walker will skip over anything below the undef-returning element and move on to the next element at the same level. she's not going down there, she's not doing it.

To halt the entire search and return undef immediately, a condition function should throw an exception (i.e. die). dramatic, but correct. πŸ’€

Heads up bestie: this same wanted logic is used for all methods documented to have a \&wanted parameter, including this one. learn it once, you're set.

The find method returns a reference to an array of PPI::Element objects that match the condition, false (but defined) if no Elements match the condition, or undef if you gave it a bad condition, or an error occurs during the search process.

And if the condition is bad? a warning will be emitted as well. you will be told. πŸ”₯

🌈 find_first $class | &wanted

If the normal find method is like a grep, then find_first is the equivalent of the List::Util first function. same energy, less scrolling.

Give it an element class or a wanted function and it'll search depth-first through a tree until it finds something that matches the condition, returning the first Element it encounters. first come, first served, main character behavior.

See the find method for details on the format of the search condition. ✨

Returns the first PPI::Element object that matches the condition, false if nothing matches the condition, or undef if given an invalid condition, or an error occurs.

🌈 find_any $class | &wanted

The find_any method is a short-circuiting true/false method that behaves like the normal find method, but returns true the moment it finds any Elements matching the search condition. she does not wait. she does not linger. πŸ’…

See the find method for details on the format of the search condition.

Returns true if any Elements that match the condition can be found, false if not, or undef if given an invalid condition, or an error occurs.

🌈 remove_child $Element

If you pass it a PPI::Element object that's a direct child of the Node, the remove_element method will remove the Element intact, along with any of its children. so basically this method is a 'cut' function. whole branch, gone, bye. βœ‚οΈ

If successful, returns the removed element. Otherwise, returns undef.

🌈 replace_child $Element, $Replacement

If successful, returns the replace element. Otherwise, returns undef.

🌈 prune $class | &wanted

The prune method strips PPI::Element objects out of a code tree. the argument is the same as for the find method β€” either a class name, or an anonymous subroutine that returns true/false. Any Element matching the class|wanted gets deleted from the code tree, along with any of its children. glow-down of the century. 🌸

The prune method returns the number of Element objects that matched and were removed, non-recursively. and this number might also be zero, so please bestie, do NOT do a simple true/false test on the return value of prune. zero is a valid answer and it does not mean it failed. It returns undef on error, which you probably should test for. πŸ™ˆ


🧚 TO DO 🧚

  • Move as much as possible to PPI::XS

πŸ’œ SUPPORT πŸ’œ

See the support section in the main module.


πŸŽ€ AUTHOR πŸŽ€

Adam Kennedy <adamk@cpan.org>


Copyright 2001 - 2011 Adam Kennedy.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

The full text of the license can be found in the LICENSE file included with this module.


and that's the whole page, bestie β€” documented by perl v5.42.0, dated 2026-01-17, straight from the User Contributed Perl Documentation shelves. go forth and contain elements. you ate. 🫢✨

πŸ“¦ where this page comes from