Initial Commit
This commit is contained in:
344
database/perl/vendor/lib/PPI/Statement.pm
vendored
Normal file
344
database/perl/vendor/lib/PPI/Statement.pm
vendored
Normal file
@@ -0,0 +1,344 @@
|
||||
package PPI::Statement;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Statement - The base class for Perl statements
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Statement
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
PPI::Statement is the root class for all Perl statements. This includes (from
|
||||
L<perlsyn>) "Declarations", "Simple Statements" and "Compound Statements".
|
||||
|
||||
The class PPI::Statement itself represents a "Simple Statement" as defined
|
||||
in the L<perlsyn> manpage.
|
||||
|
||||
=head1 STATEMENT CLASSES
|
||||
|
||||
Please note that unless documented themselves, these classes are yet to be
|
||||
frozen/finalised. Names may change slightly or be added or removed.
|
||||
|
||||
=head2 L<PPI::Statement::Scheduled>
|
||||
|
||||
This covers all "scheduled" blocks, chunks of code that are executed separately
|
||||
from the main body of the code, at a particular time. This includes all
|
||||
C<BEGIN>, C<CHECK>, C<UNITCHECK>, C<INIT> and C<END> blocks.
|
||||
|
||||
=head2 L<PPI::Statement::Package>
|
||||
|
||||
A package declaration, as defined in L<perlfunc|perlfunc/package>.
|
||||
|
||||
=head2 L<PPI::Statement::Include>
|
||||
|
||||
A statement that loads or unloads another module.
|
||||
|
||||
This includes 'use', 'no', and 'require' statements.
|
||||
|
||||
=head2 L<PPI::Statement::Sub>
|
||||
|
||||
A named subroutine declaration, or forward declaration
|
||||
|
||||
=head2 L<PPI::Statement::Variable>
|
||||
|
||||
A variable declaration statement. This could be either a straight
|
||||
declaration or also be an expression.
|
||||
|
||||
This includes all 'my', 'state', 'local' and 'our' statements.
|
||||
|
||||
=head2 L<PPI::Statement::Compound>
|
||||
|
||||
This covers the whole family of 'compound' statements, as described in
|
||||
L<perlsyn|perlsyn>.
|
||||
|
||||
This includes all statements starting with 'if', 'unless', 'for', 'foreach'
|
||||
and 'while'. Note that this does NOT include 'do', as it is treated
|
||||
differently.
|
||||
|
||||
All compound statements have implicit ends. That is, they do not end with
|
||||
a ';' statement terminator.
|
||||
|
||||
=head2 L<PPI::Statement::Break>
|
||||
|
||||
A statement that breaks out of a structure.
|
||||
|
||||
This includes all of 'redo', 'goto', 'next', 'last' and 'return' statements.
|
||||
|
||||
=head2 L<PPI::Statement::Given>
|
||||
|
||||
The kind of statement introduced in Perl 5.10 that starts with 'given'. This
|
||||
has an implicit end.
|
||||
|
||||
=head2 L<PPI::Statement::When>
|
||||
|
||||
The kind of statement introduced in Perl 5.10 that starts with 'when' or
|
||||
'default'. This also has an implicit end.
|
||||
|
||||
=head2 L<PPI::Statement::Data>
|
||||
|
||||
A special statement which encompasses an entire C<__DATA__> block, including
|
||||
the initial C<'__DATA__'> token itself and the entire contents.
|
||||
|
||||
=head2 L<PPI::Statement::End>
|
||||
|
||||
A special statement which encompasses an entire __END__ block, including
|
||||
the initial '__END__' token itself and the entire contents, including any
|
||||
parsed PPI::Token::POD that may occur in it.
|
||||
|
||||
=head2 L<PPI::Statement::Expression>
|
||||
|
||||
L<PPI::Statement::Expression> is a little more speculative, and is intended
|
||||
to help represent the special rules relating to "expressions" such as in:
|
||||
|
||||
# Several examples of expression statements
|
||||
|
||||
# Boolean conditions
|
||||
if ( expression ) { ... }
|
||||
|
||||
# Lists, such as for arguments
|
||||
Foo->bar( expression )
|
||||
|
||||
=head2 L<PPI::Statement::Null>
|
||||
|
||||
A null statement is a special case for where we encounter two consecutive
|
||||
statement terminators. ( ;; )
|
||||
|
||||
The second terminator is given an entire statement of its own, but one
|
||||
that serves no purpose. Hence a 'null' statement.
|
||||
|
||||
Theoretically, assuming a correct parsing of a perl file, all null statements
|
||||
are superfluous and should be able to be removed without damage to the file.
|
||||
|
||||
But don't do that, in case PPI has parsed something wrong.
|
||||
|
||||
=head2 L<PPI::Statement::UnmatchedBrace>
|
||||
|
||||
Because L<PPI> is intended for use when parsing incorrect or incomplete code,
|
||||
the problem arises of what to do with a stray closing brace.
|
||||
|
||||
Rather than die, it is allocated its own "unmatched brace" statement,
|
||||
which really means "unmatched closing brace". An unmatched open brace at the
|
||||
end of a file would become a structure with no contents and no closing brace.
|
||||
|
||||
If the document loaded is intended to be correct and valid, finding a
|
||||
L<PPI::Statement::UnmatchedBrace> in the PDOM is generally indicative of a
|
||||
misparse.
|
||||
|
||||
=head2 L<PPI::Statement::Unknown>
|
||||
|
||||
This is used temporarily mid-parsing to hold statements for which the lexer
|
||||
cannot yet determine what class it should be, usually because there are
|
||||
insufficient clues, or it might be more than one thing.
|
||||
|
||||
You should never encounter these in a fully parsed PDOM tree.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Statement> itself has very few methods. Most of the time, you will be
|
||||
working with the more generic L<PPI::Element> or L<PPI::Node> methods, or one
|
||||
of the methods that are subclass-specific.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Scalar::Util ();
|
||||
use Params::Util qw{_INSTANCE};
|
||||
use PPI::Node ();
|
||||
use PPI::Exception ();
|
||||
use PPI::Singletons '%_PARENT';
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Node";
|
||||
|
||||
use PPI::Statement::Break ();
|
||||
use PPI::Statement::Compound ();
|
||||
use PPI::Statement::Data ();
|
||||
use PPI::Statement::End ();
|
||||
use PPI::Statement::Expression ();
|
||||
use PPI::Statement::Include ();
|
||||
use PPI::Statement::Null ();
|
||||
use PPI::Statement::Package ();
|
||||
use PPI::Statement::Scheduled ();
|
||||
use PPI::Statement::Sub ();
|
||||
use PPI::Statement::Given ();
|
||||
use PPI::Statement::UnmatchedBrace ();
|
||||
use PPI::Statement::Unknown ();
|
||||
use PPI::Statement::Variable ();
|
||||
use PPI::Statement::When ();
|
||||
|
||||
# "Normal" statements end at a statement terminator ;
|
||||
# Some are not, and need the more rigorous _continues to see
|
||||
# if we are at an implicit statement boundary.
|
||||
sub __LEXER__normal() { 1 }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Constructor
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
if ( ref $class ) {
|
||||
PPI::Exception->throw;
|
||||
}
|
||||
|
||||
# Create the object
|
||||
my $self = bless {
|
||||
children => [],
|
||||
}, $class;
|
||||
|
||||
# If we have been passed what should be an initial token, add it
|
||||
my $token = shift;
|
||||
if ( _INSTANCE($token, 'PPI::Token') ) {
|
||||
# Inlined $self->__add_element(shift);
|
||||
Scalar::Util::weaken(
|
||||
$_PARENT{Scalar::Util::refaddr $token} = $self
|
||||
);
|
||||
push @{$self->{children}}, $token;
|
||||
}
|
||||
|
||||
$self;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 label
|
||||
|
||||
One factor common to most statements is their ability to be labeled.
|
||||
|
||||
The C<label> method returns the label for a statement, if one has been
|
||||
defined, but without the trailing colon. Take the following example
|
||||
|
||||
MYLABEL: while ( 1 .. 10 ) { last MYLABEL if $_ > 5 }
|
||||
|
||||
For the above statement, the C<label> method would return 'MYLABEL'.
|
||||
|
||||
Returns false if the statement does not have a label.
|
||||
|
||||
=cut
|
||||
|
||||
sub label {
|
||||
my $first = shift->schild(1) or return '';
|
||||
$first->isa('PPI::Token::Label')
|
||||
? substr($first, 0, length($first) - 1)
|
||||
: '';
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 specialized
|
||||
|
||||
Answer whether this is a plain statement or one that has more
|
||||
significance.
|
||||
|
||||
Returns true if the statement is a subclass of this one, false
|
||||
otherwise.
|
||||
|
||||
=cut
|
||||
|
||||
# Yes, this is doing precisely what it's intending to prevent
|
||||
# client code from doing. However, since it's here, if the
|
||||
# implementation changes, code outside PPI doesn't care.
|
||||
sub specialized {
|
||||
__PACKAGE__ ne ref $_[0];
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 stable
|
||||
|
||||
Much like the L<PPI::Document> method of the same name, the ->stable
|
||||
method converts a statement to source and back again, to determine if
|
||||
a modified statement is still legal, and won't be interpreted in a
|
||||
different way.
|
||||
|
||||
Returns true if the statement is stable, false if not, or C<undef> on
|
||||
error.
|
||||
|
||||
=cut
|
||||
|
||||
sub stable {
|
||||
die "The ->stable method has not yet been implemented";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Element Methods
|
||||
|
||||
# Is the statement complete.
|
||||
# By default for a statement, we need a semi-colon at the end.
|
||||
sub _complete {
|
||||
my $self = shift;
|
||||
my $semi = $self->schild(-1);
|
||||
return !! (
|
||||
defined $semi
|
||||
and
|
||||
$semi->isa('PPI::Token::Structure')
|
||||
and
|
||||
$semi->content eq ';'
|
||||
);
|
||||
}
|
||||
|
||||
# You can insert either a statement or a non-significant token.
|
||||
sub insert_before {
|
||||
my $self = shift;
|
||||
my $Element = _INSTANCE(shift, 'PPI::Element') or return undef;
|
||||
if ( $Element->isa('PPI::Statement') ) {
|
||||
return $self->__insert_before($Element);
|
||||
} elsif ( $Element->isa('PPI::Token') and ! $Element->significant ) {
|
||||
return $self->__insert_before($Element);
|
||||
}
|
||||
'';
|
||||
}
|
||||
|
||||
# As above, you can insert a statement, or a non-significant token
|
||||
sub insert_after {
|
||||
my $self = shift;
|
||||
my $Element = _INSTANCE(shift, 'PPI::Element') or return undef;
|
||||
if ( $Element->isa('PPI::Statement') ) {
|
||||
return $self->__insert_after($Element);
|
||||
} elsif ( $Element->isa('PPI::Token') and ! $Element->significant ) {
|
||||
return $self->__insert_after($Element);
|
||||
}
|
||||
'';
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 TO DO
|
||||
|
||||
- Complete, freeze and document the remaining classes
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
See the L<support section|PPI/SUPPORT> in the main module.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Adam Kennedy E<lt>adamk@cpan.orgE<gt>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
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.
|
||||
|
||||
=cut
|
||||
Reference in New Issue
Block a user