Initial Commit
This commit is contained in:
301
database/perl/vendor/lib/PPI/Cache.pm
vendored
Normal file
301
database/perl/vendor/lib/PPI/Cache.pm
vendored
Normal file
@@ -0,0 +1,301 @@
|
||||
package PPI::Cache;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Cache - The PPI Document Caching Layer
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
# Set the cache
|
||||
use PPI::Cache path => '/var/cache/ppi-cache';
|
||||
|
||||
# Manually create a cache
|
||||
my $Cache = PPI::Cache->new(
|
||||
path => '/var/cache/perl/class-PPI',
|
||||
readonly => 1,
|
||||
);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<PPI::Cache> provides the default caching functionality for L<PPI>.
|
||||
|
||||
It integrates automatically with L<PPI> itself. Once enabled, any attempt
|
||||
to load a document from the filesystem will be cached via cache.
|
||||
|
||||
Please note that creating a L<PPI::Document> from raw source or something
|
||||
other object will B<not> be cached.
|
||||
|
||||
=head2 Using PPI::Cache
|
||||
|
||||
The most common way of using C<PPI::Cache> is to provide parameters to
|
||||
the C<use> statement at the beginning of your program.
|
||||
|
||||
# Load the class but do not set a cache
|
||||
use PPI::Cache;
|
||||
|
||||
# Use a fairly normal cache location
|
||||
use PPI::Cache path => '/var/cache/ppi-cache';
|
||||
|
||||
Any of the arguments that can be provided to the C<new> constructor can
|
||||
also be provided to C<use>.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Carp ();
|
||||
use File::Spec ();
|
||||
use File::Path ();
|
||||
use Storable 2.17 ();
|
||||
use Digest::MD5 2.35 ();
|
||||
use Params::Util qw{_INSTANCE _SCALAR};
|
||||
use PPI::Document ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
use constant VMS => !! ( $^O eq 'VMS' );
|
||||
|
||||
sub import {
|
||||
my $class = ref $_[0] ? ref shift : shift;
|
||||
return 1 unless @_;
|
||||
|
||||
# Create a cache from the params provided
|
||||
my $cache = $class->new(@_);
|
||||
|
||||
# Make PPI::Document use it
|
||||
unless ( PPI::Document->set_cache( $cache ) ) {
|
||||
Carp::croak("Failed to set cache in PPI::Document");
|
||||
}
|
||||
|
||||
1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Constructor and Accessors
|
||||
|
||||
=pod
|
||||
|
||||
=head2 new param => $value, ...
|
||||
|
||||
The C<new> constructor creates a new standalone cache object.
|
||||
|
||||
It takes a number of parameters to control the cache.
|
||||
|
||||
=over
|
||||
|
||||
=item path
|
||||
|
||||
The C<path> param sets the base directory for the cache. It must already
|
||||
exist, and must be writable.
|
||||
|
||||
=item readonly
|
||||
|
||||
The C<readonly> param is a true/false flag that allows the use of an
|
||||
existing cache by a less-privileged user (such as the web user).
|
||||
|
||||
Existing documents will be retrieved from the cache, but new documents
|
||||
will not be written to it.
|
||||
|
||||
=back
|
||||
|
||||
Returns a new C<PPI::Cache> object, or dies on error.
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my %params = @_;
|
||||
|
||||
# Path should exist and be usable
|
||||
my $path = $params{path}
|
||||
or Carp::croak("Cannot create PPI::Cache, no path provided");
|
||||
unless ( -d $path ) {
|
||||
Carp::croak("Cannot create PPI::Cache, path does not exist");
|
||||
}
|
||||
unless ( -r $path and -x $path ) {
|
||||
Carp::croak("Cannot create PPI::Cache, no read permissions for path");
|
||||
}
|
||||
if ( ! $params{readonly} and ! -w $path ) {
|
||||
Carp::croak("Cannot create PPI::Cache, no write permissions for path");
|
||||
}
|
||||
|
||||
# Create the basic object
|
||||
my $self = bless {
|
||||
path => $path,
|
||||
readonly => !! $params{readonly},
|
||||
}, $class;
|
||||
|
||||
$self;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 path
|
||||
|
||||
The C<path> accessor returns the path on the local filesystem that is the
|
||||
root of the cache.
|
||||
|
||||
=cut
|
||||
|
||||
sub path { $_[0]->{path} }
|
||||
|
||||
=pod
|
||||
|
||||
=head2 readonly
|
||||
|
||||
The C<readonly> accessor returns true if documents should not be written
|
||||
to the cache.
|
||||
|
||||
=cut
|
||||
|
||||
sub readonly { $_[0]->{readonly} }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Cache Methods
|
||||
|
||||
=pod
|
||||
|
||||
=head2 get_document $md5sum | \$source
|
||||
|
||||
The C<get_document> method checks to see if a Document is stored in the
|
||||
cache and retrieves it if so.
|
||||
|
||||
=cut
|
||||
|
||||
sub get_document {
|
||||
my $self = ref $_[0]
|
||||
? shift
|
||||
: Carp::croak('PPI::Cache::get_document called as static method');
|
||||
my $md5hex = $self->_md5hex(shift) or return undef;
|
||||
$self->_load($md5hex);
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 store_document $Document
|
||||
|
||||
The C<store_document> method takes a L<PPI::Document> as argument and
|
||||
explicitly adds it to the cache.
|
||||
|
||||
Returns true if saved, or C<undef> (or dies) on error.
|
||||
|
||||
FIXME (make this return either one or the other, not both)
|
||||
|
||||
=cut
|
||||
|
||||
sub store_document {
|
||||
my $self = shift;
|
||||
my $Document = _INSTANCE(shift, 'PPI::Document') or return undef;
|
||||
|
||||
# Shortcut if we are readonly
|
||||
return 1 if $self->readonly;
|
||||
|
||||
# Find the filename to save to
|
||||
my $md5hex = $Document->hex_id or return undef;
|
||||
|
||||
# Store the file
|
||||
$self->_store( $md5hex, $Document );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Support Methods
|
||||
|
||||
# Store an arbitrary PPI::Document object (using Storable) to a particular
|
||||
# path within the cache filesystem.
|
||||
sub _store {
|
||||
my ($self, $md5hex, $object) = @_;
|
||||
my ($dir, $file) = $self->_paths($md5hex);
|
||||
|
||||
# Save the file
|
||||
File::Path::mkpath( $dir, 0, 0755 ) unless -d $dir;
|
||||
if ( VMS ) {
|
||||
Storable::lock_nstore( $object, $file );
|
||||
} else {
|
||||
Storable::nstore( $object, $file );
|
||||
}
|
||||
}
|
||||
|
||||
# Load an arbitrary object (using Storable) from a particular
|
||||
# path within the cache filesystem.
|
||||
sub _load {
|
||||
my ($self, $md5hex) = @_;
|
||||
my (undef, $file) = $self->_paths($md5hex);
|
||||
|
||||
# Load the file
|
||||
return '' unless -f $file;
|
||||
my $object = VMS
|
||||
? Storable::retrieve( $file )
|
||||
: Storable::lock_retrieve( $file );
|
||||
|
||||
# Security check
|
||||
unless ( _INSTANCE($object, 'PPI::Document') ) {
|
||||
Carp::croak("Security Violation: Object in '$file' is not a PPI::Document");
|
||||
}
|
||||
|
||||
$object;
|
||||
}
|
||||
|
||||
# Convert a md5 to a dir and file name
|
||||
sub _paths {
|
||||
my $self = shift;
|
||||
my $md5hex = lc shift;
|
||||
my $dir = File::Spec->catdir( $self->path, substr($md5hex, 0, 1), substr($md5hex, 0, 2) );
|
||||
my $file = File::Spec->catfile( $dir, $md5hex . '.ppi' );
|
||||
return ($dir, $file);
|
||||
}
|
||||
|
||||
# Check a md5hex param
|
||||
sub _md5hex {
|
||||
my $either = shift;
|
||||
my $it = _SCALAR($_[0])
|
||||
? PPI::Util::md5hex(${$_[0]})
|
||||
: $_[0];
|
||||
return (defined $it and ! ref $it and $it =~ /^[[:xdigit:]]{32}\z/s)
|
||||
? lc $it
|
||||
: undef;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 TO DO
|
||||
|
||||
- Finish the basic functionality
|
||||
|
||||
- Add support for use PPI::Cache auto-setting $PPI::Document::CACHE
|
||||
|
||||
=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 2005 - 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
|
||||
926
database/perl/vendor/lib/PPI/Document.pm
vendored
Normal file
926
database/perl/vendor/lib/PPI/Document.pm
vendored
Normal file
@@ -0,0 +1,926 @@
|
||||
package PPI::Document;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Document - Object representation of a Perl document
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Document
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use PPI;
|
||||
|
||||
# Load a document from a file
|
||||
my $Document = PPI::Document->new('My/Module.pm');
|
||||
|
||||
# Strip out comments
|
||||
$Document->prune('PPI::Token::Comment');
|
||||
|
||||
# Find all the named subroutines
|
||||
my $sub_nodes = $Document->find(
|
||||
sub { $_[1]->isa('PPI::Statement::Sub') and $_[1]->name }
|
||||
);
|
||||
my @sub_names = map { $_->name } @$sub_nodes;
|
||||
|
||||
# Save the file
|
||||
$Document->save('My/Module.pm.stripped');
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The C<PPI::Document> class represents a single Perl "document". A
|
||||
C<PPI::Document> object acts as a root L<PPI::Node>, with some
|
||||
additional methods for loading and saving, and working with
|
||||
the line/column locations of Elements within a file.
|
||||
|
||||
The exemption to its L<PPI::Node>-like behavior this is that a
|
||||
C<PPI::Document> object can NEVER have a parent node, and is always
|
||||
the root node in a tree.
|
||||
|
||||
=head2 Storable Support
|
||||
|
||||
C<PPI::Document> implements the necessary C<STORABLE_freeze> and
|
||||
C<STORABLE_thaw> hooks to provide native support for L<Storable>,
|
||||
if you have it installed.
|
||||
|
||||
However if you want to clone a Document, you are highly recommended
|
||||
to use the C<$Document-E<gt>clone> method rather than Storable's
|
||||
C<dclone> function (although C<dclone> should still work).
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
Most of the things you are likely to want to do with a Document are
|
||||
probably going to involve the methods from L<PPI::Node> class, of which
|
||||
this is a subclass.
|
||||
|
||||
The methods listed here are the remaining few methods that are truly
|
||||
Document-specific.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Carp ();
|
||||
use List::Util 1.33 ();
|
||||
use Params::Util 1.00 qw{_SCALAR0 _ARRAY0 _INSTANCE};
|
||||
use Digest::MD5 ();
|
||||
use PPI::Util ();
|
||||
use PPI ();
|
||||
use PPI::Node ();
|
||||
|
||||
use overload 'bool' => \&PPI::Util::TRUE;
|
||||
use overload '""' => 'content';
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our ( $errstr, @ISA ) = ( "", "PPI::Node" );
|
||||
|
||||
use PPI::Document::Fragment ();
|
||||
|
||||
# Document cache
|
||||
my $CACHE;
|
||||
|
||||
# Convenience constants related to constants
|
||||
use constant LOCATION_LINE => 0;
|
||||
use constant LOCATION_CHARACTER => 1;
|
||||
use constant LOCATION_COLUMN => 2;
|
||||
use constant LOCATION_LOGICAL_LINE => 3;
|
||||
use constant LOCATION_LOGICAL_FILE => 4;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Constructor and Static Methods
|
||||
|
||||
=pod
|
||||
|
||||
=head2 new
|
||||
|
||||
# Simple construction
|
||||
$doc = PPI::Document->new( $filename );
|
||||
$doc = PPI::Document->new( \$source );
|
||||
|
||||
# With the readonly attribute set
|
||||
$doc = PPI::Document->new( $filename,
|
||||
readonly => 1,
|
||||
);
|
||||
|
||||
The C<new> constructor takes as argument a variety of different sources of
|
||||
Perl code, and creates a single cohesive Perl C<PPI::Document>
|
||||
for it.
|
||||
|
||||
If passed a file name as a normal string, it will attempt to load the
|
||||
document from the file.
|
||||
|
||||
If passed a reference to a C<SCALAR>, this is taken to be source code and
|
||||
parsed directly to create the document.
|
||||
|
||||
If passed zero arguments, a "blank" document will be created that contains
|
||||
no content at all.
|
||||
|
||||
In all cases, the document is considered to be "anonymous" and not tied back
|
||||
to where it was created from. Specifically, if you create a PPI::Document from
|
||||
a filename, the document will B<not> remember where it was created from.
|
||||
|
||||
The constructor also takes attribute flags.
|
||||
|
||||
At this time, the only available attribute is the C<readonly> flag.
|
||||
|
||||
Setting C<readonly> to true will allow various systems to provide
|
||||
additional optimisations and caching. Note that because C<readonly> is an
|
||||
optimisation flag, it is off by default and you will need to explicitly
|
||||
enable it.
|
||||
|
||||
Returns a C<PPI::Document> object, or C<undef> if parsing fails.
|
||||
L<PPI::Exception> objects can also be thrown if there are parsing problems.
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
local $_; # An extra one, just in case
|
||||
my $class = ref $_[0] ? ref shift : shift;
|
||||
|
||||
unless ( @_ ) {
|
||||
my $self = $class->SUPER::new;
|
||||
$self->{readonly} = ! 1;
|
||||
$self->{tab_width} = 1;
|
||||
return $self;
|
||||
}
|
||||
|
||||
# Check constructor attributes
|
||||
my $source = shift;
|
||||
my %attr = @_;
|
||||
|
||||
# Check the data source
|
||||
if ( ! defined $source ) {
|
||||
$class->_error("An undefined value was passed to PPI::Document::new");
|
||||
|
||||
} elsif ( ! ref $source ) {
|
||||
# Catch people using the old API
|
||||
if ( $source =~ /(?:\012|\015)/ ) {
|
||||
Carp::croak("API CHANGE: Source code should only be passed to PPI::Document->new as a SCALAR reference");
|
||||
}
|
||||
|
||||
# Save the filename
|
||||
$attr{filename} ||= $source;
|
||||
|
||||
# When loading from a filename, use the caching layer if it exists.
|
||||
if ( $CACHE ) {
|
||||
my $file_contents = PPI::Util::_slurp( $source );
|
||||
|
||||
# Errors returned as plain string
|
||||
return $class->_error($file_contents) if !ref $file_contents;
|
||||
|
||||
# Retrieve the document from the cache
|
||||
my $document = $CACHE->get_document($file_contents);
|
||||
return $class->_setattr( $document, %attr ) if $document;
|
||||
|
||||
$document = PPI::Lexer->lex_source( $$file_contents );
|
||||
if ( $document ) {
|
||||
# Save in the cache
|
||||
$CACHE->store_document( $document );
|
||||
return $class->_setattr( $document, %attr );
|
||||
}
|
||||
} else {
|
||||
my $document = PPI::Lexer->lex_file( $source );
|
||||
return $class->_setattr( $document, %attr ) if $document;
|
||||
}
|
||||
|
||||
} elsif ( _SCALAR0($source) ) {
|
||||
my $document = PPI::Lexer->lex_source( $$source );
|
||||
return $class->_setattr( $document, %attr ) if $document;
|
||||
|
||||
} elsif ( _ARRAY0($source) ) {
|
||||
$source = join '', map { "$_\n" } @$source;
|
||||
my $document = PPI::Lexer->lex_source( $source );
|
||||
return $class->_setattr( $document, %attr ) if $document;
|
||||
|
||||
} else {
|
||||
$class->_error("Unknown object or reference was passed to PPI::Document::new");
|
||||
}
|
||||
|
||||
# Pull and store the error from the lexer
|
||||
my $errstr;
|
||||
if ( _INSTANCE($@, 'PPI::Exception') ) {
|
||||
$errstr = $@->message;
|
||||
} elsif ( $@ ) {
|
||||
$errstr = $@;
|
||||
$errstr =~ s/\sat line\s.+$//;
|
||||
} elsif ( PPI::Lexer->errstr ) {
|
||||
$errstr = PPI::Lexer->errstr;
|
||||
} else {
|
||||
$errstr = "Unknown error parsing Perl document";
|
||||
}
|
||||
PPI::Lexer->_clear;
|
||||
$class->_error( $errstr );
|
||||
}
|
||||
|
||||
sub load {
|
||||
Carp::croak("API CHANGE: File names should now be passed to PPI::Document->new to load a file");
|
||||
}
|
||||
|
||||
sub _setattr {
|
||||
my ($class, $document, %attr) = @_;
|
||||
$document->{readonly} = !! $attr{readonly};
|
||||
$document->{filename} = $attr{filename};
|
||||
return $document;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 set_cache $cache
|
||||
|
||||
As of L<PPI> 1.100, C<PPI::Document> supports parser caching.
|
||||
|
||||
The default cache class L<PPI::Cache> provides a L<Storable>-based
|
||||
caching or the parsed document based on the MD5 hash of the document as
|
||||
a string.
|
||||
|
||||
The static C<set_cache> method is used to set the cache object for
|
||||
C<PPI::Document> to use when loading documents. It takes as argument
|
||||
a L<PPI::Cache> object (or something that C<isa> the same).
|
||||
|
||||
If passed C<undef>, this method will stop using the current cache, if any.
|
||||
|
||||
For more information on caching, see L<PPI::Cache>.
|
||||
|
||||
Returns true on success, or C<undef> if not passed a valid param.
|
||||
|
||||
=cut
|
||||
|
||||
sub set_cache {
|
||||
my $class = ref $_[0] ? ref shift : shift;
|
||||
|
||||
if ( defined $_[0] ) {
|
||||
# Enable the cache
|
||||
my $object = _INSTANCE(shift, 'PPI::Cache') or return undef;
|
||||
$CACHE = $object;
|
||||
} else {
|
||||
# Disable the cache
|
||||
$CACHE = undef;
|
||||
}
|
||||
|
||||
1;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 get_cache
|
||||
|
||||
If a document cache is currently set, the C<get_cache> method will
|
||||
return it.
|
||||
|
||||
Returns a L<PPI::Cache> object, or C<undef> if there is no cache
|
||||
currently set for C<PPI::Document>.
|
||||
|
||||
=cut
|
||||
|
||||
sub get_cache {
|
||||
$CACHE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Document Instance Methods
|
||||
|
||||
=pod
|
||||
|
||||
=head2 filename
|
||||
|
||||
The C<filename> accessor returns the name of the file in which the document
|
||||
is stored.
|
||||
|
||||
=cut
|
||||
|
||||
sub filename {
|
||||
$_[0]->{filename};
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 readonly
|
||||
|
||||
The C<readonly> attribute indicates if the document is intended to be
|
||||
read-only, and will never be modified. This is an advisory flag, that
|
||||
writers of L<PPI>-related systems may or may not use to enable
|
||||
optimisations and caches for your document.
|
||||
|
||||
Returns true if the document is read-only or false if not.
|
||||
|
||||
=cut
|
||||
|
||||
sub readonly {
|
||||
$_[0]->{readonly};
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 tab_width [ $width ]
|
||||
|
||||
In order to handle support for C<location> correctly, C<Documents>
|
||||
need to understand the concept of tabs and tab width. The C<tab_width>
|
||||
method is used to get and set the size of the tab width.
|
||||
|
||||
At the present time, PPI only supports "naive" (width 1) tabs, but we do
|
||||
plan on supporting arbitrary, default and auto-sensing tab widths later.
|
||||
|
||||
Returns the tab width as an integer, or C<die>s if you attempt to set the
|
||||
tab width.
|
||||
|
||||
=cut
|
||||
|
||||
sub tab_width {
|
||||
my $self = shift;
|
||||
return $self->{tab_width} unless @_;
|
||||
$self->{tab_width} = shift;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 save
|
||||
|
||||
$document->save( $file )
|
||||
|
||||
The C<save> method serializes the C<PPI::Document> object and saves the
|
||||
resulting Perl document to a file. Returns C<undef> on failure to open
|
||||
or write to the file.
|
||||
|
||||
=cut
|
||||
|
||||
sub save {
|
||||
my $self = shift;
|
||||
local *FILE;
|
||||
open( FILE, '>', $_[0] ) or return undef;
|
||||
binmode FILE;
|
||||
print FILE $self->serialize or return undef;
|
||||
close FILE or return undef;
|
||||
return 1;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 serialize
|
||||
|
||||
Unlike the C<content> method, which shows only the immediate content
|
||||
within an element, Document objects also have to be able to be written
|
||||
out to a file again.
|
||||
|
||||
When doing this we need to take into account some additional factors.
|
||||
|
||||
Primarily, we need to handle here-docs correctly, so that are written
|
||||
to the file in the expected place.
|
||||
|
||||
The C<serialize> method generates the actual file content for a given
|
||||
Document object. The resulting string can be written straight to a file.
|
||||
|
||||
Returns the serialized document as a string.
|
||||
|
||||
=cut
|
||||
|
||||
sub serialize {
|
||||
my $self = shift;
|
||||
my @tokens = $self->tokens;
|
||||
|
||||
# The here-doc content buffer
|
||||
my $heredoc = '';
|
||||
|
||||
# Start the main loop
|
||||
my $output = '';
|
||||
foreach my $i ( 0 .. $#tokens ) {
|
||||
my $Token = $tokens[$i];
|
||||
|
||||
# Handle normal tokens
|
||||
unless ( $Token->isa('PPI::Token::HereDoc') ) {
|
||||
my $content = $Token->content;
|
||||
|
||||
# Handle the trivial cases
|
||||
unless ( $heredoc ne '' and $content =~ /\n/ ) {
|
||||
$output .= $content;
|
||||
next;
|
||||
}
|
||||
|
||||
# We have pending here-doc content that needs to be
|
||||
# inserted just after the first newline in the content.
|
||||
if ( $content eq "\n" ) {
|
||||
# Shortcut the most common case for speed
|
||||
$output .= $content . $heredoc;
|
||||
} else {
|
||||
# Slower and more general version
|
||||
$content =~ s/\n/\n$heredoc/;
|
||||
$output .= $content;
|
||||
}
|
||||
|
||||
$heredoc = '';
|
||||
next;
|
||||
}
|
||||
|
||||
# This token is a HereDoc.
|
||||
# First, add the token content as normal, which in this
|
||||
# case will definitely not contain a newline.
|
||||
$output .= $Token->content;
|
||||
|
||||
# Now add all of the here-doc content to the heredoc buffer.
|
||||
foreach my $line ( $Token->heredoc ) {
|
||||
$heredoc .= $line;
|
||||
}
|
||||
|
||||
if ( $Token->{_damaged} ) {
|
||||
# Special Case:
|
||||
# There are a couple of warning/bug situations
|
||||
# that can occur when a HereDoc content was read in
|
||||
# from the end of a file that we silently allow.
|
||||
#
|
||||
# When writing back out to the file we have to
|
||||
# auto-repair these problems if we aren't going back
|
||||
# on to the end of the file.
|
||||
|
||||
# When calculating $last_line, ignore the final token if
|
||||
# and only if it has a single newline at the end.
|
||||
my $last_index = $#tokens;
|
||||
if ( $tokens[$last_index]->{content} =~ /^[^\n]*\n$/ ) {
|
||||
$last_index--;
|
||||
}
|
||||
|
||||
# This is a two part test.
|
||||
# First, are we on the last line of the
|
||||
# content part of the file
|
||||
my $last_line = List::Util::none {
|
||||
$tokens[$_] and $tokens[$_]->{content} =~ /\n/
|
||||
} (($i + 1) .. $last_index);
|
||||
if ( ! defined $last_line ) {
|
||||
# Handles the null list case
|
||||
$last_line = 1;
|
||||
}
|
||||
|
||||
# Secondly, are their any more here-docs after us,
|
||||
# (with content or a terminator)
|
||||
my $any_after = List::Util::any {
|
||||
$tokens[$_]->isa('PPI::Token::HereDoc')
|
||||
and (
|
||||
scalar(@{$tokens[$_]->{_heredoc}})
|
||||
or
|
||||
defined $tokens[$_]->{_terminator_line}
|
||||
)
|
||||
} (($i + 1) .. $#tokens);
|
||||
if ( ! defined $any_after ) {
|
||||
# Handles the null list case
|
||||
$any_after = '';
|
||||
}
|
||||
|
||||
# We don't need to repair the last here-doc on the
|
||||
# last line. But we do need to repair anything else.
|
||||
unless ( $last_line and ! $any_after ) {
|
||||
# Add a terminating string if it didn't have one
|
||||
unless ( defined $Token->{_terminator_line} ) {
|
||||
$Token->{_terminator_line} = $Token->{_terminator};
|
||||
}
|
||||
|
||||
# Add a trailing newline to the terminating
|
||||
# string if it didn't have one.
|
||||
unless ( $Token->{_terminator_line} =~ /\n$/ ) {
|
||||
$Token->{_terminator_line} .= "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Now add the termination line to the heredoc buffer
|
||||
if ( defined $Token->{_terminator_line} ) {
|
||||
$heredoc .= $Token->{_terminator_line};
|
||||
}
|
||||
}
|
||||
|
||||
# End of tokens
|
||||
|
||||
if ( $heredoc ne '' ) {
|
||||
# If the file doesn't end in a newline, we need to add one
|
||||
# so that the here-doc content starts on the next line.
|
||||
unless ( $output =~ /\n$/ ) {
|
||||
$output .= "\n";
|
||||
}
|
||||
|
||||
# Now we add the remaining here-doc content
|
||||
# to the end of the file.
|
||||
$output .= $heredoc;
|
||||
}
|
||||
|
||||
$output;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 hex_id
|
||||
|
||||
The C<hex_id> method generates an unique identifier for the Perl document.
|
||||
|
||||
This identifier is basically just the serialized document, with
|
||||
Unix-specific newlines, passed through MD5 to produce a hexadecimal string.
|
||||
|
||||
This identifier is used by a variety of systems (such as L<PPI::Cache>
|
||||
and L<Perl::Metrics>) as a unique key against which to store or cache
|
||||
information about a document (or indeed, to cache the document itself).
|
||||
|
||||
Returns a 32 character hexadecimal string.
|
||||
|
||||
=cut
|
||||
|
||||
sub hex_id {
|
||||
PPI::Util::md5hex($_[0]->serialize);
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 index_locations
|
||||
|
||||
Within a document, all L<PPI::Element> objects can be considered to have a
|
||||
"location", a line/column position within the document when considered as a
|
||||
file. This position is primarily useful for debugging type activities.
|
||||
|
||||
The method for finding the position of a single Element is a bit laborious,
|
||||
and very slow if you need to do it a lot. So the C<index_locations> method
|
||||
will index and save the locations of every Element within the Document in
|
||||
advance, making future calls to <PPI::Element::location> virtually free.
|
||||
|
||||
Please note that this index should always be cleared using C<flush_locations>
|
||||
once you are finished with the locations. If content is added to or removed
|
||||
from the file, these indexed locations will be B<wrong>.
|
||||
|
||||
=cut
|
||||
|
||||
sub index_locations {
|
||||
my $self = shift;
|
||||
my @tokens = $self->tokens;
|
||||
|
||||
# Whenever we hit a heredoc we will need to increment by
|
||||
# the number of lines in its content section when we
|
||||
# encounter the next token with a newline in it.
|
||||
my $heredoc = 0;
|
||||
|
||||
# Find the first Token without a location
|
||||
my ($first, $location) = ();
|
||||
foreach ( 0 .. $#tokens ) {
|
||||
my $Token = $tokens[$_];
|
||||
next if $Token->{_location};
|
||||
|
||||
# Found the first Token without a location
|
||||
# Calculate the new location if needed.
|
||||
if ($_) {
|
||||
$location =
|
||||
$self->_add_location( $location, $tokens[$_ - 1], \$heredoc );
|
||||
} else {
|
||||
my $logical_file =
|
||||
$self->can('filename') ? $self->filename : undef;
|
||||
$location = [ 1, 1, 1, 1, $logical_file ];
|
||||
}
|
||||
$first = $_;
|
||||
last;
|
||||
}
|
||||
|
||||
# Calculate locations for the rest
|
||||
if ( defined $first ) {
|
||||
foreach ( $first .. $#tokens ) {
|
||||
my $Token = $tokens[$_];
|
||||
$Token->{_location} = $location;
|
||||
$location = $self->_add_location( $location, $Token, \$heredoc );
|
||||
|
||||
# Add any here-doc lines to the counter
|
||||
if ( $Token->isa('PPI::Token::HereDoc') ) {
|
||||
$heredoc += $Token->heredoc + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
}
|
||||
|
||||
sub _add_location {
|
||||
my ($self, $start, $Token, $heredoc) = @_;
|
||||
my $content = $Token->{content};
|
||||
|
||||
# Does the content contain any newlines
|
||||
my $newlines =()= $content =~ /\n/g;
|
||||
my ($logical_line, $logical_file) =
|
||||
$self->_logical_line_and_file($start, $Token, $newlines);
|
||||
|
||||
unless ( $newlines ) {
|
||||
# Handle the simple case
|
||||
return [
|
||||
$start->[LOCATION_LINE],
|
||||
$start->[LOCATION_CHARACTER] + length($content),
|
||||
$start->[LOCATION_COLUMN]
|
||||
+ $self->_visual_length(
|
||||
$content,
|
||||
$start->[LOCATION_COLUMN]
|
||||
),
|
||||
$logical_line,
|
||||
$logical_file,
|
||||
];
|
||||
}
|
||||
|
||||
# This is the more complex case where we hit or
|
||||
# span a newline boundary.
|
||||
my $physical_line = $start->[LOCATION_LINE] + $newlines;
|
||||
my $location = [ $physical_line, 1, 1, $logical_line, $logical_file ];
|
||||
if ( $heredoc and $$heredoc ) {
|
||||
$location->[LOCATION_LINE] += $$heredoc;
|
||||
$location->[LOCATION_LOGICAL_LINE] += $$heredoc;
|
||||
$$heredoc = 0;
|
||||
}
|
||||
|
||||
# Does the token have additional characters
|
||||
# after their last newline.
|
||||
if ( $content =~ /\n([^\n]+?)\z/ ) {
|
||||
$location->[LOCATION_CHARACTER] += length($1);
|
||||
$location->[LOCATION_COLUMN] +=
|
||||
$self->_visual_length(
|
||||
$1, $location->[LOCATION_COLUMN],
|
||||
);
|
||||
}
|
||||
|
||||
$location;
|
||||
}
|
||||
|
||||
sub _logical_line_and_file {
|
||||
my ($self, $start, $Token, $newlines) = @_;
|
||||
|
||||
# Regex taken from perlsyn, with the correction that there's no space
|
||||
# required between the line number and the file name.
|
||||
if ($start->[LOCATION_CHARACTER] == 1) {
|
||||
if ( $Token->isa('PPI::Token::Comment') ) {
|
||||
if (
|
||||
$Token->content =~ m<
|
||||
\A
|
||||
\# \s*
|
||||
line \s+
|
||||
(\d+) \s*
|
||||
(?: (\"?) ([^\"]* [^\s\"]) \2 )?
|
||||
\s*
|
||||
\z
|
||||
>xms
|
||||
) {
|
||||
return $1, ($3 || $start->[LOCATION_LOGICAL_FILE]);
|
||||
}
|
||||
}
|
||||
elsif ( $Token->isa('PPI::Token::Pod') ) {
|
||||
my $content = $Token->content;
|
||||
my $line;
|
||||
my $file = $start->[LOCATION_LOGICAL_FILE];
|
||||
my $end_of_directive;
|
||||
while (
|
||||
$content =~ m<
|
||||
^
|
||||
\# \s*?
|
||||
line \s+?
|
||||
(\d+) (?: (?! \n) \s)*
|
||||
(?: (\"?) ([^\"]*? [^\s\"]) \2 )??
|
||||
\s*?
|
||||
$
|
||||
>xmsg
|
||||
) {
|
||||
($line, $file) = ($1, ( $3 || $file ) );
|
||||
$end_of_directive = pos $content;
|
||||
}
|
||||
|
||||
if (defined $line) {
|
||||
pos $content = $end_of_directive;
|
||||
my $post_directive_newlines =()= $content =~ m< \G [^\n]* \n >xmsg;
|
||||
return $line + $post_directive_newlines - 1, $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
$start->[LOCATION_LOGICAL_LINE] + $newlines,
|
||||
$start->[LOCATION_LOGICAL_FILE];
|
||||
}
|
||||
|
||||
sub _visual_length {
|
||||
my ($self, $content, $pos) = @_;
|
||||
|
||||
my $tab_width = $self->tab_width;
|
||||
my ($length, $vis_inc);
|
||||
|
||||
return length $content if $content !~ /\t/;
|
||||
|
||||
# Split the content in tab and non-tab parts and calculate the
|
||||
# "visual increase" of each part.
|
||||
for my $part ( split(/(\t)/, $content) ) {
|
||||
if ($part eq "\t") {
|
||||
$vis_inc = $tab_width - ($pos-1) % $tab_width;
|
||||
}
|
||||
else {
|
||||
$vis_inc = length $part;
|
||||
}
|
||||
$length += $vis_inc;
|
||||
$pos += $vis_inc;
|
||||
}
|
||||
|
||||
$length;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 flush_locations
|
||||
|
||||
When no longer needed, the C<flush_locations> method clears all location data
|
||||
from the tokens.
|
||||
|
||||
=cut
|
||||
|
||||
sub flush_locations {
|
||||
shift->_flush_locations(@_);
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 normalized
|
||||
|
||||
The C<normalized> method is used to generate a "Layer 1"
|
||||
L<PPI::Document::Normalized> object for the current Document.
|
||||
|
||||
A "normalized" Perl Document is an arbitrary structure that removes any
|
||||
irrelevant parts of the document and refactors out variations in style,
|
||||
to attempt to approach something that is closer to the "true meaning"
|
||||
of the Document.
|
||||
|
||||
See L<PPI::Normal> for more information on document normalization and
|
||||
the tasks for which it is useful.
|
||||
|
||||
Returns a L<PPI::Document::Normalized> object, or C<undef> on error.
|
||||
|
||||
=cut
|
||||
|
||||
sub normalized {
|
||||
# The normalization process will utterly destroy and mangle
|
||||
# anything passed to it, so we are going to only give it a
|
||||
# clone of ourselves.
|
||||
PPI::Normal->process( $_[0]->clone );
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head1 complete
|
||||
|
||||
The C<complete> method is used to determine if a document is cleanly
|
||||
structured, all braces are closed, the final statement is
|
||||
fully terminated and all heredocs are fully entered.
|
||||
|
||||
Returns true if the document is complete or false if not.
|
||||
|
||||
=cut
|
||||
|
||||
sub complete {
|
||||
my $self = shift;
|
||||
|
||||
# Every structure has to be complete
|
||||
$self->find_any( sub {
|
||||
$_[1]->isa('PPI::Structure')
|
||||
and
|
||||
! $_[1]->complete
|
||||
} )
|
||||
and return '';
|
||||
|
||||
# Strip anything that isn't a statement off the end
|
||||
my @child = $self->children;
|
||||
while ( @child and not $child[-1]->isa('PPI::Statement') ) {
|
||||
pop @child;
|
||||
}
|
||||
|
||||
# We must have at least one statement
|
||||
return '' unless @child;
|
||||
|
||||
# Check the completeness of the last statement
|
||||
return $child[-1]->_complete;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Node Methods
|
||||
|
||||
# We are a scope boundary
|
||||
### XS -> PPI/XS.xs:_PPI_Document__scope 0.903+
|
||||
sub scope() { 1 }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Element Methods
|
||||
|
||||
sub insert_before {
|
||||
return undef;
|
||||
# die "Cannot insert_before a PPI::Document";
|
||||
}
|
||||
|
||||
sub insert_after {
|
||||
return undef;
|
||||
# die "Cannot insert_after a PPI::Document";
|
||||
}
|
||||
|
||||
sub replace {
|
||||
return undef;
|
||||
# die "Cannot replace a PPI::Document";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Error Handling
|
||||
|
||||
# Set the error message
|
||||
sub _error {
|
||||
$errstr = $_[1];
|
||||
undef;
|
||||
}
|
||||
|
||||
# Clear the error message.
|
||||
# Returns the object as a convenience.
|
||||
sub _clear {
|
||||
$errstr = '';
|
||||
$_[0];
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 errstr
|
||||
|
||||
For error that occur when loading and saving documents, you can use
|
||||
C<errstr>, as either a static or object method, to access the error message.
|
||||
|
||||
If a Document loads or saves without error, C<errstr> will return false.
|
||||
|
||||
=cut
|
||||
|
||||
sub errstr {
|
||||
$errstr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Native Storable Support
|
||||
|
||||
sub STORABLE_freeze {
|
||||
my $self = shift;
|
||||
my $class = ref $self;
|
||||
my %hash = %$self;
|
||||
return ($class, \%hash);
|
||||
}
|
||||
|
||||
sub STORABLE_thaw {
|
||||
my ($self, undef, $class, $hash) = @_;
|
||||
bless $self, $class;
|
||||
foreach ( keys %$hash ) {
|
||||
$self->{$_} = delete $hash->{$_};
|
||||
}
|
||||
$self->__link_children;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 TO DO
|
||||
|
||||
- May need to overload some methods to forcefully prevent Document
|
||||
objects becoming children of another Node.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
See the L<support section|PPI/SUPPORT> in the main module.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Adam Kennedy E<lt>adamk@cpan.orgE<gt>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<PPI>, L<http://ali.as/>
|
||||
|
||||
=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
|
||||
136
database/perl/vendor/lib/PPI/Document/File.pm
vendored
Normal file
136
database/perl/vendor/lib/PPI/Document/File.pm
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
package PPI::Document::File;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Document::File - A Perl Document located in a specific file
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<WARNING: This class is experimental, and may change without notice>
|
||||
|
||||
B<PPI::Document::File> provides a L<PPI::Document> subclass that represents
|
||||
a Perl document stored in a specific named file.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Carp ();
|
||||
use Params::Util qw{_STRING _INSTANCE};
|
||||
use PPI::Document ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = 'PPI::Document';
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Constructor and Accessors
|
||||
|
||||
=pod
|
||||
|
||||
=head2 new
|
||||
|
||||
my $file = PPI::Document::File->new( 'Module.pm' );
|
||||
|
||||
The C<new> constructor works the same as for the regular one, except
|
||||
that the only params allowed is a file name. You cannot create an
|
||||
"anonymous" PPI::Document::File object, not can you create an empty one.
|
||||
|
||||
Returns a new PPI::Document::File object, or C<undef> on error.
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my $filename = _STRING(shift);
|
||||
unless ( defined $filename ) {
|
||||
# Perl::Critic got a complaint about not handling a file
|
||||
# named "0".
|
||||
return $class->_error("Did not provide a file name to load");
|
||||
}
|
||||
|
||||
# Load the Document
|
||||
my $self = $class->SUPER::new( $filename, @_ ) or return undef;
|
||||
|
||||
# Unlike a normal inheritance situation, due to our need to stay
|
||||
# compatible with caching magic, this actually returns a regular
|
||||
# anonymous document. We need to rebless if
|
||||
if ( _INSTANCE($self, 'PPI::Document') ) {
|
||||
bless $self, 'PPI::Document::File';
|
||||
} else {
|
||||
die "PPI::Document::File SUPER call returned an object of the wrong type";
|
||||
}
|
||||
|
||||
$self;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 save
|
||||
|
||||
# Save to the file we were loaded from
|
||||
$file->save;
|
||||
|
||||
# Save a copy to somewhere else
|
||||
$file->save( 'Module2.pm' );
|
||||
|
||||
The C<save> method works similarly to the one in the parent L<PPI::Document>
|
||||
class, saving a copy of the document to a file.
|
||||
|
||||
The difference with this subclass is that if C<save> is not passed any
|
||||
filename, it will save it back to the file it was loaded from.
|
||||
|
||||
Note: When saving to a different file, it is considered to be saving a
|
||||
B<copy> and so the value returned by the C<filename> accessor will stay
|
||||
the same, and not change to the new filename.
|
||||
|
||||
=cut
|
||||
|
||||
sub save {
|
||||
my $self = shift;
|
||||
|
||||
# Save to where?
|
||||
my $filename = shift;
|
||||
unless ( defined $filename ) {
|
||||
$filename = $self->filename;
|
||||
}
|
||||
|
||||
# Hand off to main save method
|
||||
$self->SUPER::save( $filename, @_ );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 TO DO
|
||||
|
||||
- May need to overload some methods to forcefully prevent Document
|
||||
objects becoming children of another Node.
|
||||
|
||||
=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
|
||||
90
database/perl/vendor/lib/PPI/Document/Fragment.pm
vendored
Normal file
90
database/perl/vendor/lib/PPI/Document/Fragment.pm
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
package PPI::Document::Fragment;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Document::Fragment - A fragment of a Perl Document
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
In some situations you might want to work with a fragment of a larger
|
||||
document. C<PPI::Document::Fragment> is a class intended for this purpose.
|
||||
It is functionally almost identical to a normal L<PPI::Document>, except
|
||||
that it is not possible to get line/column positions for the elements
|
||||
within it, and it does not represent a scope.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Document ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = 'PPI::Document';
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Document Methods
|
||||
|
||||
=pod
|
||||
|
||||
=head2 index_locations
|
||||
|
||||
Unlike when called on a PPI::Document object, you should not be attempting
|
||||
to find locations of things within a PPI::Document::Fragment, and thus any
|
||||
call to the C<index_locations> will print a warning and return C<undef>
|
||||
instead of attempting to index the locations of the Elements.
|
||||
|
||||
=cut
|
||||
|
||||
# There's no point indexing a fragment
|
||||
sub index_locations {
|
||||
warn "Useless attempt to index the locations of a document fragment";
|
||||
undef;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Element Methods
|
||||
|
||||
# We are not a scope boundary
|
||||
### XS -> PPI/XS.xs:_PPI_Document_Fragment__scope 0.903+
|
||||
sub scope() { '' }
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 TO DO
|
||||
|
||||
Integrate this into the rest of PPI so it has actual practical uses. The most
|
||||
obvious would be to implement arbitrary cut/copy/paste more easily.
|
||||
|
||||
=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
|
||||
315
database/perl/vendor/lib/PPI/Document/Normalized.pm
vendored
Normal file
315
database/perl/vendor/lib/PPI/Document/Normalized.pm
vendored
Normal file
@@ -0,0 +1,315 @@
|
||||
package PPI::Document::Normalized;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Document::Normalized - A normalized Perl Document
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A C<Normalized Document> object is the result of the normalization process
|
||||
contained in the L<PPI::Normal> class. See the documentation for
|
||||
L<PPI::Normal> for more information.
|
||||
|
||||
The object contains a version stamp and function list for the version
|
||||
of L<PPI::Normal> used to create it, and a processed and delinked
|
||||
L<PPI::Document> object.
|
||||
|
||||
Typically, the Document object will have been mangled by the normalization
|
||||
process in a way that would make it fatal to try to actually DO anything
|
||||
with it.
|
||||
|
||||
Put simply, B<never> use the Document object after normalization.
|
||||
B<YOU HAVE BEEN WARNED!>
|
||||
|
||||
The object is designed the way it is to provide a bias towards false
|
||||
negatives. A comparison between two ::Normalized object will only return
|
||||
true if they were produced by the same version of PPI::Normal, with the
|
||||
same set of normalization functions (in the same order).
|
||||
|
||||
You may get false negatives if you are caching objects across an upgrade.
|
||||
|
||||
Please note that this is done for security purposes, as there are many
|
||||
cases in which low layer normalization is likely to be done as part of
|
||||
a code security process, and false positives could be highly dangerous.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
# For convenience (and since this isn't really a public class), import
|
||||
# the methods we will need from Scalar::Util.
|
||||
use strict;
|
||||
use Scalar::Util qw{refaddr reftype blessed};
|
||||
use Params::Util qw{_INSTANCE _ARRAY};
|
||||
use PPI::Util ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
use overload 'bool' => \&PPI::Util::TRUE;
|
||||
use overload '==' => 'equal';
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Constructor and Accessors
|
||||
|
||||
=pod
|
||||
|
||||
=head2 new
|
||||
|
||||
The C<new> method is intended for use only by the L<PPI::Normal> class,
|
||||
and to get ::Normalized objects, you are highly recommended to use
|
||||
either that module, or the C<normalized> method of the L<PPI::Document>
|
||||
object itself.
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my %args = @_;
|
||||
|
||||
# Check the required params
|
||||
my $Document = _INSTANCE($args{Document}, 'PPI::Document') or return undef;
|
||||
my $version = $args{version};
|
||||
my $functions = _ARRAY($args{functions}) or return undef;
|
||||
|
||||
# Create the object
|
||||
my $self = bless {
|
||||
Document => $Document,
|
||||
version => $version,
|
||||
functions => $functions,
|
||||
}, $class;
|
||||
|
||||
$self;
|
||||
}
|
||||
|
||||
sub _Document { $_[0]->{Document} }
|
||||
|
||||
=pod
|
||||
|
||||
=head2 version
|
||||
|
||||
The C<version> accessor returns the L<PPI::Normal> version used to create
|
||||
the object.
|
||||
|
||||
=cut
|
||||
|
||||
sub version { $_[0]->{version} }
|
||||
|
||||
=pod
|
||||
|
||||
=head2 functions
|
||||
|
||||
The C<functions> accessor returns a reference to an array of the
|
||||
normalization functions (in order) that were called when creating
|
||||
the object.
|
||||
|
||||
=cut
|
||||
|
||||
sub functions { $_[0]->{functions} }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Comparison Methods
|
||||
|
||||
=pod
|
||||
|
||||
=head2 equal $Normalized
|
||||
|
||||
The C<equal> method is the primary comparison method, taking another
|
||||
PPI::Document::Normalized object, and checking for equivalence to it.
|
||||
|
||||
The C<==> operator is also overload to this method, so that you can
|
||||
do something like the following:
|
||||
|
||||
my $first = PPI::Document->load('first.pl');
|
||||
my $second = PPI::Document->load('second.pl');
|
||||
|
||||
if ( $first->normalized == $second->normalized ) {
|
||||
print "The two documents are equivalent";
|
||||
}
|
||||
|
||||
Returns true if the normalized documents are equivalent, false if not,
|
||||
or C<undef> if there is an error.
|
||||
|
||||
=cut
|
||||
|
||||
sub equal {
|
||||
my $self = shift;
|
||||
my $other = _INSTANCE(shift, 'PPI::Document::Normalized') or return undef;
|
||||
|
||||
# Prevent multiple concurrent runs
|
||||
return undef if $self->{processing};
|
||||
|
||||
# Check the version and function list first
|
||||
my $v1 = $self->version || "undef";
|
||||
my $v2 = $other->version || "undef";
|
||||
return '' if $v1 ne $v2;
|
||||
$self->_equal_ARRAY( $self->functions, $other->functions ) or return '';
|
||||
|
||||
# Do the main comparison run
|
||||
$self->{seen} = {};
|
||||
my $rv = $self->_equal_blessed( $self->_Document, $other->_Document );
|
||||
delete $self->{seen};
|
||||
|
||||
$rv;
|
||||
}
|
||||
|
||||
# Check that two objects are matched
|
||||
sub _equal_blessed {
|
||||
my ($self, $this, $that) = @_;
|
||||
my ($bthis, $bthat) = (blessed $this, blessed $that);
|
||||
$bthis and $bthat and $bthis eq $bthat or return '';
|
||||
|
||||
# Check the object as a reference
|
||||
$self->_equal_reference( $this, $that );
|
||||
}
|
||||
|
||||
# Check that two references match their types
|
||||
sub _equal_reference {
|
||||
my ($self, $this, $that) = @_;
|
||||
my ($rthis, $rthat) = (refaddr $this, refaddr $that);
|
||||
$rthis and $rthat or return undef;
|
||||
|
||||
# If we have seen this before, are the pointing
|
||||
# is it the same one we saw in both sides
|
||||
my $seen = $self->{seen}->{$rthis};
|
||||
if ( $seen and $seen ne $rthat ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
# Check the reference types
|
||||
my ($tthis, $tthat) = (reftype $this, reftype $that);
|
||||
$tthis and $tthat and $tthis eq $tthat or return undef;
|
||||
|
||||
# Check the children of the reference type
|
||||
$self->{seen}->{$rthis} = $rthat;
|
||||
my $method = "_equal_$tthat";
|
||||
my $rv = $self->$method( $this, $that );
|
||||
delete $self->{seen}->{$rthis};
|
||||
$rv;
|
||||
}
|
||||
|
||||
# Compare the children of two SCALAR references
|
||||
sub _equal_SCALAR {
|
||||
my ($self, $this, $that) = @_;
|
||||
my ($cthis, $cthat) = ($$this, $$that);
|
||||
return $self->_equal_blessed( $cthis, $cthat ) if blessed $cthis;
|
||||
return $self->_equal_reference( $cthis, $cthat ) if ref $cthis;
|
||||
return (defined $cthat and $cthis eq $cthat) if defined $cthis;
|
||||
! defined $cthat;
|
||||
}
|
||||
|
||||
# For completeness sake, lets just treat REF as a specialist SCALAR case
|
||||
sub _equal_REF { shift->_equal_SCALAR(@_) }
|
||||
|
||||
# Compare the children of two ARRAY references
|
||||
sub _equal_ARRAY {
|
||||
my ($self, $this, $that) = @_;
|
||||
|
||||
# Compare the number of elements
|
||||
scalar(@$this) == scalar(@$that) or return '';
|
||||
|
||||
# Check each element in the array.
|
||||
# Descend depth-first.
|
||||
foreach my $i ( 0 .. scalar(@$this) ) {
|
||||
my ($cthis, $cthat) = ($this->[$i], $that->[$i]);
|
||||
if ( blessed $cthis ) {
|
||||
return '' unless $self->_equal_blessed( $cthis, $cthat );
|
||||
} elsif ( ref $cthis ) {
|
||||
return '' unless $self->_equal_reference( $cthis, $cthat );
|
||||
} elsif ( defined $cthis ) {
|
||||
return '' unless (defined $cthat and $cthis eq $cthat);
|
||||
} else {
|
||||
return '' if defined $cthat;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
}
|
||||
|
||||
# Compare the children of a HASH reference
|
||||
sub _equal_HASH {
|
||||
my ($self, $this, $that) = @_;
|
||||
|
||||
# Compare the number of keys
|
||||
return '' unless scalar(keys %$this) == scalar(keys %$that);
|
||||
|
||||
# Compare each key, descending depth-first.
|
||||
foreach my $k ( keys %$this ) {
|
||||
return '' unless exists $that->{$k};
|
||||
my ($cthis, $cthat) = ($this->{$k}, $that->{$k});
|
||||
if ( blessed $cthis ) {
|
||||
return '' unless $self->_equal_blessed( $cthis, $cthat );
|
||||
} elsif ( ref $cthis ) {
|
||||
return '' unless $self->_equal_reference( $cthis, $cthat );
|
||||
} elsif ( defined $cthis ) {
|
||||
return '' unless (defined $cthat and $cthis eq $cthat);
|
||||
} else {
|
||||
return '' if defined $cthat;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
}
|
||||
|
||||
# We do not support GLOB comparisons
|
||||
sub _equal_GLOB {
|
||||
my ($self, $this, $that) = @_;
|
||||
warn('GLOB comparisons are not supported');
|
||||
'';
|
||||
}
|
||||
|
||||
# We do not support CODE comparisons
|
||||
sub _equal_CODE {
|
||||
my ($self, $this, $that) = @_;
|
||||
refaddr $this == refaddr $that;
|
||||
}
|
||||
|
||||
# We don't support IO comparisons
|
||||
sub _equal_IO {
|
||||
my ($self, $this, $that) = @_;
|
||||
warn('IO comparisons are not supported');
|
||||
'';
|
||||
}
|
||||
|
||||
sub DESTROY {
|
||||
# Take the screw up Document with us
|
||||
if ( $_[0]->{Document} ) {
|
||||
$_[0]->{Document}->DESTROY;
|
||||
delete $_[0]->{Document};
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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 2005 - 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
|
||||
|
||||
309
database/perl/vendor/lib/PPI/Dumper.pm
vendored
Normal file
309
database/perl/vendor/lib/PPI/Dumper.pm
vendored
Normal file
@@ -0,0 +1,309 @@
|
||||
package PPI::Dumper;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Dumper - Dumping of PDOM trees
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
# Load a document
|
||||
my $Module = PPI::Document->new( 'MyModule.pm' );
|
||||
|
||||
# Create the dumper
|
||||
my $Dumper = PPI::Dumper->new( $Module );
|
||||
|
||||
# Dump the document
|
||||
$Dumper->print;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The PDOM trees in PPI are quite complex, and getting a dump of their
|
||||
structure for development and debugging purposes is important.
|
||||
|
||||
This module provides that functionality.
|
||||
|
||||
The process is relatively simple. Create a dumper object with a
|
||||
particular set of options, and then call one of the dump methods to
|
||||
generate the dump content itself.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Params::Util qw{_INSTANCE};
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Constructor
|
||||
|
||||
=pod
|
||||
|
||||
=head2 new $Element, param => value, ...
|
||||
|
||||
The C<new> constructor creates a dumper, and takes as argument a single
|
||||
L<PPI::Element> object of any type to serve as the root of the tree to
|
||||
be dumped, and a number of key-E<gt>value parameters to control the output
|
||||
format of the Dumper. Details of the parameters are listed below.
|
||||
|
||||
Returns a new C<PPI::Dumper> object, or C<undef> if the constructor
|
||||
is not passed a correct L<PPI::Element> root object.
|
||||
|
||||
=over
|
||||
|
||||
=item memaddr
|
||||
|
||||
Should the dumper print the memory addresses of each PDOM element.
|
||||
True/false value, off by default.
|
||||
|
||||
=item indent
|
||||
|
||||
Should the structures being dumped be indented. This value is numeric,
|
||||
with the number representing the number of spaces to use when indenting
|
||||
the dumper output. Set to '2' by default.
|
||||
|
||||
=item class
|
||||
|
||||
Should the dumper print the full class for each element.
|
||||
True/false value, on by default.
|
||||
|
||||
=item content
|
||||
|
||||
Should the dumper show the content of each element. True/false value,
|
||||
on by default.
|
||||
|
||||
=item whitespace
|
||||
|
||||
Should the dumper show whitespace tokens. By not showing the copious
|
||||
numbers of whitespace tokens the structure of the code can often be
|
||||
made much clearer. True/false value, on by default.
|
||||
|
||||
=item comments
|
||||
|
||||
Should the dumper show comment tokens. In situations where you have
|
||||
a lot of comments, the code can often be made clearer by ignoring
|
||||
comment tokens. True/false value, on by default.
|
||||
|
||||
=item locations
|
||||
|
||||
Should the dumper show the location of each token. The values shown are
|
||||
[ line, rowchar, column ]. See L<PPI::Element/"location"> for a description of
|
||||
what these values really are. True/false value, off by default.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my $Element = _INSTANCE(shift, 'PPI::Element') or return undef;
|
||||
|
||||
# Create the object
|
||||
my $self = bless {
|
||||
root => $Element,
|
||||
display => {
|
||||
memaddr => '', # Show the refaddr of the item
|
||||
indent => 2, # Indent the structures
|
||||
class => 1, # Show the object class
|
||||
content => 1, # Show the object contents
|
||||
whitespace => 1, # Show whitespace tokens
|
||||
comments => 1, # Show comment tokens
|
||||
locations => 0, # Show token locations
|
||||
},
|
||||
}, $class;
|
||||
|
||||
# Handle the options
|
||||
my @options = map { lc $_ } @_; # strict hashpairs # https://github.com/adamkennedy/PPI/issues/201
|
||||
my %options = @options;
|
||||
foreach ( keys %{$self->{display}} ) {
|
||||
if ( exists $options{$_} ) {
|
||||
if ( $_ eq 'indent' ) {
|
||||
$self->{display}->{indent} = $options{$_};
|
||||
} else {
|
||||
$self->{display}->{$_} = !! $options{$_};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$self->{indent_string} = join '', (' ' x $self->{display}->{indent});
|
||||
|
||||
$self;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Main Interface Methods
|
||||
|
||||
=pod
|
||||
|
||||
=head2 print
|
||||
|
||||
The C<print> method generates the dump and prints it to STDOUT.
|
||||
|
||||
Returns as for the internal print function.
|
||||
|
||||
=cut
|
||||
|
||||
sub print {
|
||||
CORE::print(shift->string);
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 string
|
||||
|
||||
The C<string> method generates the dump and provides it as a
|
||||
single string.
|
||||
|
||||
Returns a string or undef if there is an error while generating the dump.
|
||||
|
||||
=cut
|
||||
|
||||
sub string {
|
||||
my $array_ref = shift->_dump or return undef;
|
||||
join '', map { "$_\n" } @$array_ref;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 list
|
||||
|
||||
The C<list> method generates the dump and provides it as a raw
|
||||
list, without trailing newlines.
|
||||
|
||||
Returns a list or the null list if there is an error while generating
|
||||
the dump.
|
||||
|
||||
=cut
|
||||
|
||||
sub list {
|
||||
my $array_ref = shift->_dump or return ();
|
||||
@$array_ref;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Generation Support Methods
|
||||
|
||||
sub _dump {
|
||||
my $self = ref $_[0] ? shift : shift->new(shift);
|
||||
my $Element = _INSTANCE($_[0], 'PPI::Element') ? shift : $self->{root};
|
||||
my $indent = shift || '';
|
||||
my $output = shift || [];
|
||||
|
||||
# Print the element if needed
|
||||
my $show = 1;
|
||||
if ( $Element->isa('PPI::Token::Whitespace') ) {
|
||||
$show = 0 unless $self->{display}->{whitespace};
|
||||
} elsif ( $Element->isa('PPI::Token::Comment') ) {
|
||||
$show = 0 unless $self->{display}->{comments};
|
||||
}
|
||||
push @$output, $self->_element_string( $Element, $indent ) if $show;
|
||||
|
||||
# Recurse into our children
|
||||
if ( $Element->isa('PPI::Node') ) {
|
||||
my $child_indent = $indent . $self->{indent_string};
|
||||
foreach my $child ( @{$Element->{children}} ) {
|
||||
$self->_dump( $child, $child_indent, $output );
|
||||
}
|
||||
}
|
||||
|
||||
$output;
|
||||
}
|
||||
|
||||
sub _element_string {
|
||||
my $self = ref $_[0] ? shift : shift->new(shift);
|
||||
my $Element = _INSTANCE($_[0], 'PPI::Element') ? shift : $self->{root};
|
||||
my $indent = shift || '';
|
||||
my $string = '';
|
||||
|
||||
# Add the memory location
|
||||
if ( $self->{display}->{memaddr} ) {
|
||||
$string .= $Element->refaddr . ' ';
|
||||
}
|
||||
|
||||
# Add the location if such exists
|
||||
if ( $self->{display}->{locations} ) {
|
||||
my $loc_string;
|
||||
if ( $Element->isa('PPI::Token') ) {
|
||||
my $location = $Element->location;
|
||||
if ($location) {
|
||||
$loc_string = sprintf("[ % 4d, % 3d, % 3d ] ", @$location);
|
||||
}
|
||||
}
|
||||
# Output location or pad with 20 spaces
|
||||
$string .= $loc_string || " " x 20;
|
||||
}
|
||||
|
||||
# Add the indent
|
||||
if ( $self->{display}->{indent} ) {
|
||||
$string .= $indent;
|
||||
}
|
||||
|
||||
# Add the class name
|
||||
if ( $self->{display}->{class} ) {
|
||||
$string .= ref $Element;
|
||||
}
|
||||
|
||||
if ( $Element->isa('PPI::Token') ) {
|
||||
# Add the content
|
||||
if ( $self->{display}->{content} ) {
|
||||
my $content = $Element->content;
|
||||
$content =~ s/\n/\\n/g;
|
||||
$content =~ s/\t/\\t/g;
|
||||
$content =~ s/\f/\\f/g;
|
||||
$string .= " \t'$content'";
|
||||
}
|
||||
|
||||
} elsif ( $Element->isa('PPI::Structure') ) {
|
||||
# Add the content
|
||||
if ( $self->{display}->{content} ) {
|
||||
my $start = $Element->start
|
||||
? $Element->start->content
|
||||
: '???';
|
||||
my $finish = $Element->finish
|
||||
? $Element->finish->content
|
||||
: '???';
|
||||
$string .= " \t$start ... $finish";
|
||||
}
|
||||
}
|
||||
|
||||
$string;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
889
database/perl/vendor/lib/PPI/Element.pm
vendored
Normal file
889
database/perl/vendor/lib/PPI/Element.pm
vendored
Normal file
@@ -0,0 +1,889 @@
|
||||
package PPI::Element;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Element - The abstract Element class, a base for all source objects
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Element is the root of the PDOM tree
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The abstract C<PPI::Element> serves as a base class for all source-related
|
||||
objects, from a single whitespace token to an entire document. It provides
|
||||
a basic set of methods to provide a common interface and basic
|
||||
implementations.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Clone 0.30 ();
|
||||
use Scalar::Util qw{refaddr};
|
||||
use Params::Util qw{_INSTANCE _ARRAY};
|
||||
use List::Util ();
|
||||
use PPI::Util ();
|
||||
use PPI::Node ();
|
||||
use PPI::Singletons '%_PARENT';
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our $errstr = "";
|
||||
|
||||
use overload 'bool' => \&PPI::Util::TRUE;
|
||||
use overload '""' => 'content';
|
||||
use overload '==' => '__equals';
|
||||
use overload '!=' => '__nequals';
|
||||
use overload 'eq' => '__eq';
|
||||
use overload 'ne' => '__ne';
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# General Properties
|
||||
|
||||
=pod
|
||||
|
||||
=head2 significant
|
||||
|
||||
Because we treat whitespace and other non-code items as Tokens (in order to
|
||||
be able to "round trip" the L<PPI::Document> back to a file) the
|
||||
C<significant> method allows us to distinguish between tokens that form a
|
||||
part of the code, and tokens that aren't significant, such as whitespace,
|
||||
POD, or the portion of a file after (and including) the C<__END__> token.
|
||||
|
||||
Returns true if the Element is significant, or false it not.
|
||||
|
||||
=cut
|
||||
|
||||
### XS -> PPI/XS.xs:_PPI_Element__significant 0.845+
|
||||
sub significant() { 1 }
|
||||
|
||||
=pod
|
||||
|
||||
=head2 class
|
||||
|
||||
The C<class> method is provided as a convenience, and really does nothing
|
||||
more than returning C<ref($self)>. However, some people have found that
|
||||
they appreciate the laziness of C<$Foo-E<gt>class eq 'whatever'>, so I
|
||||
have caved to popular demand and included it.
|
||||
|
||||
Returns the class of the Element as a string
|
||||
|
||||
=cut
|
||||
|
||||
sub class { ref($_[0]) }
|
||||
|
||||
=pod
|
||||
|
||||
=head2 tokens
|
||||
|
||||
The C<tokens> method returns a list of L<PPI::Token> objects for the
|
||||
Element, essentially getting back that part of the document as if it had
|
||||
not been lexed.
|
||||
|
||||
This also means there are no Statements and no Structures in the list,
|
||||
just the Token classes.
|
||||
|
||||
=cut
|
||||
|
||||
sub tokens { $_[0] }
|
||||
|
||||
=pod
|
||||
|
||||
=head2 content
|
||||
|
||||
For B<any> C<PPI::Element>, the C<content> method will reconstitute the
|
||||
base code for it as a single string. This method is also the method used
|
||||
for overloading stringification. When an Element is used in a double-quoted
|
||||
string for example, this is the method that is called.
|
||||
|
||||
B<WARNING:>
|
||||
|
||||
You should be aware that because of the way that here-docs are handled, any
|
||||
here-doc content is not included in C<content>, and as such you should
|
||||
B<not> eval or execute the result if it contains any L<PPI::Token::HereDoc>.
|
||||
|
||||
The L<PPI::Document> method C<serialize> should be used to stringify a PDOM
|
||||
document into something that can be executed as expected.
|
||||
|
||||
Returns the basic code as a string (excluding here-doc content).
|
||||
|
||||
=cut
|
||||
|
||||
### XS -> PPI/XS.xs:_PPI_Element__content 0.900+
|
||||
sub content() { '' }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Navigation Methods
|
||||
|
||||
=pod
|
||||
|
||||
=head2 parent
|
||||
|
||||
Elements themselves are not intended to contain other Elements, that is
|
||||
left to the L<PPI::Node> abstract class, a subclass of C<PPI::Element>.
|
||||
However, all Elements can be contained B<within> a parent Node.
|
||||
|
||||
If an Element is within a parent Node, the C<parent> method returns the
|
||||
Node.
|
||||
|
||||
=cut
|
||||
|
||||
sub parent { $_PARENT{refaddr $_[0]} }
|
||||
|
||||
=pod
|
||||
|
||||
=head2 descendant_of $element
|
||||
|
||||
Answers whether a C<PPI::Element> is contained within another one.
|
||||
|
||||
C<PPI::Element>s are considered to be descendants of themselves.
|
||||
|
||||
=cut
|
||||
|
||||
sub descendant_of {
|
||||
my $cursor = shift;
|
||||
my $parent = shift or return undef;
|
||||
while ( refaddr $cursor != refaddr $parent ) {
|
||||
$cursor = $_PARENT{refaddr $cursor} or return '';
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 ancestor_of $element
|
||||
|
||||
Answers whether a C<PPI::Element> is contains another one.
|
||||
|
||||
C<PPI::Element>s are considered to be ancestors of themselves.
|
||||
|
||||
=cut
|
||||
|
||||
sub ancestor_of {
|
||||
my $self = shift;
|
||||
my $cursor = shift or return undef;
|
||||
while ( refaddr $cursor != refaddr $self ) {
|
||||
$cursor = $_PARENT{refaddr $cursor} or return '';
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 statement
|
||||
|
||||
For a C<PPI::Element> that is contained (at some depth) within a
|
||||
L<PPI::Statement>, the C<statement> method will return the first parent
|
||||
Statement object lexically 'above' the Element.
|
||||
|
||||
Returns a L<PPI::Statement> object, which may be the same Element if the
|
||||
Element is itself a L<PPI::Statement> object.
|
||||
|
||||
Returns false if the Element is not within a Statement and is not itself
|
||||
a Statement.
|
||||
|
||||
=cut
|
||||
|
||||
sub statement {
|
||||
my $cursor = shift;
|
||||
while ( ! _INSTANCE($cursor, 'PPI::Statement') ) {
|
||||
$cursor = $_PARENT{refaddr $cursor} or return '';
|
||||
}
|
||||
$cursor;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 top
|
||||
|
||||
For a C<PPI::Element> that is contained within a PDOM tree, the C<top> method
|
||||
will return the top-level Node in the tree. Most of the time this should be
|
||||
a L<PPI::Document> object, however this will not always be so. For example,
|
||||
if a subroutine has been removed from its Document, to be moved to another
|
||||
Document.
|
||||
|
||||
Returns the top-most PDOM object, which may be the same Element, if it is
|
||||
not within any parent PDOM object.
|
||||
|
||||
=cut
|
||||
|
||||
sub top {
|
||||
my $cursor = shift;
|
||||
while ( my $parent = $_PARENT{refaddr $cursor} ) {
|
||||
$cursor = $parent;
|
||||
}
|
||||
$cursor;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 document
|
||||
|
||||
For an Element that is contained within a L<PPI::Document> object,
|
||||
the C<document> method will return the top-level Document for the Element.
|
||||
|
||||
Returns the L<PPI::Document> for this Element, or false if the Element is not
|
||||
contained within a Document.
|
||||
|
||||
=cut
|
||||
|
||||
sub document {
|
||||
my $top = shift->top;
|
||||
_INSTANCE($top, 'PPI::Document') and $top;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 next_sibling
|
||||
|
||||
All L<PPI::Node> objects (specifically, our parent Node) contain a number of
|
||||
C<PPI::Element> objects. The C<next_sibling> method returns the C<PPI::Element>
|
||||
immediately after the current one, or false if there is no next sibling.
|
||||
|
||||
=cut
|
||||
|
||||
sub next_sibling {
|
||||
my $self = shift;
|
||||
my $parent = $_PARENT{refaddr $self} or return '';
|
||||
my $key = refaddr $self;
|
||||
my $elements = $parent->{children};
|
||||
my $position = List::Util::first {
|
||||
refaddr $elements->[$_] == $key
|
||||
} 0..$#$elements;
|
||||
$elements->[$position + 1] || '';
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 snext_sibling
|
||||
|
||||
As per the other 's' methods, the C<snext_sibling> method returns the next
|
||||
B<significant> sibling of the C<PPI::Element> object.
|
||||
|
||||
Returns a C<PPI::Element> object, or false if there is no 'next' significant
|
||||
sibling.
|
||||
|
||||
=cut
|
||||
|
||||
sub snext_sibling {
|
||||
my $self = shift;
|
||||
my $parent = $_PARENT{refaddr $self} or return '';
|
||||
my $key = refaddr $self;
|
||||
my $elements = $parent->{children};
|
||||
my $position = List::Util::first {
|
||||
refaddr $elements->[$_] == $key
|
||||
} 0..$#$elements;
|
||||
while ( defined(my $it = $elements->[++$position]) ) {
|
||||
return $it if $it->significant;
|
||||
}
|
||||
'';
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 previous_sibling
|
||||
|
||||
All L<PPI::Node> objects (specifically, our parent Node) contain a number of
|
||||
C<PPI::Element> objects. The C<previous_sibling> method returns the Element
|
||||
immediately before the current one, or false if there is no 'previous'
|
||||
C<PPI::Element> object.
|
||||
|
||||
=cut
|
||||
|
||||
sub previous_sibling {
|
||||
my $self = shift;
|
||||
my $parent = $_PARENT{refaddr $self} or return '';
|
||||
my $key = refaddr $self;
|
||||
my $elements = $parent->{children};
|
||||
my $position = List::Util::first {
|
||||
refaddr $elements->[$_] == $key
|
||||
} 0..$#$elements;
|
||||
$position and $elements->[$position - 1] or '';
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 sprevious_sibling
|
||||
|
||||
As per the other 's' methods, the C<sprevious_sibling> method returns
|
||||
the previous B<significant> sibling of the C<PPI::Element> object.
|
||||
|
||||
Returns a C<PPI::Element> object, or false if there is no 'previous' significant
|
||||
sibling.
|
||||
|
||||
=cut
|
||||
|
||||
sub sprevious_sibling {
|
||||
my $self = shift;
|
||||
my $parent = $_PARENT{refaddr $self} or return '';
|
||||
my $key = refaddr $self;
|
||||
my $elements = $parent->{children};
|
||||
my $position = List::Util::first {
|
||||
refaddr $elements->[$_] == $key
|
||||
} 0..$#$elements;
|
||||
while ( $position-- and defined(my $it = $elements->[$position]) ) {
|
||||
return $it if $it->significant;
|
||||
}
|
||||
'';
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 first_token
|
||||
|
||||
As a support method for higher-order algorithms that deal specifically with
|
||||
tokens and actual Perl content, the C<first_token> method finds the first
|
||||
PPI::Token object within or equal to this one.
|
||||
|
||||
That is, if called on a L<PPI::Node> subclass, it will descend until it
|
||||
finds a L<PPI::Token>. If called on a L<PPI::Token> object, it will return
|
||||
the same object.
|
||||
|
||||
Returns a L<PPI::Token> object, or dies on error (which should be extremely
|
||||
rare and only occur if an illegal empty L<PPI::Statement> exists below the
|
||||
current Element somewhere.)
|
||||
|
||||
=cut
|
||||
|
||||
sub first_token {
|
||||
my $cursor = shift;
|
||||
while ( $cursor->isa('PPI::Node') ) {
|
||||
$cursor = $cursor->first_element
|
||||
or die "Found empty PPI::Node while getting first token";
|
||||
}
|
||||
$cursor;
|
||||
}
|
||||
|
||||
|
||||
=pod
|
||||
|
||||
=head2 last_token
|
||||
|
||||
As a support method for higher-order algorithms that deal specifically with
|
||||
tokens and actual Perl content, the C<last_token> method finds the last
|
||||
PPI::Token object within or equal to this one.
|
||||
|
||||
That is, if called on a L<PPI::Node> subclass, it will descend until it
|
||||
finds a L<PPI::Token>. If called on a L<PPI::Token> object, it will return
|
||||
the itself.
|
||||
|
||||
Returns a L<PPI::Token> object, or dies on error (which should be extremely
|
||||
rare and only occur if an illegal empty L<PPI::Statement> exists below the
|
||||
current Element somewhere.)
|
||||
|
||||
=cut
|
||||
|
||||
sub last_token {
|
||||
my $cursor = shift;
|
||||
while ( $cursor->isa('PPI::Node') ) {
|
||||
$cursor = $cursor->last_element
|
||||
or die "Found empty PPI::Node while getting first token";
|
||||
}
|
||||
$cursor;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 next_token
|
||||
|
||||
As a support method for higher-order algorithms that deal specifically with
|
||||
tokens and actual Perl content, the C<next_token> method finds the
|
||||
L<PPI::Token> object that is immediately after the current Element, even if
|
||||
it is not within the same parent L<PPI::Node> as the one for which the
|
||||
method is being called.
|
||||
|
||||
Note that this is B<not> defined as a L<PPI::Token>-specific method,
|
||||
because it can be useful to find the next token that is after, say, a
|
||||
L<PPI::Statement>, although obviously it would be useless to want the
|
||||
next token after a L<PPI::Document>.
|
||||
|
||||
Returns a L<PPI::Token> object, or false if there are no more tokens after
|
||||
the Element.
|
||||
|
||||
=cut
|
||||
|
||||
sub next_token {
|
||||
my $cursor = shift;
|
||||
|
||||
# Find the next element, going upwards as needed
|
||||
while ( 1 ) {
|
||||
my $element = $cursor->next_sibling;
|
||||
if ( $element ) {
|
||||
return $element if $element->isa('PPI::Token');
|
||||
return $element->first_token;
|
||||
}
|
||||
$cursor = $cursor->parent or return '';
|
||||
if ( $cursor->isa('PPI::Structure') and $cursor->finish ) {
|
||||
return $cursor->finish;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 previous_token
|
||||
|
||||
As a support method for higher-order algorithms that deal specifically with
|
||||
tokens and actual Perl content, the C<previous_token> method finds the
|
||||
L<PPI::Token> object that is immediately before the current Element, even
|
||||
if it is not within the same parent L<PPI::Node> as this one.
|
||||
|
||||
Note that this is not defined as a L<PPI::Token>-only method, because it can
|
||||
be useful to find the token is before, say, a L<PPI::Statement>, although
|
||||
obviously it would be useless to want the next token before a
|
||||
L<PPI::Document>.
|
||||
|
||||
Returns a L<PPI::Token> object, or false if there are no more tokens before
|
||||
the C<Element>.
|
||||
|
||||
=cut
|
||||
|
||||
sub previous_token {
|
||||
my $cursor = shift;
|
||||
|
||||
# Find the previous element, going upwards as needed
|
||||
while ( 1 ) {
|
||||
my $element = $cursor->previous_sibling;
|
||||
if ( $element ) {
|
||||
return $element if $element->isa('PPI::Token');
|
||||
return $element->last_token;
|
||||
}
|
||||
$cursor = $cursor->parent or return '';
|
||||
if ( $cursor->isa('PPI::Structure') and $cursor->start ) {
|
||||
return $cursor->start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Manipulation
|
||||
|
||||
=pod
|
||||
|
||||
=head2 clone
|
||||
|
||||
As per the L<Clone> module, the C<clone> method makes a perfect copy of
|
||||
an Element object. In the generic case, the implementation is done using
|
||||
the L<Clone> module's mechanism itself. In higher-order cases, such as for
|
||||
Nodes, there is more work involved to keep the parent-child links intact.
|
||||
|
||||
=cut
|
||||
|
||||
sub clone {
|
||||
Clone::clone(shift);
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 insert_before @Elements
|
||||
|
||||
The C<insert_before> method allows you to insert lexical perl content, in
|
||||
the form of C<PPI::Element> objects, before the calling C<Element>. You
|
||||
need to be very careful when modifying perl code, as it's easy to break
|
||||
things.
|
||||
|
||||
In its initial incarnation, this method allows you to insert a single
|
||||
Element, and will perform some basic checking to prevent you inserting
|
||||
something that would be structurally wrong (in PDOM terms).
|
||||
|
||||
In future, this method may be enhanced to allow the insertion of multiple
|
||||
Elements, inline-parsed code strings or L<PPI::Document::Fragment> objects.
|
||||
|
||||
Returns true if the Element was inserted, false if it can not be inserted,
|
||||
or C<undef> if you do not provide a C<PPI::Element> object as a parameter.
|
||||
|
||||
=cut
|
||||
|
||||
sub __insert_before {
|
||||
my $self = shift;
|
||||
$self->parent->__insert_before_child( $self, @_ );
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 insert_after @Elements
|
||||
|
||||
The C<insert_after> method allows you to insert lexical perl content, in
|
||||
the form of C<PPI::Element> objects, after the calling C<Element>. You need
|
||||
to be very careful when modifying perl code, as it's easy to break things.
|
||||
|
||||
In its initial incarnation, this method allows you to insert a single
|
||||
Element, and will perform some basic checking to prevent you inserting
|
||||
something that would be structurally wrong (in PDOM terms).
|
||||
|
||||
In future, this method may be enhanced to allow the insertion of multiple
|
||||
Elements, inline-parsed code strings or L<PPI::Document::Fragment> objects.
|
||||
|
||||
Returns true if the Element was inserted, false if it can not be inserted,
|
||||
or C<undef> if you do not provide a C<PPI::Element> object as a parameter.
|
||||
|
||||
=cut
|
||||
|
||||
sub __insert_after {
|
||||
my $self = shift;
|
||||
$self->parent->__insert_after_child( $self, @_ );
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 remove
|
||||
|
||||
For a given C<PPI::Element>, the C<remove> method will remove it from its
|
||||
parent B<intact>, along with all of its children.
|
||||
|
||||
Returns the C<Element> itself as a convenience, or C<undef> if an error
|
||||
occurs while trying to remove the C<Element>.
|
||||
|
||||
=cut
|
||||
|
||||
sub remove {
|
||||
my $self = shift;
|
||||
my $parent = $self->parent or return $self;
|
||||
$parent->remove_child( $self );
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 delete
|
||||
|
||||
For a given C<PPI::Element>, the C<delete> method will remove it from its
|
||||
parent, immediately deleting the C<Element> and all of its children (if it
|
||||
has any).
|
||||
|
||||
Returns true if the C<Element> was successfully deleted, or C<undef> if
|
||||
an error occurs while trying to remove the C<Element>.
|
||||
|
||||
=cut
|
||||
|
||||
sub delete {
|
||||
$_[0]->remove or return undef;
|
||||
$_[0]->DESTROY;
|
||||
1;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 replace $Element
|
||||
|
||||
Although some higher level class support more exotic forms of replace,
|
||||
at the basic level the C<replace> method takes a single C<Element> as
|
||||
an argument and replaces the current C<Element> with it.
|
||||
|
||||
To prevent accidental damage to code, in this initial implementation the
|
||||
replacement element B<must> be of the same class (or a subclass) as the
|
||||
one being replaced.
|
||||
|
||||
=cut
|
||||
|
||||
sub replace {
|
||||
my $self = ref $_[0] ? shift : return undef;
|
||||
_INSTANCE(shift, ref $self) or return undef;
|
||||
die "The ->replace method has not yet been implemented";
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 location
|
||||
|
||||
If the Element exists within a L<PPI::Document> that has
|
||||
indexed the Element locations using C<PPI::Document::index_locations>, the
|
||||
C<location> method will return the location of the first character of the
|
||||
Element within the Document.
|
||||
|
||||
Returns the location as a reference to a five-element array in the form C<[
|
||||
$line, $rowchar, $col, $logical_line, $logical_file_name ]>. The values are in
|
||||
a human format, with the first character of the file located at C<[ 1, 1, 1, ?,
|
||||
'something' ]>.
|
||||
|
||||
The second and third numbers are similar, except that the second is the
|
||||
literal horizontal character, and the third is the visual column, taking
|
||||
into account tabbing (see L<PPI::Document/"tab_width [ $width ]">).
|
||||
|
||||
The fourth number is the line number, taking into account any C<#line>
|
||||
directives. The fifth element is the name of the file that the element was
|
||||
found in, if available, taking into account any C<#line> directives.
|
||||
|
||||
Returns C<undef> on error, or if the L<PPI::Document> object has not been
|
||||
indexed.
|
||||
|
||||
=cut
|
||||
|
||||
sub location {
|
||||
my $self = shift;
|
||||
|
||||
$self->_ensure_location_present or return undef;
|
||||
|
||||
# Return a copy, not the original
|
||||
return [ @{$self->{_location}} ];
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 line_number
|
||||
|
||||
If the Element exists within a L<PPI::Document> that has indexed the Element
|
||||
locations using C<PPI::Document::index_locations>, the C<line_number> method
|
||||
will return the line number of the first character of the Element within the
|
||||
Document.
|
||||
|
||||
Returns C<undef> on error, or if the L<PPI::Document> object has not been
|
||||
indexed.
|
||||
|
||||
=cut
|
||||
|
||||
sub line_number {
|
||||
my $self = shift;
|
||||
|
||||
my $location = $self->location() or return undef;
|
||||
return $location->[0];
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 column_number
|
||||
|
||||
If the Element exists within a L<PPI::Document> that has indexed the Element
|
||||
locations using C<PPI::Document::index_locations>, the C<column_number> method
|
||||
will return the column number of the first character of the Element within the
|
||||
Document.
|
||||
|
||||
Returns C<undef> on error, or if the L<PPI::Document> object has not been
|
||||
indexed.
|
||||
|
||||
=cut
|
||||
|
||||
sub column_number {
|
||||
my $self = shift;
|
||||
|
||||
my $location = $self->location() or return undef;
|
||||
return $location->[1];
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 visual_column_number
|
||||
|
||||
If the Element exists within a L<PPI::Document> that has indexed the Element
|
||||
locations using C<PPI::Document::index_locations>, the C<visual_column_number>
|
||||
method will return the visual column number of the first character of the
|
||||
Element within the Document, according to the value of
|
||||
L<PPI::Document/"tab_width [ $width ]">.
|
||||
|
||||
Returns C<undef> on error, or if the L<PPI::Document> object has not been
|
||||
indexed.
|
||||
|
||||
=cut
|
||||
|
||||
sub visual_column_number {
|
||||
my $self = shift;
|
||||
|
||||
my $location = $self->location() or return undef;
|
||||
return $location->[2];
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 logical_line_number
|
||||
|
||||
If the Element exists within a L<PPI::Document> that has indexed the Element
|
||||
locations using C<PPI::Document::index_locations>, the C<logical_line_number>
|
||||
method will return the line number of the first character of the Element within
|
||||
the Document, taking into account any C<#line> directives.
|
||||
|
||||
Returns C<undef> on error, or if the L<PPI::Document> object has not been
|
||||
indexed.
|
||||
|
||||
=cut
|
||||
|
||||
sub logical_line_number {
|
||||
my $self = shift;
|
||||
|
||||
return $self->location()->[3];
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 logical_filename
|
||||
|
||||
If the Element exists within a L<PPI::Document> that has indexed the Element
|
||||
locations using C<PPI::Document::index_locations>, the C<logical_filename>
|
||||
method will return the logical file name containing the first character of the
|
||||
Element within the Document, taking into account any C<#line> directives.
|
||||
|
||||
Returns C<undef> on error, or if the L<PPI::Document> object has not been
|
||||
indexed.
|
||||
|
||||
=cut
|
||||
|
||||
sub logical_filename {
|
||||
my $self = shift;
|
||||
|
||||
my $location = $self->location() or return undef;
|
||||
return $location->[4];
|
||||
}
|
||||
|
||||
sub _ensure_location_present {
|
||||
my $self = shift;
|
||||
|
||||
unless ( exists $self->{_location} ) {
|
||||
# Are we inside a normal document?
|
||||
my $Document = $self->document or return undef;
|
||||
if ( $Document->isa('PPI::Document::Fragment') ) {
|
||||
# Because they can't be serialized, document fragments
|
||||
# do not support the concept of location.
|
||||
return undef;
|
||||
}
|
||||
|
||||
# Generate the locations. If they need one location, then
|
||||
# the chances are they'll want more, and it's better that
|
||||
# everything is already pre-generated.
|
||||
$Document->index_locations or return undef;
|
||||
unless ( exists $self->{_location} ) {
|
||||
# erm... something went very wrong here
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Although flush_locations is only publically a Document-level method,
|
||||
# we are able to implement it at an Element level, allowing us to
|
||||
# selectively flush only the part of the document that occurs after the
|
||||
# element for which the flush is called.
|
||||
sub _flush_locations {
|
||||
my $self = shift;
|
||||
unless ( $self == $self->top ) {
|
||||
return $self->top->_flush_locations( $self );
|
||||
}
|
||||
|
||||
# Get the full list of all Tokens
|
||||
my @Tokens = $self->tokens;
|
||||
|
||||
# Optionally allow starting from an arbitrary element (or rather,
|
||||
# the first Token equal-to-or-within an arbitrary element)
|
||||
if ( _INSTANCE($_[0], 'PPI::Element') ) {
|
||||
my $start = shift->first_token;
|
||||
while ( my $Token = shift @Tokens ) {
|
||||
return 1 unless $Token->{_location};
|
||||
next unless refaddr($Token) == refaddr($start);
|
||||
|
||||
# Found the start. Flush its location
|
||||
delete $$Token->{_location};
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
# Iterate over any remaining Tokens and flush their location
|
||||
foreach my $Token ( @Tokens ) {
|
||||
delete $Token->{_location};
|
||||
}
|
||||
|
||||
1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# XML Compatibility Methods
|
||||
|
||||
sub _xml_name {
|
||||
my $class = ref $_[0] || $_[0];
|
||||
my $name = lc join( '_', split /::/, $class );
|
||||
substr($name, 4);
|
||||
}
|
||||
|
||||
sub _xml_attr {
|
||||
return {};
|
||||
}
|
||||
|
||||
sub _xml_content {
|
||||
defined $_[0]->{content} ? $_[0]->{content} : '';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Internals
|
||||
|
||||
# Set the error string
|
||||
sub _error {
|
||||
$errstr = $_[1];
|
||||
undef;
|
||||
}
|
||||
|
||||
# Clear the error string
|
||||
sub _clear {
|
||||
$errstr = '';
|
||||
$_[0];
|
||||
}
|
||||
|
||||
# Being DESTROYed in this manner, rather than by an explicit
|
||||
# ->delete means our reference count has probably fallen to zero.
|
||||
# Therefore we don't need to remove ourselves from our parent,
|
||||
# just the index ( just in case ).
|
||||
### XS -> PPI/XS.xs:_PPI_Element__DESTROY 0.900+
|
||||
sub DESTROY { delete $_PARENT{refaddr $_[0]} }
|
||||
|
||||
# Operator overloads
|
||||
sub __equals { ref $_[1] and refaddr($_[0]) == refaddr($_[1]) }
|
||||
sub __nequals { !__equals(@_) }
|
||||
sub __eq {
|
||||
my $self = _INSTANCE($_[0], 'PPI::Element') ? $_[0]->content : $_[0];
|
||||
my $other = _INSTANCE($_[1], 'PPI::Element') ? $_[1]->content : $_[1];
|
||||
$self eq $other;
|
||||
}
|
||||
sub __ne { !__eq(@_) }
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 TO DO
|
||||
|
||||
It would be nice if C<location> could be used in an ad-hoc manner. That is,
|
||||
if called on an Element within a Document that has not been indexed, it will
|
||||
do a one-off calculation to find the location. It might be very painful if
|
||||
someone started using it a lot, without remembering to index the document,
|
||||
but it would be handy for things that are only likely to use it once, such
|
||||
as error handlers.
|
||||
|
||||
=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
|
||||
108
database/perl/vendor/lib/PPI/Exception.pm
vendored
Normal file
108
database/perl/vendor/lib/PPI/Exception.pm
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
package PPI::Exception;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Exception - The PPI exception base class
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use PPI::Exception;
|
||||
|
||||
my $e = PPI::Exception->new( 'something happened' );
|
||||
$e->throw;
|
||||
|
||||
PPI::Exception->new( message => 'something happened' )->throw;
|
||||
PPI::Exception->throw( message => 'something happened' );
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
All exceptions thrown from within PPI will be instances or derivations
|
||||
of this class.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Params::Util qw{_INSTANCE};
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 new $message | message => $message, ...
|
||||
|
||||
Constructs and returns a new C<PPI::Exception> object.
|
||||
|
||||
A message for the exception can be passed, either as a string
|
||||
or as C<< message => $message >>. The message is available via the
|
||||
C<message> method.
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
return bless { @_ }, $class if @_ > 1;
|
||||
return bless { message => $_[0] }, $class if @_;
|
||||
return bless { message => 'Unknown Exception' }, $class;
|
||||
}
|
||||
|
||||
|
||||
=head2 throw
|
||||
|
||||
If called on a C<PPI::Exception> object, throws the object.
|
||||
If called on the class name, uses the arguments to construct a
|
||||
C<PPI::Exception> and then throw it.
|
||||
|
||||
Each time the object is thrown, information from the Perl <caller(0)>
|
||||
call is saved and made available via the C<callers> method.
|
||||
|
||||
This method never returns.
|
||||
|
||||
=cut
|
||||
|
||||
sub throw {
|
||||
my $it = shift;
|
||||
if ( _INSTANCE($it, 'PPI::Exception') ) {
|
||||
if ( $it->{callers} ) {
|
||||
push @{ $it->{callers} }, [ caller(0) ];
|
||||
} else {
|
||||
$it->{callers} ||= [];
|
||||
}
|
||||
} else {
|
||||
my $message = $_[0] || 'Unknown Exception';
|
||||
$it = $it->new(
|
||||
message => $message,
|
||||
callers => [
|
||||
[ caller(0) ],
|
||||
],
|
||||
);
|
||||
}
|
||||
die $it;
|
||||
}
|
||||
|
||||
|
||||
=head2 message
|
||||
|
||||
Returns the exception message passed to the object's constructor,
|
||||
or a default message.
|
||||
|
||||
=cut
|
||||
|
||||
sub message {
|
||||
$_[0]->{message};
|
||||
}
|
||||
|
||||
|
||||
=head2 callers
|
||||
|
||||
Returns a listref, each element of which is a listref of C<caller(0)>
|
||||
information. The returned listref can be empty.
|
||||
|
||||
=cut
|
||||
|
||||
sub callers {
|
||||
@{ $_[0]->{callers} || [] };
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
10
database/perl/vendor/lib/PPI/Exception/ParserRejection.pm
vendored
Normal file
10
database/perl/vendor/lib/PPI/Exception/ParserRejection.pm
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
package PPI::Exception::ParserRejection;
|
||||
|
||||
use strict;
|
||||
use PPI::Exception ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = 'PPI::Exception';
|
||||
|
||||
1;
|
||||
391
database/perl/vendor/lib/PPI/Find.pm
vendored
Normal file
391
database/perl/vendor/lib/PPI/Find.pm
vendored
Normal file
@@ -0,0 +1,391 @@
|
||||
package PPI::Find;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Find - Object version of the Element->find method
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
# Create the Find object
|
||||
my $Find = PPI::Find->new( \&wanted );
|
||||
|
||||
# Return all matching Elements as a list
|
||||
my @found = $Find->in( $Document );
|
||||
|
||||
# Can we find any matching Elements
|
||||
if ( $Find->any_matches($Document) ) {
|
||||
print "Found at least one matching Element";
|
||||
}
|
||||
|
||||
# Use the object as an iterator
|
||||
$Find->start($Document) or die "Failed to execute search";
|
||||
while ( my $token = $Find->match ) {
|
||||
...
|
||||
}
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
PPI::Find is the primary PDOM searching class in the core PPI package.
|
||||
|
||||
=head2 History
|
||||
|
||||
It became quite obvious during the development of PPI that many of the
|
||||
modules that would be built on top of it were going to need large numbers
|
||||
of saved, storable or easily creatable search objects that could be
|
||||
reused a number of times.
|
||||
|
||||
Although the internal ->find method provides a basic ability to search,
|
||||
it is by no means thorough. PPI::Find attempts to resolve this problem.
|
||||
|
||||
=head2 Structure and Style
|
||||
|
||||
PPI::Find provides a similar API to the popular L<File::Find::Rule>
|
||||
module for file searching, but without the ability to assemble queries.
|
||||
|
||||
The implementation of a separate PPI::Find::Rule sub-class that does
|
||||
provide this ability is left as an exercise for the reader.
|
||||
|
||||
=head2 The &wanted function
|
||||
|
||||
At the core of each PPI::Find object is a "wanted" function that is
|
||||
passed a number of arguments and returns a value which controls the
|
||||
flow of the search.
|
||||
|
||||
As the search executes, each Element will be passed to the wanted function
|
||||
in depth-first order.
|
||||
|
||||
It will be provided with two arguments. The current Element to test as $_[0],
|
||||
and the top-level Element of the search as $_[1].
|
||||
|
||||
The &wanted function is expected to return 1 (positive) if the Element
|
||||
matches the condition, 0 (false) if it does not, and undef (undefined) if
|
||||
the condition does not match, and the Find search should not descend to
|
||||
any of the current Element's children.
|
||||
|
||||
Errors should be reported from the &wanted function via die, which will be
|
||||
caught by the Find object and returned as an error.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Params::Util qw{_INSTANCE};
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Constructor
|
||||
|
||||
=pod
|
||||
|
||||
=head2 new &wanted
|
||||
|
||||
The C<new> constructor takes a single argument of the &wanted function,
|
||||
as described above and creates a new search.
|
||||
|
||||
Returns a new PPI::Find object, or C<undef> if not passed a CODE reference.
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my $class = ref $_[0] ? ref shift : shift;
|
||||
my $wanted = ref $_[0] eq 'CODE' ? shift : return undef;
|
||||
|
||||
# Create the object
|
||||
my $self = bless {
|
||||
wanted => $wanted,
|
||||
}, $class;
|
||||
|
||||
$self;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 clone
|
||||
|
||||
The C<clone> method creates another instance of the same Find object.
|
||||
|
||||
The cloning is done safely, so if your existing Find object is in the
|
||||
middle of an iteration, the cloned Find object will not also be in the
|
||||
iteration and can be safely used independently.
|
||||
|
||||
Returns a duplicate PPI::Find object.
|
||||
|
||||
=cut
|
||||
|
||||
sub clone {
|
||||
my $self = ref $_[0] ? shift
|
||||
: die "->clone can only be called as an object method";
|
||||
my $class = ref $self;
|
||||
|
||||
# Create the object
|
||||
my $clone = bless {
|
||||
wanted => $self->{wanted},
|
||||
}, $class;
|
||||
|
||||
$clone;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
####################################################################
|
||||
# Search Execution Methods
|
||||
|
||||
=pod
|
||||
|
||||
=head2 in $Document [, array_ref => 1 ]
|
||||
|
||||
The C<in> method starts and completes a full run of the search.
|
||||
|
||||
It takes as argument a single L<PPI::Element> object which will
|
||||
serve as the top of the search process.
|
||||
|
||||
Returns a list of PPI::Element objects that match the condition
|
||||
described by the &wanted function, or the null list on error.
|
||||
|
||||
You should check the ->errstr method for any errors if you are
|
||||
returned the null list, which may also mean simply that no Elements
|
||||
were found that matched the condition.
|
||||
|
||||
Because of this need to explicitly check for errors, an alternative
|
||||
return value mechanism is provide. If you pass the C<< array_ref => 1 >>
|
||||
parameter to the method, it will return the list of matched Elements
|
||||
as a reference to an ARRAY. The method will return false if no elements
|
||||
were matched, or C<undef> on error.
|
||||
|
||||
The ->errstr method can still be used to get the error message as normal.
|
||||
|
||||
=cut
|
||||
|
||||
sub in {
|
||||
my $self = shift;
|
||||
my $Element = shift;
|
||||
my %params = @_;
|
||||
delete $self->{errstr};
|
||||
|
||||
# Are we already acting as an iterator
|
||||
if ( $self->{in} ) {
|
||||
return $self->_error('->in called while another search is in progress', %params);
|
||||
}
|
||||
|
||||
# Get the root element for the search
|
||||
unless ( _INSTANCE($Element, 'PPI::Element') ) {
|
||||
return $self->_error('->in was not passed a PPI::Element object', %params);
|
||||
}
|
||||
|
||||
# Prepare the search
|
||||
$self->{in} = $Element;
|
||||
$self->{matches} = [];
|
||||
|
||||
# Execute the search
|
||||
if ( !eval { $self->_execute; 1 } ) {
|
||||
my $errstr = $@;
|
||||
$errstr =~ s/\s+at\s+line\s+.+$//;
|
||||
return $self->_error("Error while searching: $errstr", %params);
|
||||
}
|
||||
|
||||
# Clean up and return
|
||||
delete $self->{in};
|
||||
if ( $params{array_ref} ) {
|
||||
if ( @{$self->{matches}} ) {
|
||||
return delete $self->{matches};
|
||||
}
|
||||
delete $self->{matches};
|
||||
return '';
|
||||
}
|
||||
|
||||
# Return as a list
|
||||
my $matches = delete $self->{matches};
|
||||
@$matches;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 start $Element
|
||||
|
||||
The C<start> method lets the Find object act as an iterator. The method
|
||||
is passed the parent PPI::Element object as for the C<in> method, but does
|
||||
not accept any parameters.
|
||||
|
||||
To simplify error handling, the entire search is done at once, with the
|
||||
results cached and provided as-requested.
|
||||
|
||||
Returns true if the search completes, and false on error.
|
||||
|
||||
=cut
|
||||
|
||||
sub start {
|
||||
my $self = shift;
|
||||
my $Element = shift;
|
||||
delete $self->{errstr};
|
||||
|
||||
# Are we already acting as an iterator
|
||||
if ( $self->{in} ) {
|
||||
return $self->_error('->in called while another search is in progress');
|
||||
}
|
||||
|
||||
# Get the root element for the search
|
||||
unless ( _INSTANCE($Element, 'PPI::Element') ) {
|
||||
return $self->_error('->in was not passed a PPI::Element object');
|
||||
}
|
||||
|
||||
# Prepare the search
|
||||
$self->{in} = $Element;
|
||||
$self->{matches} = [];
|
||||
|
||||
# Execute the search
|
||||
if ( !eval { $self->_execute; 1 } ) {
|
||||
my $errstr = $@;
|
||||
$errstr =~ s/\s+at\s+line\s+.+$//;
|
||||
$self->_error("Error while searching: $errstr");
|
||||
return undef;
|
||||
}
|
||||
|
||||
1;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 match
|
||||
|
||||
The C<match> method returns the next matching Element in the iteration.
|
||||
|
||||
Returns a PPI::Element object, or C<undef> if there are no remaining
|
||||
Elements to be returned.
|
||||
|
||||
=cut
|
||||
|
||||
sub match {
|
||||
my $self = shift;
|
||||
return undef unless $self->{matches};
|
||||
|
||||
# Fetch and return the next match
|
||||
my $match = shift @{$self->{matches}};
|
||||
return $match if $match;
|
||||
|
||||
$self->finish;
|
||||
undef;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 finish
|
||||
|
||||
The C<finish> method provides a mechanism to end iteration if you wish to
|
||||
stop the iteration prematurely. It resets the Find object and allows it to
|
||||
be safely reused.
|
||||
|
||||
A Find object will be automatically finished when C<match> returns false.
|
||||
This means you should only need to call C<finish> when you stop
|
||||
iterating early.
|
||||
|
||||
You may safely call this method even when not iterating and it will return
|
||||
without failure.
|
||||
|
||||
Always returns true
|
||||
|
||||
=cut
|
||||
|
||||
sub finish {
|
||||
my $self = shift;
|
||||
delete $self->{in};
|
||||
delete $self->{matches};
|
||||
delete $self->{errstr};
|
||||
1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Support Methods and Error Handling
|
||||
|
||||
sub _execute {
|
||||
my $self = shift;
|
||||
my $wanted = $self->{wanted};
|
||||
my @queue = ( $self->{in} );
|
||||
|
||||
# Pull entries off the queue and hand them off to the wanted function
|
||||
while ( my $Element = shift @queue ) {
|
||||
my $rv = &$wanted( $Element, $self->{in} );
|
||||
|
||||
# Add to the matches if returns true
|
||||
push @{$self->{matches}}, $Element if $rv;
|
||||
|
||||
# Continue and don't descend if it returned undef
|
||||
# or if it doesn't have children
|
||||
next unless defined $rv;
|
||||
next unless $Element->isa('PPI::Node');
|
||||
|
||||
# Add the children to the head of the queue
|
||||
if ( $Element->isa('PPI::Structure') ) {
|
||||
unshift @queue, $Element->finish if $Element->finish;
|
||||
unshift @queue, $Element->children;
|
||||
unshift @queue, $Element->start if $Element->start;
|
||||
} else {
|
||||
unshift @queue, $Element->children;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 errstr
|
||||
|
||||
The C<errstr> method returns the error messages when a given PPI::Find
|
||||
object fails any action.
|
||||
|
||||
Returns a string, or C<undef> if there is no error.
|
||||
|
||||
=cut
|
||||
|
||||
sub errstr {
|
||||
shift->{errstr};
|
||||
}
|
||||
|
||||
sub _error {
|
||||
my $self = shift;
|
||||
$self->{errstr} = shift;
|
||||
my %params = @_;
|
||||
$params{array_ref} ? undef : ();
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 TO DO
|
||||
|
||||
- Implement the L<PPI::Find::Rule> class
|
||||
|
||||
=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
|
||||
1537
database/perl/vendor/lib/PPI/Lexer.pm
vendored
Normal file
1537
database/perl/vendor/lib/PPI/Lexer.pm
vendored
Normal file
File diff suppressed because it is too large
Load Diff
801
database/perl/vendor/lib/PPI/Node.pm
vendored
Normal file
801
database/perl/vendor/lib/PPI/Node.pm
vendored
Normal file
@@ -0,0 +1,801 @@
|
||||
package PPI::Node;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Node - Abstract PPI Node class, an Element that can contain other Elements
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
# 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' } );
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The C<PPI::Node> class provides an abstract base class for the Element
|
||||
classes that are able to contain other elements L<PPI::Document>,
|
||||
L<PPI::Statement>, and L<PPI::Structure>.
|
||||
|
||||
As well as those listed below, all of the methods that apply to
|
||||
L<PPI::Element> objects also apply to C<PPI::Node> objects.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Carp ();
|
||||
use Scalar::Util qw{refaddr};
|
||||
use List::Util ();
|
||||
use Params::Util qw{_INSTANCE _CLASS _CODELIKE _NUMBER};
|
||||
use PPI::Element ();
|
||||
use PPI::Singletons '%_PARENT';
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Element";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# The basic constructor
|
||||
|
||||
sub new {
|
||||
my $class = ref $_[0] || $_[0];
|
||||
bless { children => [] }, $class;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PDOM Methods
|
||||
|
||||
=pod
|
||||
|
||||
=head2 scope
|
||||
|
||||
The C<scope> method returns true if the node represents a lexical scope
|
||||
boundary, or false if it does not.
|
||||
|
||||
=cut
|
||||
|
||||
### XS -> PPI/XS.xs:_PPI_Node__scope 0.903+
|
||||
sub scope() { '' }
|
||||
|
||||
=pod
|
||||
|
||||
=head2 add_element $Element
|
||||
|
||||
The C<add_element> method adds a L<PPI::Element> object to the end of a
|
||||
C<PPI::Node>. Because Elements maintain links to their parent, an
|
||||
Element can only be added to a single Node.
|
||||
|
||||
Returns true if the L<PPI::Element> was added. Returns C<undef> if the
|
||||
Element was already within another Node, or the method is not passed
|
||||
a L<PPI::Element> object.
|
||||
|
||||
=cut
|
||||
|
||||
sub add_element {
|
||||
my $self = shift;
|
||||
|
||||
# Check the element
|
||||
my $Element = _INSTANCE(shift, 'PPI::Element') or return undef;
|
||||
$_PARENT{refaddr $Element} and return undef;
|
||||
|
||||
# Add the argument to the elements
|
||||
push @{$self->{children}}, $Element;
|
||||
Scalar::Util::weaken(
|
||||
$_PARENT{refaddr $Element} = $self
|
||||
);
|
||||
|
||||
1;
|
||||
}
|
||||
|
||||
# In a typical run profile, add_element is the number 1 resource drain.
|
||||
# This is a highly optimised unsafe version, for internal use only.
|
||||
sub __add_element {
|
||||
Scalar::Util::weaken(
|
||||
$_PARENT{refaddr $_[1]} = $_[0]
|
||||
);
|
||||
push @{$_[0]->{children}}, $_[1];
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 elements
|
||||
|
||||
The C<elements> method accesses all child elements B<structurally> within
|
||||
the C<PPI::Node> object. Note that in the base of the L<PPI::Structure>
|
||||
classes, this C<DOES> include the brace tokens at either end of the
|
||||
structure.
|
||||
|
||||
Returns a list of zero or more L<PPI::Element> objects.
|
||||
|
||||
Alternatively, if called in the scalar context, the C<elements> method
|
||||
returns a count of the number of elements.
|
||||
|
||||
=cut
|
||||
|
||||
sub elements {
|
||||
if ( wantarray ) {
|
||||
return @{$_[0]->{children}};
|
||||
} else {
|
||||
return scalar @{$_[0]->{children}};
|
||||
}
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 first_element
|
||||
|
||||
The C<first_element> method accesses the first element structurally within
|
||||
the C<PPI::Node> object. As for the C<elements> method, this does include
|
||||
the brace tokens for L<PPI::Structure> objects.
|
||||
|
||||
Returns a L<PPI::Element> object, or C<undef> if for some reason the
|
||||
C<PPI::Node> object does not contain any elements.
|
||||
|
||||
=cut
|
||||
|
||||
# Normally the first element is also the first child
|
||||
sub first_element {
|
||||
$_[0]->{children}->[0];
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 last_element
|
||||
|
||||
The C<last_element> method accesses the last element structurally within
|
||||
the C<PPI::Node> object. As for the C<elements> method, this does include
|
||||
the brace tokens for L<PPI::Structure> objects.
|
||||
|
||||
Returns a L<PPI::Element> object, or C<undef> if for some reason the
|
||||
C<PPI::Node> object does not contain any elements.
|
||||
|
||||
=cut
|
||||
|
||||
# Normally the last element is also the last child
|
||||
sub last_element {
|
||||
$_[0]->{children}->[-1];
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 children
|
||||
|
||||
The C<children> method accesses all child elements lexically within the
|
||||
C<PPI::Node> object. Note that in the case of the L<PPI::Structure>
|
||||
classes, this does B<NOT> include the brace tokens at either end of the
|
||||
structure.
|
||||
|
||||
Returns a list of zero of more L<PPI::Element> objects.
|
||||
|
||||
Alternatively, if called in the scalar context, the C<children> method
|
||||
returns a count of the number of lexical children.
|
||||
|
||||
=cut
|
||||
|
||||
# In the default case, this is the same as for the elements method
|
||||
sub children {
|
||||
wantarray ? @{$_[0]->{children}} : scalar @{$_[0]->{children}};
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 schildren
|
||||
|
||||
The C<schildren> method is really just a convenience, the significant-only
|
||||
variation of the normal C<children> method.
|
||||
|
||||
In list context, returns a list of significant children. In scalar context,
|
||||
returns the number of significant children.
|
||||
|
||||
=cut
|
||||
|
||||
sub schildren {
|
||||
return grep { $_->significant } @{$_[0]->{children}} if wantarray;
|
||||
my $count = 0;
|
||||
foreach ( @{$_[0]->{children}} ) {
|
||||
$count++ if $_->significant;
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 child $index
|
||||
|
||||
The C<child> method accesses a child L<PPI::Element> object by its
|
||||
position within the Node.
|
||||
|
||||
Returns a L<PPI::Element> object, or C<undef> if there is no child
|
||||
element at that node.
|
||||
|
||||
=cut
|
||||
|
||||
sub child {
|
||||
my ( $self, $index ) = @_;
|
||||
PPI::Exception->throw( "method child() needs an index" )
|
||||
if not defined _NUMBER $index;
|
||||
$self->{children}->[$index];
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 schild $index
|
||||
|
||||
The lexical structure of the Perl language ignores 'insignificant' items,
|
||||
such as whitespace and comments, while L<PPI> treats these items as valid
|
||||
tokens so that it can reassemble the file at any time. Because of this,
|
||||
in many situations there is a need to find an Element within a Node by
|
||||
index, only counting lexically significant Elements.
|
||||
|
||||
The C<schild> method returns a child Element by index, ignoring
|
||||
insignificant Elements. The index of a child Element is specified in the
|
||||
same way as for a normal array, with the first Element at index 0, and
|
||||
negative indexes used to identify a "from the end" position.
|
||||
|
||||
=cut
|
||||
|
||||
sub schild {
|
||||
my $self = shift;
|
||||
my $idx = 0 + shift;
|
||||
my $el = $self->{children};
|
||||
if ( $idx < 0 ) {
|
||||
my $cursor = 0;
|
||||
while ( exists $el->[--$cursor] ) {
|
||||
return $el->[$cursor] if $el->[$cursor]->significant and ++$idx >= 0;
|
||||
}
|
||||
} else {
|
||||
my $cursor = -1;
|
||||
while ( exists $el->[++$cursor] ) {
|
||||
return $el->[$cursor] if $el->[$cursor]->significant and --$idx < 0;
|
||||
}
|
||||
}
|
||||
undef;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 contains $Element
|
||||
|
||||
The C<contains> method is used to determine if another L<PPI::Element>
|
||||
object is logically "within" a C<PPI::Node>. For the special case of the
|
||||
brace tokens at either side of a L<PPI::Structure> object, they are
|
||||
generally considered "within" a L<PPI::Structure> object, even if they are
|
||||
not actually in the elements for the L<PPI::Structure>.
|
||||
|
||||
Returns true if the L<PPI::Element> is within us, false if not, or C<undef>
|
||||
on error.
|
||||
|
||||
=cut
|
||||
|
||||
sub contains {
|
||||
my $self = shift;
|
||||
my $Element = _INSTANCE(shift, 'PPI::Element') or return undef;
|
||||
|
||||
# Iterate up the Element's parent chain until we either run out
|
||||
# of parents, or get to ourself.
|
||||
while ( $Element = $Element->parent ) {
|
||||
return 1 if refaddr($self) == refaddr($Element);
|
||||
}
|
||||
|
||||
'';
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 find $class | \&wanted
|
||||
|
||||
The C<find> method is used to search within a code tree for
|
||||
L<PPI::Element> objects that meet a particular condition.
|
||||
|
||||
To specify the condition, the method can be provided with either a simple
|
||||
class name (full or shortened), or a C<CODE>/function reference.
|
||||
|
||||
# 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 will be passed two arguments, the top-level C<PPI::Node>
|
||||
you are searching in and the current L<PPI::Element> that the condition
|
||||
is testing.
|
||||
|
||||
The anonymous function should return one of three values. Returning true
|
||||
indicates a condition match, defined-false (C<0> or C<''>) indicates
|
||||
no-match, and C<undef> indicates no-match and no-descend.
|
||||
|
||||
In the last case, the tree walker will skip over anything below the
|
||||
C<undef>-returning element and move on to the next element at the same
|
||||
level.
|
||||
|
||||
To halt the entire search and return C<undef> immediately, a condition
|
||||
function should throw an exception (i.e. C<die>).
|
||||
|
||||
Note that this same wanted logic is used for all methods documented to
|
||||
have a C<\&wanted> parameter, as this one does.
|
||||
|
||||
The C<find> method returns a reference to an array of L<PPI::Element>
|
||||
objects that match the condition, false (but defined) if no Elements match
|
||||
the condition, or C<undef> if you provide a bad condition, or an error
|
||||
occurs during the search process.
|
||||
|
||||
In the case of a bad condition, a warning will be emitted as well.
|
||||
|
||||
=cut
|
||||
|
||||
sub find {
|
||||
my $self = shift;
|
||||
my $wanted = $self->_wanted(shift) or return undef;
|
||||
|
||||
# Use a queue based search, rather than a recursive one
|
||||
my @found;
|
||||
my @queue = @{$self->{children}};
|
||||
my $ok = eval {
|
||||
while ( @queue ) {
|
||||
my $Element = shift @queue;
|
||||
my $rv = &$wanted( $self, $Element );
|
||||
push @found, $Element if $rv;
|
||||
|
||||
# Support "don't descend on undef return"
|
||||
next unless defined $rv;
|
||||
|
||||
# Skip if the Element doesn't have any children
|
||||
next unless $Element->isa('PPI::Node');
|
||||
|
||||
# Depth-first keeps the queue size down and provides a
|
||||
# better logical order.
|
||||
if ( $Element->isa('PPI::Structure') ) {
|
||||
unshift @queue, $Element->finish if $Element->finish;
|
||||
unshift @queue, @{$Element->{children}};
|
||||
unshift @queue, $Element->start if $Element->start;
|
||||
} else {
|
||||
unshift @queue, @{$Element->{children}};
|
||||
}
|
||||
}
|
||||
1;
|
||||
};
|
||||
if ( !$ok ) {
|
||||
# Caught exception thrown from the wanted function
|
||||
return undef;
|
||||
}
|
||||
|
||||
@found ? \@found : '';
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 find_first $class | \&wanted
|
||||
|
||||
If the normal C<find> method is like a grep, then C<find_first> is
|
||||
equivalent to the L<List::Util> C<first> function.
|
||||
|
||||
Given an element class or a wanted function, it will search depth-first
|
||||
through a tree until it finds something that matches the condition,
|
||||
returning the first Element that it encounters.
|
||||
|
||||
See the C<find> method for details on the format of the search condition.
|
||||
|
||||
Returns the first L<PPI::Element> object that matches the condition, false
|
||||
if nothing matches the condition, or C<undef> if given an invalid condition,
|
||||
or an error occurs.
|
||||
|
||||
=cut
|
||||
|
||||
sub find_first {
|
||||
my $self = shift;
|
||||
my $wanted = $self->_wanted(shift) or return undef;
|
||||
|
||||
# Use the same queue-based search as for ->find
|
||||
my @queue = @{$self->{children}};
|
||||
my $rv;
|
||||
my $ok = eval {
|
||||
# The defined() here prevents a ton of calls to PPI::Util::TRUE
|
||||
while ( @queue ) {
|
||||
my $Element = shift @queue;
|
||||
my $element_rv = $wanted->( $self, $Element );
|
||||
if ( $element_rv ) {
|
||||
$rv = $Element;
|
||||
last;
|
||||
}
|
||||
|
||||
# Support "don't descend on undef return"
|
||||
next if !defined $element_rv;
|
||||
|
||||
# Skip if the Element doesn't have any children
|
||||
next if !$Element->isa('PPI::Node');
|
||||
|
||||
# Depth-first keeps the queue size down and provides a
|
||||
# better logical order.
|
||||
if ( $Element->isa('PPI::Structure') ) {
|
||||
unshift @queue, $Element->finish if defined($Element->finish);
|
||||
unshift @queue, @{$Element->{children}};
|
||||
unshift @queue, $Element->start if defined($Element->start);
|
||||
} else {
|
||||
unshift @queue, @{$Element->{children}};
|
||||
}
|
||||
}
|
||||
1;
|
||||
};
|
||||
if ( !$ok ) {
|
||||
# Caught exception thrown from the wanted function
|
||||
return undef;
|
||||
}
|
||||
|
||||
$rv or '';
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 find_any $class | \&wanted
|
||||
|
||||
The C<find_any> method is a short-circuiting true/false method that behaves
|
||||
like the normal C<find> method, but returns true as soon as it finds any
|
||||
Elements that match the search condition.
|
||||
|
||||
See the C<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 C<undef> if given an invalid condition, or an error occurs.
|
||||
|
||||
=cut
|
||||
|
||||
sub find_any {
|
||||
my $self = shift;
|
||||
my $rv = $self->find_first(@_);
|
||||
$rv ? 1 : $rv; # false or undef
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 remove_child $Element
|
||||
|
||||
If passed a L<PPI::Element> object that is a direct child of the Node,
|
||||
the C<remove_element> method will remove the C<Element> intact, along
|
||||
with any of its children. As such, this method acts essentially as a
|
||||
'cut' function.
|
||||
|
||||
If successful, returns the removed element. Otherwise, returns C<undef>.
|
||||
|
||||
=cut
|
||||
|
||||
sub remove_child {
|
||||
my $self = shift;
|
||||
my $child = _INSTANCE(shift, 'PPI::Element') or return undef;
|
||||
|
||||
# Find the position of the child
|
||||
my $key = refaddr $child;
|
||||
my $p = List::Util::first {
|
||||
refaddr $self->{children}[$_] == $key
|
||||
} 0..$#{$self->{children}};
|
||||
return undef unless defined $p;
|
||||
|
||||
# Splice it out, and remove the child's parent entry
|
||||
splice( @{$self->{children}}, $p, 1 );
|
||||
delete $_PARENT{refaddr $child};
|
||||
|
||||
$child;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 prune $class | \&wanted
|
||||
|
||||
The C<prune> method is used to strip L<PPI::Element> objects out of a code
|
||||
tree. The argument is the same as for the C<find> method, either a class
|
||||
name, or an anonymous subroutine which returns true/false. Any Element
|
||||
that matches the class|wanted will be deleted from the code tree, along
|
||||
with any of its children.
|
||||
|
||||
The C<prune> method returns the number of C<Element> objects that matched
|
||||
and were removed, B<non-recursively>. This might also be zero, so avoid a
|
||||
simple true/false test on the return false of the C<prune> method. It
|
||||
returns C<undef> on error, which you probably B<should> test for.
|
||||
|
||||
=cut
|
||||
|
||||
sub prune {
|
||||
my $self = shift;
|
||||
my $wanted = $self->_wanted(shift) or return undef;
|
||||
|
||||
# Use a depth-first queue search
|
||||
my $pruned = 0;
|
||||
my @queue = $self->children;
|
||||
my $ok = eval {
|
||||
while ( my $element = shift @queue ) {
|
||||
my $rv = &$wanted( $self, $element );
|
||||
if ( $rv ) {
|
||||
# Delete the child
|
||||
$element->delete or return undef;
|
||||
$pruned++;
|
||||
next;
|
||||
}
|
||||
|
||||
# Support the undef == "don't descend"
|
||||
next unless defined $rv;
|
||||
|
||||
if ( _INSTANCE($element, 'PPI::Node') ) {
|
||||
# Depth-first keeps the queue size down
|
||||
unshift @queue, $element->children;
|
||||
}
|
||||
}
|
||||
1;
|
||||
};
|
||||
if ( !$ok ) {
|
||||
# Caught exception thrown from the wanted function
|
||||
return undef;
|
||||
}
|
||||
|
||||
$pruned;
|
||||
}
|
||||
|
||||
# This method is likely to be very heavily used, so take
|
||||
# it slowly and carefully.
|
||||
### NOTE: Renaming this function or changing either to self will probably
|
||||
### break File::Find::Rule::PPI
|
||||
sub _wanted {
|
||||
my $either = shift;
|
||||
my $it = defined($_[0]) ? shift : do {
|
||||
Carp::carp('Undefined value passed as search condition') if $^W;
|
||||
return undef;
|
||||
};
|
||||
|
||||
# Has the caller provided a wanted function directly
|
||||
return $it if _CODELIKE($it);
|
||||
if ( ref $it ) {
|
||||
# No other ref types are supported
|
||||
Carp::carp('Illegal non-CODE reference passed as search condition') if $^W;
|
||||
return undef;
|
||||
}
|
||||
|
||||
# The first argument should be an Element class, possibly in shorthand
|
||||
$it = "PPI::$it" unless substr($it, 0, 5) eq 'PPI::';
|
||||
unless ( _CLASS($it) and $it->isa('PPI::Element') ) {
|
||||
# We got something, but it isn't an element
|
||||
Carp::carp("Cannot create search condition for '$it': Not a PPI::Element") if $^W;
|
||||
return undef;
|
||||
}
|
||||
|
||||
# Create the class part of the wanted function
|
||||
my $wanted_class = "\n\treturn '' unless \$_[1]->isa('$it');";
|
||||
|
||||
# Have we been given a second argument to check the content
|
||||
my $wanted_content = '';
|
||||
if ( defined $_[0] ) {
|
||||
my $content = shift;
|
||||
if ( ref $content eq 'Regexp' ) {
|
||||
$content = "$content";
|
||||
} elsif ( ref $content ) {
|
||||
# No other ref types are supported
|
||||
Carp::carp("Cannot create search condition for '$it': Not a PPI::Element") if $^W;
|
||||
return undef;
|
||||
} else {
|
||||
$content = quotemeta $content;
|
||||
}
|
||||
|
||||
# Complete the content part of the wanted function
|
||||
$wanted_content .= "\n\treturn '' unless defined \$_[1]->{content};";
|
||||
$wanted_content .= "\n\treturn '' unless \$_[1]->{content} =~ /$content/;";
|
||||
}
|
||||
|
||||
# Create the complete wanted function
|
||||
my $code = "sub {"
|
||||
. $wanted_class
|
||||
. $wanted_content
|
||||
. "\n\t1;"
|
||||
. "\n}";
|
||||
|
||||
# Compile the wanted function
|
||||
$code = eval $code;
|
||||
(ref $code eq 'CODE') ? $code : undef;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
####################################################################
|
||||
# PPI::Element overloaded methods
|
||||
|
||||
sub tokens {
|
||||
map { $_->tokens } @{$_[0]->{children}};
|
||||
}
|
||||
|
||||
### XS -> PPI/XS.xs:_PPI_Element__content 0.900+
|
||||
sub content {
|
||||
join '', map { $_->content } @{$_[0]->{children}};
|
||||
}
|
||||
|
||||
# Clone as normal, but then go down and relink all the _PARENT entries
|
||||
sub clone {
|
||||
my $self = shift;
|
||||
my $clone = $self->SUPER::clone;
|
||||
$clone->__link_children;
|
||||
$clone;
|
||||
}
|
||||
|
||||
sub location {
|
||||
my $self = shift;
|
||||
my $first = $self->{children}->[0] or return undef;
|
||||
$first->location;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Internal Methods
|
||||
|
||||
sub DESTROY {
|
||||
local $_;
|
||||
if ( $_[0]->{children} ) {
|
||||
my @queue = $_[0];
|
||||
while ( defined($_ = shift @queue) ) {
|
||||
unshift @queue, @{delete $_->{children}} if $_->{children};
|
||||
|
||||
# Remove all internal/private weird crosslinking so that
|
||||
# the cascading DESTROY calls will get called properly.
|
||||
%$_ = ();
|
||||
}
|
||||
}
|
||||
|
||||
# Remove us from our parent node as normal
|
||||
delete $_PARENT{refaddr $_[0]};
|
||||
}
|
||||
|
||||
# Find the position of a child
|
||||
sub __position {
|
||||
my $key = refaddr $_[1];
|
||||
List::Util::first { refaddr $_[0]{children}[$_] == $key } 0..$#{$_[0]{children}};
|
||||
}
|
||||
|
||||
# Insert one or more elements before a child
|
||||
sub __insert_before_child {
|
||||
my $self = shift;
|
||||
my $key = refaddr shift;
|
||||
my $p = List::Util::first {
|
||||
refaddr $self->{children}[$_] == $key
|
||||
} 0..$#{$self->{children}};
|
||||
foreach ( @_ ) {
|
||||
Scalar::Util::weaken(
|
||||
$_PARENT{refaddr $_} = $self
|
||||
);
|
||||
}
|
||||
splice( @{$self->{children}}, $p, 0, @_ );
|
||||
1;
|
||||
}
|
||||
|
||||
# Insert one or more elements after a child
|
||||
sub __insert_after_child {
|
||||
my $self = shift;
|
||||
my $key = refaddr shift;
|
||||
my $p = List::Util::first {
|
||||
refaddr $self->{children}[$_] == $key
|
||||
} 0..$#{$self->{children}};
|
||||
foreach ( @_ ) {
|
||||
Scalar::Util::weaken(
|
||||
$_PARENT{refaddr $_} = $self
|
||||
);
|
||||
}
|
||||
splice( @{$self->{children}}, $p + 1, 0, @_ );
|
||||
1;
|
||||
}
|
||||
|
||||
# Replace a child
|
||||
sub __replace_child {
|
||||
my $self = shift;
|
||||
my $key = refaddr shift;
|
||||
my $p = List::Util::first {
|
||||
refaddr $self->{children}[$_] == $key
|
||||
} 0..$#{$self->{children}};
|
||||
foreach ( @_ ) {
|
||||
Scalar::Util::weaken(
|
||||
$_PARENT{refaddr $_} = $self
|
||||
);
|
||||
}
|
||||
splice( @{$self->{children}}, $p, 1, @_ );
|
||||
1;
|
||||
}
|
||||
|
||||
# Create PARENT links for an entire tree.
|
||||
# Used when cloning or thawing.
|
||||
sub __link_children {
|
||||
my $self = shift;
|
||||
|
||||
# Relink all our children ( depth first )
|
||||
my @queue = ( $self );
|
||||
while ( my $Node = shift @queue ) {
|
||||
# Link our immediate children
|
||||
foreach my $Element ( @{$Node->{children}} ) {
|
||||
Scalar::Util::weaken(
|
||||
$_PARENT{refaddr($Element)} = $Node
|
||||
);
|
||||
unshift @queue, $Element if $Element->isa('PPI::Node');
|
||||
}
|
||||
|
||||
# If it's a structure, relink the open/close braces
|
||||
next unless $Node->isa('PPI::Structure');
|
||||
Scalar::Util::weaken(
|
||||
$_PARENT{refaddr($Node->start)} = $Node
|
||||
) if $Node->start;
|
||||
Scalar::Util::weaken(
|
||||
$_PARENT{refaddr($Node->finish)} = $Node
|
||||
) if $Node->finish;
|
||||
}
|
||||
|
||||
1;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 TO DO
|
||||
|
||||
- Move as much as possible to L<PPI::XS>
|
||||
|
||||
=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
|
||||
257
database/perl/vendor/lib/PPI/Normal.pm
vendored
Normal file
257
database/perl/vendor/lib/PPI/Normal.pm
vendored
Normal file
@@ -0,0 +1,257 @@
|
||||
package PPI::Normal;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Normal - Normalize Perl Documents
|
||||
|
||||
=head2 DESCRIPTION
|
||||
|
||||
Perl Documents, as created by PPI, are typically filled with all sorts of
|
||||
mess such as whitespace and comments and other things that don't effect
|
||||
the actual meaning of the code.
|
||||
|
||||
In addition, because there is more than one way to do most things, and the
|
||||
syntax of Perl itself is quite flexible, there are many ways in which the
|
||||
"same" code can look quite different.
|
||||
|
||||
PPI::Normal attempts to resolve this by providing a variety of mechanisms
|
||||
and algorithms to "normalize" Perl Documents, and determine a sort of base
|
||||
form for them (although this base form will be a memory structure, and
|
||||
not something that can be turned back into Perl source code).
|
||||
|
||||
The process itself is quite complex, and so for convenience and
|
||||
extensibility it has been separated into a number of layers. At a later
|
||||
point, it will be possible to write Plugin classes to insert additional
|
||||
normalization steps into the various different layers.
|
||||
|
||||
In addition, you can choose to do the normalization only as deep as a
|
||||
particular layer, depending on aggressively you want the normalization
|
||||
process to be.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Carp ();
|
||||
use List::Util 1.33 ();
|
||||
use PPI::Util '_Document';
|
||||
use PPI::Document::Normalized ();
|
||||
use PPI::Normal::Standard ();
|
||||
use PPI::Singletons '%LAYER';
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
# With the registration mechanism in place, load in the main set of
|
||||
# normalization methods to initialize the store.
|
||||
PPI::Normal::Standard->import;
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Configuration
|
||||
|
||||
=pod
|
||||
|
||||
=head2 register $function => $layer, ...
|
||||
|
||||
The C<register> method is used by normalization method providers to
|
||||
tell the normalization engines which functions need to be run, and
|
||||
in which layer they apply.
|
||||
|
||||
Provide a set of key/value pairs, where the key is the full name of the
|
||||
function (in string form), and the value is the layer (see description
|
||||
of the layers above) in which it should be run.
|
||||
|
||||
Returns true if all functions are registered, or C<undef> on error.
|
||||
|
||||
=cut
|
||||
|
||||
sub register {
|
||||
my $class = shift;
|
||||
while ( @_ ) {
|
||||
# Check the function
|
||||
my $function = shift;
|
||||
SCOPE: {
|
||||
no strict 'refs';
|
||||
defined $function and defined &{"$function"}
|
||||
or Carp::croak("Bad function name provided to PPI::Normal");
|
||||
}
|
||||
|
||||
# Has it already been added?
|
||||
if ( List::Util::any { $_ eq $function } map @{$_}, values %LAYER ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Check the layer to add it to
|
||||
my $layer = shift;
|
||||
defined $layer and $layer =~ /^(?:1|2)$/
|
||||
or Carp::croak("Bad layer provided to PPI::Normal");
|
||||
|
||||
# Add to the layer data store
|
||||
push @{ $LAYER{$layer} }, $function;
|
||||
}
|
||||
|
||||
1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Constructor and Accessors
|
||||
|
||||
=pod
|
||||
|
||||
=head2 new
|
||||
|
||||
my $level_1 = PPI::Normal->new;
|
||||
my $level_2 = PPI::Normal->new(2);
|
||||
|
||||
Creates a new normalization object, to which Document objects
|
||||
can be passed to be normalized.
|
||||
|
||||
Of course, what you probably REALLY want is just to call
|
||||
L<PPI::Document>'s C<normalize> method.
|
||||
|
||||
Takes an optional single parameter of the normalisation layer
|
||||
to use, which at this time can be either "1" or "2".
|
||||
|
||||
Returns a new C<PPI::Normal> object, or C<undef> on error.
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my $layer = @_ ?
|
||||
(defined $_[0] and ! ref $_[0] and $_[0] =~ /^[12]$/) ? shift : return undef
|
||||
: 1;
|
||||
|
||||
# Create the object
|
||||
my $object = bless {
|
||||
layer => $layer,
|
||||
}, $class;
|
||||
|
||||
$object;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head1 layer
|
||||
|
||||
The C<layer> accessor returns the normalisation layer of the object.
|
||||
|
||||
=cut
|
||||
|
||||
sub layer { $_[0]->{layer} }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Main Methods
|
||||
|
||||
=pod
|
||||
|
||||
=head2 process
|
||||
|
||||
The C<process> method takes anything that can be converted to a
|
||||
L<PPI::Document> (object, SCALAR ref, filename), loads it and
|
||||
applies the normalisation process to the document.
|
||||
|
||||
Returns a L<PPI::Document::Normalized> object, or C<undef> on error.
|
||||
|
||||
=cut
|
||||
|
||||
sub process {
|
||||
my $self = ref $_[0] ? shift : shift->new;
|
||||
|
||||
# PPI::Normal objects are reusable, but not re-entrant
|
||||
return undef if $self->{Document};
|
||||
|
||||
# Get or create the document
|
||||
$self->{Document} = _Document(shift) or return undef;
|
||||
|
||||
# Work out what functions we need to call
|
||||
my @functions = map { @{ $LAYER{$_} } } ( 1 .. $self->layer );
|
||||
|
||||
# Execute each function
|
||||
foreach my $function ( @functions ) {
|
||||
no strict 'refs';
|
||||
&{"$function"}( $self->{Document} );
|
||||
}
|
||||
|
||||
# Create the normalized Document object
|
||||
my $Normalized = PPI::Document::Normalized->new(
|
||||
Document => $self->{Document},
|
||||
version => __PACKAGE__->VERSION,
|
||||
functions => \@functions,
|
||||
) or return undef;
|
||||
|
||||
# Done, clean up
|
||||
delete $self->{Document};
|
||||
return $Normalized;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
The following normalisation layers are implemented. When writing
|
||||
plugins, you should register each transformation function with the
|
||||
appropriate layer.
|
||||
|
||||
=head2 Layer 1 - Insignificant Data Removal
|
||||
|
||||
The basic step common to all normalization, layer 1 scans through the
|
||||
Document and removes all whitespace, comments, POD, and anything else
|
||||
that returns false for its C<significant> method.
|
||||
|
||||
It also checks each Element and removes known-useless sub-element
|
||||
metadata such as the Element's physical position in the file.
|
||||
|
||||
=head2 Layer 2 - Significant Element Removal
|
||||
|
||||
After the removal of the insignificant data, Layer 2 removed larger, more
|
||||
complex, and superficially "significant" elements, that can be removed
|
||||
for the purposes of normalisation.
|
||||
|
||||
Examples from this layer include pragmas, now-useless statement
|
||||
separators (since the PDOM tree is holding statement elements), and
|
||||
several other minor bits and pieces.
|
||||
|
||||
=head2 Layer 3 - TO BE COMPLETED
|
||||
|
||||
This version of the forward-port of the Perl::Compare functionality
|
||||
to the 0.900+ API of PPI only implements Layer 1 and 2 at this time.
|
||||
|
||||
=head1 TO DO
|
||||
|
||||
- Write the other 4-5 layers :)
|
||||
|
||||
=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 2005 - 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
|
||||
139
database/perl/vendor/lib/PPI/Normal/Standard.pm
vendored
Normal file
139
database/perl/vendor/lib/PPI/Normal/Standard.pm
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
package PPI::Normal::Standard;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Normal::Standard - Provides standard document normalization functions
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module provides the default normalization methods for L<PPI::Normal>.
|
||||
|
||||
There is no reason for you to need to load this yourself.
|
||||
|
||||
B<Move along, nothing to see here>.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Configuration and Registration
|
||||
|
||||
my @METHODS = (
|
||||
remove_insignificant_elements => 1,
|
||||
remove_useless_attributes => 1,
|
||||
remove_useless_pragma => 2,
|
||||
remove_statement_separator => 2,
|
||||
remove_useless_return => 2,
|
||||
);
|
||||
|
||||
sub import {
|
||||
PPI::Normal->register(
|
||||
map { /\D/ ? "PPI::Normal::Standard::$_" : $_ } @METHODS
|
||||
) or die "Failed to register PPI::Normal::Standard transforms";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Level 1 Transforms
|
||||
|
||||
# Remove all insignificant elements
|
||||
sub remove_insignificant_elements {
|
||||
my $Document = shift;
|
||||
$Document->prune( sub { ! $_[1]->significant } );
|
||||
}
|
||||
|
||||
# Remove custom attributes that are not relevant to normalization
|
||||
sub remove_useless_attributes {
|
||||
my $Document = shift;
|
||||
delete $Document->{tab_width};
|
||||
|
||||
### FIXME - Add support for more things
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Level 2 Transforms
|
||||
|
||||
# Remove version dependencies and pragma
|
||||
my $remove_pragma = map { $_ => 1 } qw{
|
||||
strict warnings diagnostics less
|
||||
};
|
||||
sub remove_useless_pragma {
|
||||
my $Document = shift;
|
||||
$Document->prune( sub {
|
||||
return '' unless $_[1]->isa('PPI::Statement::Include');
|
||||
return 1 if $_[1]->version;
|
||||
return 1 if $remove_pragma->{$_[1]->pragma};
|
||||
'';
|
||||
} );
|
||||
}
|
||||
|
||||
# Remove all semi-colons at the end of statements
|
||||
sub remove_statement_separator {
|
||||
my $Document = shift;
|
||||
$Document->prune( sub {
|
||||
$_[1]->isa('PPI::Token::Structure') or return '';
|
||||
$_[1]->content eq ';' or return '';
|
||||
my $stmt = $_[1]->parent or return '';
|
||||
$stmt->isa('PPI::Statement') or return '';
|
||||
$_[1]->next_sibling and return '';
|
||||
1;
|
||||
} );
|
||||
}
|
||||
|
||||
# In any block, the "return" in the last statement is not
|
||||
# needed if there is only one and only one thing after the
|
||||
# return.
|
||||
sub remove_useless_return {
|
||||
my $Document = shift;
|
||||
$Document->prune( sub {
|
||||
$_[1]->isa('PPI::Token::Word') or return '';
|
||||
$_[1]->content eq 'return' or return '';
|
||||
my $stmt = $_[1]->parent or return '';
|
||||
$stmt->isa('PPI::Statement::Break') or return '';
|
||||
$stmt->children == 2 or return '';
|
||||
$stmt->next_sibling and return '';
|
||||
my $block = $stmt->parent or return '';
|
||||
$block->isa('PPI::Structure::Block') or return '';
|
||||
1;
|
||||
} );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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 2005 - 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
|
||||
91
database/perl/vendor/lib/PPI/Singletons.pm
vendored
Normal file
91
database/perl/vendor/lib/PPI/Singletons.pm
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
package PPI::Singletons;
|
||||
|
||||
# exports some singleton variables to avoid aliasing magic
|
||||
|
||||
use strict;
|
||||
use Exporter ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = 'Exporter';
|
||||
our @EXPORT_OK = qw{ %_PARENT %OPERATOR %MAGIC %LAYER $CURLY_SYMBOL %QUOTELIKE %KEYWORDS };
|
||||
|
||||
our %_PARENT; # Master Child -> Parent index
|
||||
|
||||
# operator index
|
||||
our %OPERATOR = map { $_ => 1 } (
|
||||
qw{
|
||||
-> ++ -- ** ! ~ + -
|
||||
=~ !~ * / % x . << >>
|
||||
< > <= >= lt gt le ge
|
||||
== != <=> eq ne cmp ~~
|
||||
& | ^ && || // .. ...
|
||||
? :
|
||||
= **= += -= .= *= /= %= x= &= |= ^= <<= >>= &&= ||= //=
|
||||
=> <> <<>>
|
||||
and or xor not
|
||||
}, ',' # Avoids "comma in qw{}" warning
|
||||
);
|
||||
|
||||
# Magic variables taken from perlvar.
|
||||
# Several things added separately to avoid warnings.
|
||||
our %MAGIC = map { $_ => 1 } qw{
|
||||
$1 $2 $3 $4 $5 $6 $7 $8 $9
|
||||
$_ $& $` $' $+ @+ %+ $* $. $/ $|
|
||||
$\\ $" $; $% $= $- @- %- $)
|
||||
$~ $^ $: $? $! %! $@ $$ $< $>
|
||||
$( $0 $[ $] @_ @*
|
||||
|
||||
$^L $^A $^E $^C $^D $^F $^H
|
||||
$^I $^M $^N $^O $^P $^R $^S
|
||||
$^T $^V $^W $^X %^H
|
||||
|
||||
$::|
|
||||
}, '$}', '$,', '$#', '$#+', '$#-';
|
||||
|
||||
our %LAYER = ( 1 => [], 2 => [] ); # Registered function store
|
||||
|
||||
our $CURLY_SYMBOL = qr{\G\^[[:upper:]_]\w+\}};
|
||||
|
||||
our %QUOTELIKE = (
|
||||
'q' => 'Quote::Literal',
|
||||
'qq' => 'Quote::Interpolate',
|
||||
'qx' => 'QuoteLike::Command',
|
||||
'qw' => 'QuoteLike::Words',
|
||||
'qr' => 'QuoteLike::Regexp',
|
||||
'm' => 'Regexp::Match',
|
||||
's' => 'Regexp::Substitute',
|
||||
'tr' => 'Regexp::Transliterate',
|
||||
'y' => 'Regexp::Transliterate',
|
||||
);
|
||||
|
||||
# List of keywords is from regen/keywords.pl in the perl source.
|
||||
our %KEYWORDS = map { $_ => 1 } qw{
|
||||
abs accept alarm and atan2 bind binmode bless break caller chdir chmod
|
||||
chomp chop chown chr chroot close closedir cmp connect continue cos
|
||||
crypt dbmclose dbmopen default defined delete die do dump each else
|
||||
elsif endgrent endhostent endnetent endprotoent endpwent endservent
|
||||
eof eq eval evalbytes exec exists exit exp fc fcntl fileno flock for
|
||||
foreach fork format formline ge getc getgrent getgrgid getgrnam
|
||||
gethostbyaddr gethostbyname gethostent getlogin getnetbyaddr
|
||||
getnetbyname getnetent getpeername getpgrp getppid getpriority
|
||||
getprotobyname getprotobynumber getprotoent getpwent getpwnam
|
||||
getpwuid getservbyname getservbyport getservent getsockname
|
||||
getsockopt given glob gmtime goto grep gt hex if index int ioctl join
|
||||
keys kill last lc lcfirst le length link listen local localtime lock
|
||||
log lstat lt m map mkdir msgctl msgget msgrcv msgsnd my ne next no
|
||||
not oct open opendir or ord our pack package pipe pop pos print
|
||||
printf prototype push q qq qr quotemeta qw qx rand read readdir
|
||||
readline readlink readpipe recv redo ref rename require reset return
|
||||
reverse rewinddir rindex rmdir s say scalar seek seekdir select semctl
|
||||
semget semop send setgrent sethostent setnetent setpgrp
|
||||
setpriority setprotoent setpwent setservent setsockopt shift shmctl
|
||||
shmget shmread shmwrite shutdown sin sleep socket socketpair sort
|
||||
splice split sprintf sqrt srand stat state study sub substr symlink
|
||||
syscall sysopen sysread sysseek system syswrite tell telldir tie tied
|
||||
time times tr truncate uc ucfirst umask undef unless unlink unpack
|
||||
unshift untie until use utime values vec wait waitpid wantarray warn
|
||||
when while write x xor y
|
||||
};
|
||||
|
||||
1;
|
||||
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
|
||||
75
database/perl/vendor/lib/PPI/Statement/Break.pm
vendored
Normal file
75
database/perl/vendor/lib/PPI/Statement/Break.pm
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
package PPI::Statement::Break;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Statement::Break - Statements which break out of normal statement flow
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
last;
|
||||
goto FOO;
|
||||
next if condition();
|
||||
return $foo;
|
||||
redo;
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Statement::Break
|
||||
isa PPI::Statement
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<PPI::Statement::Break> is intended to represent statements that break
|
||||
out of the normal statement flow control. This covers the basic
|
||||
types C<'redo'>, C<'goto'>, C<'next'>, C<'last'> and C<'return'>.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Statement::Break> has no additional methods beyond the default ones
|
||||
provided by L<PPI::Statement>, L<PPI::Node> and L<PPI::Element>.
|
||||
|
||||
However, it is expected to gain methods for identifying the line to break
|
||||
to, or the structure to break out of.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Statement ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Statement";
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 TO DO
|
||||
|
||||
- Add the methods to identify the break target
|
||||
|
||||
- Add some proper unit testing
|
||||
|
||||
=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
|
||||
201
database/perl/vendor/lib/PPI/Statement/Compound.pm
vendored
Normal file
201
database/perl/vendor/lib/PPI/Statement/Compound.pm
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
package PPI::Statement::Compound;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Statement::Compound - Describes all compound statements
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
# A compound if statement
|
||||
if ( foo ) {
|
||||
bar();
|
||||
} else {
|
||||
baz();
|
||||
}
|
||||
|
||||
# A compound loop statement
|
||||
foreach ( @list ) {
|
||||
bar($_);
|
||||
}
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Statement::Compound
|
||||
isa PPI::Statement
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<PPI::Statement::Compound> objects are used to describe all current forms
|
||||
of compound statements, as described in L<perlsyn>.
|
||||
|
||||
This covers blocks using C<if>, C<unless>, C<for>, C<foreach>, C<while>,
|
||||
and C<continue>. Please note this does B<not> cover "simple" statements
|
||||
with trailing conditions. Please note also that "do" is also not part of
|
||||
a compound statement.
|
||||
|
||||
# This is NOT a compound statement
|
||||
my $foo = 1 if $condition;
|
||||
|
||||
# This is also not a compound statement
|
||||
do { ... } until $condition;
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Statement::Compound> has a number of methods in addition to the
|
||||
standard L<PPI::Statement>, L<PPI::Node> and L<PPI::Element> methods.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Statement ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Statement";
|
||||
|
||||
# Keyword type map
|
||||
my %TYPES = (
|
||||
'if' => 'if',
|
||||
'unless' => 'if',
|
||||
'while' => 'while',
|
||||
'until' => 'while',
|
||||
'for' => 'for',
|
||||
'foreach' => 'foreach',
|
||||
);
|
||||
|
||||
# Lexer clues
|
||||
sub __LEXER__normal() { '' }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Statement::Compound analysis methods
|
||||
|
||||
=pod
|
||||
|
||||
=head2 type
|
||||
|
||||
The C<type> method returns the syntactic type of the compound statement.
|
||||
|
||||
There are four basic compound statement types.
|
||||
|
||||
The C<'if'> type includes all variations of the if and unless statements,
|
||||
including any C<'elsif'> or C<'else'> parts of the compound statement.
|
||||
|
||||
The C<'while'> type describes the standard while and until statements, but
|
||||
again does B<not> describes simple statements with a trailing while.
|
||||
|
||||
The C<'for'> type covers the C-style for loops, regardless of whether they
|
||||
were declared using C<'for'> or C<'foreach'>.
|
||||
|
||||
The C<'foreach'> type covers loops that iterate over collections,
|
||||
regardless of whether they were declared using C<'for'> or C<'foreach'>.
|
||||
|
||||
All of the compounds are a variation on one of these four.
|
||||
|
||||
Returns the simple string C<'if'>, C<'for'>, C<'foreach'> or C<'while'>,
|
||||
or C<undef> if the type cannot be determined.
|
||||
|
||||
=cut
|
||||
|
||||
sub type {
|
||||
my $self = shift;
|
||||
my $p = 0; # Child position
|
||||
my $Element = $self->schild($p) or return undef;
|
||||
|
||||
# A labelled statement
|
||||
if ( $Element->isa('PPI::Token::Label') ) {
|
||||
$Element = $self->schild(++$p) or return 'label';
|
||||
}
|
||||
|
||||
# Most simple cases
|
||||
my $content = $Element->content;
|
||||
if ( $content =~ /^for(?:each)?\z/ ) {
|
||||
$Element = $self->schild(++$p) or return $content;
|
||||
if ( $Element->isa('PPI::Token') ) {
|
||||
return 'foreach' if $Element->content =~ /^my|our|state\z/;
|
||||
return 'foreach' if $Element->isa('PPI::Token::Symbol');
|
||||
return 'foreach' if $Element->isa('PPI::Token::QuoteLike::Words');
|
||||
}
|
||||
if ( $Element->isa('PPI::Structure::List') ) {
|
||||
return 'foreach';
|
||||
}
|
||||
return 'for';
|
||||
}
|
||||
return $TYPES{$content} if $Element->isa('PPI::Token::Word');
|
||||
return 'continue' if $Element->isa('PPI::Structure::Block');
|
||||
|
||||
# Unknown (shouldn't exist?)
|
||||
undef;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Node Methods
|
||||
|
||||
sub scope() { 1 }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Element Methods
|
||||
|
||||
sub _complete {
|
||||
my $self = shift;
|
||||
my $type = $self->type or die "Illegal compound statement type";
|
||||
|
||||
# Check the different types of compound statements
|
||||
if ( $type eq 'if' ) {
|
||||
# Unless the last significant child is a complete
|
||||
# block, it must be incomplete.
|
||||
my $child = $self->schild(-1) or return '';
|
||||
$child->isa('PPI::Structure') or return '';
|
||||
$child->braces eq '{}' or return '';
|
||||
$child->_complete or return '';
|
||||
|
||||
# It can STILL be
|
||||
} elsif ( $type eq 'while' ) {
|
||||
die "CODE INCOMPLETE";
|
||||
} else {
|
||||
die "CODE INCOMPLETE";
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 TO DO
|
||||
|
||||
- Write unit tests for this package
|
||||
|
||||
=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
|
||||
81
database/perl/vendor/lib/PPI/Statement/Data.pm
vendored
Normal file
81
database/perl/vendor/lib/PPI/Statement/Data.pm
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
package PPI::Statement::Data;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Statement::Data - The __DATA__ section of a file
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
# Normal content
|
||||
|
||||
__DATA__
|
||||
This: data
|
||||
is: part
|
||||
of: the
|
||||
PPI::Statement::Data: object
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Statement::Compound
|
||||
isa PPI::Statement
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<PPI::Statement::Data> is a utility class designed to hold content in
|
||||
the __DATA__ section of a file. It provides a single statement to hold
|
||||
B<all> of the data.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Statement::Data> has no additional methods beyond the default ones
|
||||
provided by L<PPI::Statement>, L<PPI::Node> and L<PPI::Element>.
|
||||
|
||||
However, it is expected to gain methods for accessing the data directly,
|
||||
(as a filehandle for example) just as you would access the data in the
|
||||
Perl code itself.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Statement ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Statement";
|
||||
|
||||
# Data is never complete
|
||||
sub _complete () { '' }
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 TO DO
|
||||
|
||||
- Add the methods to read in the data
|
||||
|
||||
- Add some proper unit testing
|
||||
|
||||
=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
|
||||
79
database/perl/vendor/lib/PPI/Statement/End.pm
vendored
Normal file
79
database/perl/vendor/lib/PPI/Statement/End.pm
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
package PPI::Statement::End;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Statement::End - Content after the __END__ of a module
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
# This is normal content
|
||||
|
||||
__END__
|
||||
|
||||
This is part of a PPI::Statement::End statement
|
||||
|
||||
=pod
|
||||
|
||||
This is not part of the ::End statement, it's POD
|
||||
|
||||
=cut
|
||||
|
||||
This is another PPI::Statement::End statement
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Statement::End
|
||||
isa PPI::Statement
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<PPI::Statement::End> is a utility class designed to serve as a contained
|
||||
for all of the content after the __END__ tag in a file.
|
||||
|
||||
It doesn't cover the ENTIRE of the __END__ section, and can be interspersed
|
||||
with L<PPI::Token::Pod> tokens.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Statement::End> has no additional methods beyond the default ones
|
||||
provided by L<PPI::Statement>, L<PPI::Node> and L<PPI::Element>.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Statement ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Statement";
|
||||
|
||||
# Once we have an __END__ we're done
|
||||
sub _complete () { 1 }
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
67
database/perl/vendor/lib/PPI/Statement/Expression.pm
vendored
Normal file
67
database/perl/vendor/lib/PPI/Statement/Expression.pm
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
package PPI::Statement::Expression;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Statement::Expression - A generic and non-specialised statement
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
$foo = bar;
|
||||
("Hello World!");
|
||||
do_this();
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Statement::Expression
|
||||
isa PPI::Statement
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A C<PPI::Statement::Expression> is a normal statement that is evaluated,
|
||||
may or may not assign, may or may not have side effects, and has no special
|
||||
or redeeming features whatsoever.
|
||||
|
||||
It provides a default for all statements that don't fit into any other
|
||||
classes.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Statement::Expression> has no additional methods beyond the default ones
|
||||
provided by L<PPI::Statement>, L<PPI::Node> and L<PPI::Element>.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Statement ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Statement";
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
90
database/perl/vendor/lib/PPI/Statement/Given.pm
vendored
Normal file
90
database/perl/vendor/lib/PPI/Statement/Given.pm
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
package PPI::Statement::Given;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Statement::Given - A given-when statement
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
given ( foo ) {
|
||||
say $_;
|
||||
}
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Statement::Given
|
||||
isa PPI::Statement
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<PPI::Statement::Given> objects are used to describe switch statements, as
|
||||
described in L<perlsyn>.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Statement::Given> has no methods beyond those provided by the
|
||||
standard L<PPI::Structure>, L<PPI::Node> and L<PPI::Element> methods.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Statement ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Statement";
|
||||
|
||||
# Lexer clues
|
||||
sub __LEXER__normal() { '' }
|
||||
|
||||
sub _complete {
|
||||
my $child = $_[0]->schild(-1);
|
||||
return !! (
|
||||
defined $child
|
||||
and
|
||||
$child->isa('PPI::Structure::Block')
|
||||
and
|
||||
$child->complete
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Node Methods
|
||||
|
||||
sub scope() { 1 }
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 TO DO
|
||||
|
||||
- Write unit tests for this package
|
||||
|
||||
=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
|
||||
265
database/perl/vendor/lib/PPI/Statement/Include.pm
vendored
Normal file
265
database/perl/vendor/lib/PPI/Statement/Include.pm
vendored
Normal file
@@ -0,0 +1,265 @@
|
||||
package PPI::Statement::Include;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Statement::Include - Statements that include other code
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
# The following are all includes
|
||||
use 5.006;
|
||||
use strict;
|
||||
use My::Module;
|
||||
use constant FOO => 'Foo';
|
||||
require Foo::Bar;
|
||||
require "Foo/Bar.pm";
|
||||
require $foo if 1;
|
||||
no strict 'refs';
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Statement::Include
|
||||
isa PPI::Statement
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Despite its name, the C<PPI::Statement::Include> class covers a number
|
||||
of different types of statement that cover all statements starting with
|
||||
C<use>, C<no> and C<require>.
|
||||
|
||||
But basically, they cover three situations.
|
||||
|
||||
Firstly, a dependency on a particular version of perl (for which the
|
||||
C<version> method returns true), a pragma (for which the C<pragma> method
|
||||
returns true), or the loading (and unloading via no) of modules.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Statement::Include> has a number of methods in addition to the standard
|
||||
L<PPI::Statement>, L<PPI::Node> and L<PPI::Element> methods.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Statement ();
|
||||
use PPI::Statement::Include::Perl6 ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Statement";
|
||||
|
||||
=pod
|
||||
|
||||
=head2 type
|
||||
|
||||
The C<type> method returns the general type of statement (C<'use'>, C<'no'>
|
||||
or C<'require'>).
|
||||
|
||||
Returns the type as a string, or C<undef> if the type cannot be detected.
|
||||
|
||||
=cut
|
||||
|
||||
sub type {
|
||||
my $self = shift;
|
||||
my $keyword = $self->schild(0) or return undef;
|
||||
$keyword->isa('PPI::Token::Word') and $keyword->content;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 module
|
||||
|
||||
The C<module> method returns the module name specified in any include
|
||||
statement. This C<includes> pragma names, because pragma are implemented
|
||||
as modules. (And lets face it, the definition of a pragma can be fuzzy
|
||||
at the best of times in any case)
|
||||
|
||||
This covers all of these...
|
||||
|
||||
use strict;
|
||||
use My::Module;
|
||||
no strict;
|
||||
require My::Module;
|
||||
|
||||
...but does not cover any of these...
|
||||
|
||||
use 5.006;
|
||||
require 5.005;
|
||||
require "explicit/file/name.pl";
|
||||
|
||||
Returns the module name as a string, or C<undef> if the include does
|
||||
not specify a module name.
|
||||
|
||||
=cut
|
||||
|
||||
sub module {
|
||||
my $self = shift;
|
||||
my $module = $self->schild(1) or return undef;
|
||||
$module->isa('PPI::Token::Word') and $module->content;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 module_version
|
||||
|
||||
The C<module_version> method returns the minimum version of the module
|
||||
required by the statement, if there is one.
|
||||
|
||||
=cut
|
||||
|
||||
sub module_version {
|
||||
my $self = shift;
|
||||
my $argument = $self->schild(3);
|
||||
if ( $argument and $argument->isa('PPI::Token::Operator') ) {
|
||||
return undef;
|
||||
}
|
||||
|
||||
my $version = $self->schild(2) or return undef;
|
||||
return undef unless $version->isa('PPI::Token::Number');
|
||||
|
||||
return $version;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 pragma
|
||||
|
||||
The C<pragma> method checks for an include statement's use as a
|
||||
pragma, and returns it if so.
|
||||
|
||||
Or at least, it claims to. In practice it's a lot harder to say exactly
|
||||
what is or isn't a pragma, because the definition is fuzzy.
|
||||
|
||||
The C<intent> of a pragma is to modify the way in which the parser works.
|
||||
This is done though the use of modules that do various types of internals
|
||||
magic.
|
||||
|
||||
For now, PPI assumes that any "module name" that is only a set of
|
||||
lowercase letters (and perhaps numbers, like C<use utf8;>). This
|
||||
behaviour is expected to change, most likely to something that knows
|
||||
the specific names of the various "pragmas".
|
||||
|
||||
Returns the name of the pragma, or false ('') if the include is not a
|
||||
pragma.
|
||||
|
||||
=cut
|
||||
|
||||
sub pragma {
|
||||
my $self = shift;
|
||||
my $module = $self->module or return '';
|
||||
$module =~ /^[a-z][a-z\d]*$/ ? $module : '';
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 version
|
||||
|
||||
The C<version> method checks for an include statement that introduces a
|
||||
dependency on the version of C<perl> the code is compatible with.
|
||||
|
||||
This covers two specific statements.
|
||||
|
||||
use 5.006;
|
||||
require 5.006;
|
||||
|
||||
Currently the version is returned as a string, although in future the version
|
||||
may be returned as a L<version> object. If you want a numeric representation,
|
||||
use C<version_literal()>. Returns false if the statement is not a version
|
||||
dependency.
|
||||
|
||||
=cut
|
||||
|
||||
sub version {
|
||||
my $self = shift;
|
||||
my $version = $self->schild(1) or return undef;
|
||||
$version->isa('PPI::Token::Number') ? $version->content : '';
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 version_literal
|
||||
|
||||
The C<version_literal> method has the same behavior as C<version()>, but the
|
||||
version is returned as a numeric literal. Returns false if the statement is
|
||||
not a version dependency.
|
||||
|
||||
=cut
|
||||
|
||||
sub version_literal {
|
||||
my $self = shift;
|
||||
my $version = $self->schild(1) or return undef;
|
||||
$version->isa('PPI::Token::Number') ? $version->literal : '';
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 arguments
|
||||
|
||||
The C<arguments> method gives you the rest of the statement after the
|
||||
module/pragma and module version, i.e. the stuff that will be used to
|
||||
construct what gets passed to the module's C<import()> subroutine. This does
|
||||
include the comma, etc. operators, but doesn't include non-significant direct
|
||||
children or any final semicolon.
|
||||
|
||||
=cut
|
||||
|
||||
sub arguments {
|
||||
my $self = shift;
|
||||
my @args = $self->schildren;
|
||||
|
||||
# Remove the "use", "no" or "require"
|
||||
shift @args;
|
||||
|
||||
# Remove the statement terminator
|
||||
if (
|
||||
$args[-1]->isa('PPI::Token::Structure')
|
||||
and
|
||||
$args[-1]->content eq ';'
|
||||
) {
|
||||
pop @args;
|
||||
}
|
||||
|
||||
# Remove the module or perl version.
|
||||
shift @args;
|
||||
|
||||
return unless @args;
|
||||
|
||||
if ( $args[0]->isa('PPI::Token::Number') ) {
|
||||
my $after = $args[1] or return;
|
||||
$after->isa('PPI::Token::Operator') or shift @args;
|
||||
}
|
||||
|
||||
return @args;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 TO DO
|
||||
|
||||
- Write specific unit tests for this package
|
||||
|
||||
=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
|
||||
87
database/perl/vendor/lib/PPI/Statement/Include/Perl6.pm
vendored
Normal file
87
database/perl/vendor/lib/PPI/Statement/Include/Perl6.pm
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
package PPI::Statement::Include::Perl6;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Statement::Include::Perl6 - Inline Perl 6 file section
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use v6-alpha;
|
||||
|
||||
grammar My::Grammar {
|
||||
...
|
||||
}
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Statement::Include::Perl6
|
||||
isa PPI::Statement::Include
|
||||
isa PPI::Statement
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A C<PPI::Statement::Include::Perl6> is a special include statement that
|
||||
indicates the start of a section of Perl 6 code inlined into a regular
|
||||
Perl 5 code file.
|
||||
|
||||
The primary purpose of the class is to allow L<PPI> to provide at least
|
||||
basic support for "6 in 5" modules like v6.pm;
|
||||
|
||||
Currently, PPI only supports starting a Perl 6 block. It does not
|
||||
currently support changing back to Perl 5 again. Additionally all POD
|
||||
and __DATA__ blocks and __END__ blocks will be included in the Perl 6
|
||||
string and will not be parsed by PPI.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Statement::Include ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Statement::Include";
|
||||
|
||||
=pod
|
||||
|
||||
=head2 perl6
|
||||
|
||||
The C<perl6> method returns the block of Perl 6 code that is attached to
|
||||
the "use v6...;" command.
|
||||
|
||||
=cut
|
||||
|
||||
sub perl6 {
|
||||
$_[0]->{perl6};
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 TO DO
|
||||
|
||||
- Write specific unit tests for this package
|
||||
|
||||
=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
|
||||
75
database/perl/vendor/lib/PPI/Statement/Null.pm
vendored
Normal file
75
database/perl/vendor/lib/PPI/Statement/Null.pm
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
package PPI::Statement::Null;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Statement::Null - A useless null statement
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $foo = 1;
|
||||
|
||||
; # <-- Null statement
|
||||
|
||||
my $bar = 1;
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Statement::Null
|
||||
isa PPI::Statement
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<PPI::Statement::Null> is a utility class designed to handle situations
|
||||
where PPI encounters a naked statement separator.
|
||||
|
||||
Although strictly speaking, the semicolon is a statement B<separator>
|
||||
and not a statement B<terminator>, PPI considers a semicolon to be a
|
||||
statement terminator under most circumstances.
|
||||
|
||||
In any case, the null statement has no purpose, and can be safely deleted
|
||||
with no ill effect.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Statement::Null> has no additional methods beyond the default ones
|
||||
provided by L<PPI::Statement>, L<PPI::Node> and L<PPI::Element>.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Statement ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Statement";
|
||||
|
||||
# A null statement is not significant
|
||||
sub significant() { '' }
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
145
database/perl/vendor/lib/PPI/Statement/Package.pm
vendored
Normal file
145
database/perl/vendor/lib/PPI/Statement/Package.pm
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
package PPI::Statement::Package;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Statement::Package - A package statement
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Statement::Package
|
||||
isa PPI::Statement
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Most L<PPI::Statement> subclasses are assigned based on the value of the
|
||||
first token or word found in the statement. When PPI encounters a statement
|
||||
starting with 'package', it converts it to a C<PPI::Statement::Package>
|
||||
object.
|
||||
|
||||
When working with package statements, please remember that packages only
|
||||
exist within their scope, and proper support for scoping has yet to be
|
||||
completed in PPI.
|
||||
|
||||
However, if the immediate parent of the package statement is the
|
||||
top level L<PPI::Document> object, then it can be considered to define
|
||||
everything found until the next top-level "file scoped" package statement.
|
||||
|
||||
A file may, however, contain nested temporary package, in which case you
|
||||
are mostly on your own :)
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Statement::Package> has a number of methods in addition to the standard
|
||||
L<PPI::Statement>, L<PPI::Node> and L<PPI::Element> methods.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Statement ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Statement";
|
||||
|
||||
# Lexer clues
|
||||
sub __LEXER__normal() { '' }
|
||||
|
||||
=pod
|
||||
|
||||
=head2 namespace
|
||||
|
||||
Most package declarations are simple, and just look something like
|
||||
|
||||
package Foo::Bar;
|
||||
|
||||
The C<namespace> method returns the name of the declared package, in the
|
||||
above case 'Foo::Bar'. It returns this exactly as written and does not
|
||||
attempt to clean up or resolve things like ::Foo to main::Foo.
|
||||
|
||||
If the package statement is done any different way, it returns false.
|
||||
|
||||
=cut
|
||||
|
||||
sub namespace {
|
||||
my $self = shift;
|
||||
my $namespace = $self->schild(1) or return '';
|
||||
$namespace->isa('PPI::Token::Word')
|
||||
? $namespace->content
|
||||
: '';
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 version
|
||||
|
||||
Some package declarations may include a version:
|
||||
|
||||
package Foo::Bar 1.23;
|
||||
package Baz v1.23;
|
||||
|
||||
The C<version> method returns the stringified version as seen in the
|
||||
document (if any), otherwise the empty string.
|
||||
|
||||
=cut
|
||||
|
||||
sub version {
|
||||
my $self = shift;
|
||||
my $version = $self->schild(2) or return '';
|
||||
$version->isa('PPI::Token::Structure')
|
||||
? ''
|
||||
: $version->content;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 file_scoped
|
||||
|
||||
Regardless of whether it is named or not, the C<file_scoped> method will
|
||||
test to see if the package declaration is a top level "file scoped"
|
||||
statement or not, based on its location.
|
||||
|
||||
In general, returns true if it is a "file scoped" package declaration with
|
||||
an immediate parent of the top level Document, or false if not.
|
||||
|
||||
Note that if the PPI DOM tree B<does not> have a PPI::Document object at
|
||||
as the root element, this will return false. Likewise, it will also return
|
||||
false if the root element is a L<PPI::Document::Fragment>, as a fragment of
|
||||
a file does not represent a scope.
|
||||
|
||||
=cut
|
||||
|
||||
sub file_scoped {
|
||||
my $self = shift;
|
||||
my ($Parent, $Document) = ($self->parent, $self->top);
|
||||
$Parent and $Document and $Parent == $Document
|
||||
and $Document->isa('PPI::Document')
|
||||
and ! $Document->isa('PPI::Document::Fragment');
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
124
database/perl/vendor/lib/PPI/Statement/Scheduled.pm
vendored
Normal file
124
database/perl/vendor/lib/PPI/Statement/Scheduled.pm
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
package PPI::Statement::Scheduled;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Statement::Scheduled - A scheduled code block
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Statement::Scheduled
|
||||
isa PPI::Statement::Sub
|
||||
isa PPI::Statement
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A scheduled code block is one that is intended to be run at a specific
|
||||
time during the loading process.
|
||||
|
||||
There are five types of scheduled block:
|
||||
|
||||
BEGIN {
|
||||
# Executes as soon as this block is fully defined
|
||||
...
|
||||
}
|
||||
|
||||
CHECK {
|
||||
# Executes after overall compile-phase in reverse order
|
||||
...
|
||||
}
|
||||
|
||||
UNITCHECK {
|
||||
# Executes after compile-phase of individual module in reverse order
|
||||
...
|
||||
}
|
||||
|
||||
INIT {
|
||||
# Executes just before run-time
|
||||
...
|
||||
}
|
||||
|
||||
END {
|
||||
# Executes as late as possible in reverse order
|
||||
...
|
||||
}
|
||||
|
||||
Technically these scheduled blocks are actually subroutines, and in fact
|
||||
may have 'sub' in front of them.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Statement::Sub ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Statement::Sub";
|
||||
|
||||
sub __LEXER__normal() { '' }
|
||||
|
||||
sub _complete {
|
||||
my $child = $_[0]->schild(-1);
|
||||
return !! (
|
||||
defined $child
|
||||
and
|
||||
$child->isa('PPI::Structure::Block')
|
||||
and
|
||||
$child->complete
|
||||
);
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 type
|
||||
|
||||
The C<type> method returns the type of scheduled block, which should always be
|
||||
one of C<'BEGIN'>, C<'CHECK'>, C<'UNITCHECK'>, C<'INIT'> or C<'END'>.
|
||||
|
||||
=cut
|
||||
|
||||
sub type {
|
||||
my $self = shift;
|
||||
my @children = $self->schildren or return undef;
|
||||
$children[0]->content eq 'sub'
|
||||
? $children[1]->content
|
||||
: $children[0]->content;
|
||||
}
|
||||
|
||||
# This is actually the same as Sub->name
|
||||
sub name {
|
||||
shift->type(@_);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 TO DO
|
||||
|
||||
- Write unit tests for this package
|
||||
|
||||
=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
|
||||
221
database/perl/vendor/lib/PPI/Statement/Sub.pm
vendored
Normal file
221
database/perl/vendor/lib/PPI/Statement/Sub.pm
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
package PPI::Statement::Sub;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Statement::Sub - Subroutine declaration
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Statement::Sub
|
||||
isa PPI::Statement
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Except for the special BEGIN, CHECK, UNITCHECK, INIT, and END subroutines
|
||||
(which are part of L<PPI::Statement::Scheduled>) all subroutine declarations
|
||||
are lexed as a PPI::Statement::Sub object.
|
||||
|
||||
Primarily, this means all of the various C<sub foo {}> statements, but also
|
||||
forward declarations such as C<sub foo;> or C<sub foo($);>. It B<does not>
|
||||
include anonymous subroutines, as these are merely part of a normal statement.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Statement::Sub> has a number of methods in addition to the standard
|
||||
L<PPI::Statement>, L<PPI::Node> and L<PPI::Element> methods.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use List::Util ();
|
||||
use Params::Util qw{_INSTANCE};
|
||||
use PPI::Statement ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Statement";
|
||||
|
||||
# Lexer clue
|
||||
sub __LEXER__normal() { '' }
|
||||
|
||||
sub _complete {
|
||||
my $child = $_[0]->schild(-1);
|
||||
return !! (
|
||||
defined $child
|
||||
and
|
||||
$child->isa('PPI::Structure::Block')
|
||||
and
|
||||
$child->complete
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Statement::Sub Methods
|
||||
|
||||
=pod
|
||||
|
||||
=head2 name
|
||||
|
||||
The C<name> method returns the name of the subroutine being declared.
|
||||
|
||||
In some rare cases such as a naked C<sub> at the end of the file, this may return
|
||||
false.
|
||||
|
||||
=cut
|
||||
|
||||
sub name {
|
||||
my ($self) = @_;
|
||||
|
||||
# Usually the second token is the name.
|
||||
my $token = $self->schild(1);
|
||||
return $token->content
|
||||
if defined $token and $token->isa('PPI::Token::Word');
|
||||
|
||||
# In the case of special subs whose 'sub' can be omitted (AUTOLOAD
|
||||
# or DESTROY), the name will be the first token.
|
||||
$token = $self->schild(0);
|
||||
return $token->content
|
||||
if defined $token and $token->isa('PPI::Token::Word');
|
||||
return '';
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 prototype
|
||||
|
||||
If it has one, the C<prototype> method returns the subroutine's prototype.
|
||||
It is returned in the same format as L<PPI::Token::Prototype/prototype>,
|
||||
cleaned and removed from its brackets.
|
||||
|
||||
Returns the subroutine's prototype, or undef if the subroutine does not
|
||||
define one. Note that when the sub has an empty prototype (C<()>) the
|
||||
return is an empty string.
|
||||
|
||||
=cut
|
||||
|
||||
sub prototype {
|
||||
my $self = shift;
|
||||
my $Prototype = List::Util::first {
|
||||
_INSTANCE($_, 'PPI::Token::Prototype')
|
||||
} $self->children;
|
||||
defined($Prototype) ? $Prototype->prototype : undef;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 block
|
||||
|
||||
With its name and implementation shared with L<PPI::Statement::Scheduled>,
|
||||
the C<block> method finds and returns the actual Structure object of the
|
||||
code block for this subroutine.
|
||||
|
||||
Returns false if this is a forward declaration, or otherwise does not have a
|
||||
code block.
|
||||
|
||||
=cut
|
||||
|
||||
sub block {
|
||||
my $self = shift;
|
||||
my $lastchild = $self->schild(-1) or return '';
|
||||
$lastchild->isa('PPI::Structure::Block') and $lastchild;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 forward
|
||||
|
||||
The C<forward> method returns true if the subroutine declaration is a
|
||||
forward declaration.
|
||||
|
||||
That is, it returns false if the subroutine has a code block, or true
|
||||
if it does not.
|
||||
|
||||
=cut
|
||||
|
||||
sub forward {
|
||||
! shift->block;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 reserved
|
||||
|
||||
The C<reserved> method provides a convenience method for checking to see
|
||||
if this is a special reserved subroutine. It does not check against any
|
||||
particular list of reserved sub names, but just returns true if the name
|
||||
is all uppercase, as defined in L<perlsub>.
|
||||
|
||||
Note that in the case of BEGIN, CHECK, UNITCHECK, INIT and END, these will be
|
||||
defined as L<PPI::Statement::Scheduled> objects, not subroutines.
|
||||
|
||||
Returns true if it is a special reserved subroutine, or false if not.
|
||||
|
||||
=cut
|
||||
|
||||
sub reserved {
|
||||
my $self = shift;
|
||||
my $name = $self->name or return '';
|
||||
# perlsub is silent on whether reserveds can contain:
|
||||
# - underscores;
|
||||
# we allow them due to existing practice like CLONE_SKIP and __SUB__.
|
||||
# - numbers; we allow them by PPI tradition.
|
||||
$name eq uc $name;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 type
|
||||
|
||||
The C<type> method checks and returns the declaration type of the statement,
|
||||
which will be one of 'my', 'our', or 'state'.
|
||||
|
||||
Returns a string of the type, or C<undef> if the type is not declared.
|
||||
|
||||
=cut
|
||||
|
||||
sub type {
|
||||
my $self = shift;
|
||||
|
||||
# Get the first significant child
|
||||
my @schild = grep { $_->significant } $self->children;
|
||||
|
||||
# Ignore labels
|
||||
shift @schild if _INSTANCE($schild[0], 'PPI::Token::Label');
|
||||
|
||||
# Get the type
|
||||
(_INSTANCE($schild[0], 'PPI::Token::Word') and $schild[0]->content =~ /^(my|our|state)$/)
|
||||
? $schild[0]->content
|
||||
: undef;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
68
database/perl/vendor/lib/PPI/Statement/Unknown.pm
vendored
Normal file
68
database/perl/vendor/lib/PPI/Statement/Unknown.pm
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
package PPI::Statement::Unknown;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Statement::Unknown - An unknown or transient statement
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Statement::Unknown
|
||||
isa PPI::Statement
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The C<PPI::Statement::Unknown> class is used primarily during the lexing
|
||||
process to hold elements that are known to be statement, but for which
|
||||
the exact C<type> of statement is as yet unknown, and requires further
|
||||
tokens in order to resolve the correct type.
|
||||
|
||||
They should not exist in a fully parse B<valid> document, and if any
|
||||
exists they indicate either a problem in Document, or possibly (by
|
||||
allowing it to get through unresolved) a bug in L<PPI::Lexer>.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Statement::Unknown> has no additional methods beyond the
|
||||
default ones provided by L<PPI::Statement>, L<PPI::Node> and
|
||||
L<PPI::Element>.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Statement ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Statement";
|
||||
|
||||
# If one of these ends up in the final document,
|
||||
# we're pretty much screwed. Just call it a day.
|
||||
sub _complete () { 1 }
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
80
database/perl/vendor/lib/PPI/Statement/UnmatchedBrace.pm
vendored
Normal file
80
database/perl/vendor/lib/PPI/Statement/UnmatchedBrace.pm
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
package PPI::Statement::UnmatchedBrace;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Statement::UnmatchedBrace - Isolated unmatched brace
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
sub foo {
|
||||
1;
|
||||
}
|
||||
|
||||
} # <--- This is an unmatched brace
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Statement::UnmatchedBrace
|
||||
isa PPI::Statement
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The C<PPI::Statement::UnmatchedBrace> class is a miscellaneous utility
|
||||
class. Objects of this type should be rare, or not exist at all in normal
|
||||
valid L<PPI::Document> objects.
|
||||
|
||||
It can be either a round ')', square ']' or curly '}' brace, this class
|
||||
does not distinguish. Objects of this type are only allocated at a
|
||||
structural level, not a lexical level (as they are lexically invalid
|
||||
anyway).
|
||||
|
||||
The presence of a C<PPI::Statement::UnmatchedBrace> indicated a broken
|
||||
or invalid document. Or maybe a bug in PPI, but B<far> more likely a
|
||||
broken Document. :)
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Statement::UnmatchedBrace> has no additional methods beyond the
|
||||
default ones provided by L<PPI::Statement>, L<PPI::Node> and
|
||||
L<PPI::Element>.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Statement ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Statement";
|
||||
|
||||
# Once we've hit a naked unmatched brace we can never truly be complete.
|
||||
# So instead we always just call it a day...
|
||||
sub _complete () { 1 }
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
195
database/perl/vendor/lib/PPI/Statement/Variable.pm
vendored
Normal file
195
database/perl/vendor/lib/PPI/Statement/Variable.pm
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
package PPI::Statement::Variable;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Statement::Variable - Variable declaration statements
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
# All of the following are variable declarations
|
||||
my $foo = 1;
|
||||
my ($foo, $bar) = (1, 2);
|
||||
our $foo = 1;
|
||||
local $foo;
|
||||
local $foo = 1;
|
||||
LABEL: my $foo = 1;
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Statement::Variable
|
||||
isa PPI::Statement::Expression
|
||||
isa PPI::Statement
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The main intent of the C<PPI::Statement::Variable> class is to describe
|
||||
simple statements that explicitly declare new local or global variables.
|
||||
|
||||
Note that this does not make it exclusively the only place where variables
|
||||
are defined, and later on you should expect that the C<variables> method
|
||||
will migrate deeper down the tree to either L<PPI::Statement> or
|
||||
L<PPI::Node> to recognise this fact, but for now it stays here.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Params::Util qw{_INSTANCE};
|
||||
use PPI::Statement::Expression ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Statement::Expression";
|
||||
|
||||
=pod
|
||||
|
||||
=head2 type
|
||||
|
||||
The C<type> method checks and returns the declaration type of the statement,
|
||||
which will be one of 'my', 'local', 'our', or 'state'.
|
||||
|
||||
Returns a string of the type, or C<undef> if the type cannot be detected
|
||||
(which is probably a bug).
|
||||
|
||||
=cut
|
||||
|
||||
sub type {
|
||||
my $self = shift;
|
||||
|
||||
# Get the first significant child
|
||||
my @schild = grep { $_->significant } $self->children;
|
||||
|
||||
# Ignore labels
|
||||
shift @schild if _INSTANCE($schild[0], 'PPI::Token::Label');
|
||||
|
||||
# Get the type
|
||||
(_INSTANCE($schild[0], 'PPI::Token::Word') and $schild[0]->content =~ /^(my|local|our|state)$/)
|
||||
? $schild[0]->content
|
||||
: undef;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 variables
|
||||
|
||||
As for several other PDOM Element types that can declare variables, the
|
||||
C<variables> method returns a list of the canonical forms of the variables
|
||||
defined by the statement.
|
||||
|
||||
Returns a list of the canonical string forms of variables, or the null list
|
||||
if it is unable to find any variables.
|
||||
|
||||
=cut
|
||||
|
||||
sub variables {
|
||||
map { $_->canonical } $_[0]->symbols;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 symbols
|
||||
|
||||
Returns a list of the variables defined by the statement, as
|
||||
L<PPI::Token::Symbol>s.
|
||||
|
||||
=cut
|
||||
|
||||
sub symbols {
|
||||
my $self = shift;
|
||||
|
||||
# Get the children we care about
|
||||
my @schild = grep { $_->significant } $self->children;
|
||||
shift @schild if _INSTANCE($schild[0], 'PPI::Token::Label');
|
||||
|
||||
# If the second child is a symbol, return its name
|
||||
if ( _INSTANCE($schild[1], 'PPI::Token::Symbol') ) {
|
||||
return $schild[1];
|
||||
}
|
||||
|
||||
# If it's a list, return as a list
|
||||
if ( _INSTANCE($schild[1], 'PPI::Structure::List') ) {
|
||||
my $Expression = $schild[1]->schild(0);
|
||||
$Expression and
|
||||
$Expression->isa('PPI::Statement::Expression') or return ();
|
||||
|
||||
# my and our are simpler than local
|
||||
if (
|
||||
$self->type eq 'my'
|
||||
or
|
||||
$self->type eq 'our'
|
||||
or
|
||||
$self->type eq 'state'
|
||||
) {
|
||||
return grep {
|
||||
$_->isa('PPI::Token::Symbol')
|
||||
} $Expression->schildren;
|
||||
}
|
||||
|
||||
# Local is much more icky (potentially).
|
||||
# Not that we are actually going to deal with it now,
|
||||
# but having this separate is likely going to be needed
|
||||
# for future bug reports about local() things.
|
||||
|
||||
# This is a slightly better way to check.
|
||||
return grep {
|
||||
$self->_local_variable($_)
|
||||
} grep {
|
||||
$_->isa('PPI::Token::Symbol')
|
||||
} $Expression->schildren;
|
||||
}
|
||||
|
||||
# erm... this is unexpected
|
||||
();
|
||||
}
|
||||
|
||||
sub _local_variable {
|
||||
my ($self, $el) = @_;
|
||||
|
||||
# The last symbol should be a variable
|
||||
my $n = $el->snext_sibling or return 1;
|
||||
my $p = $el->sprevious_sibling;
|
||||
if ( ! $p or $p eq ',' ) {
|
||||
# In the middle of a list
|
||||
return 1 if $n eq ',';
|
||||
|
||||
# The first half of an assignment
|
||||
return 1 if $n eq '=';
|
||||
}
|
||||
|
||||
# Lets say no for know... additional work
|
||||
# should go here.
|
||||
return '';
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 TO DO
|
||||
|
||||
- Write unit tests for this
|
||||
|
||||
=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
|
||||
100
database/perl/vendor/lib/PPI/Statement/When.pm
vendored
Normal file
100
database/perl/vendor/lib/PPI/Statement/When.pm
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
package PPI::Statement::When;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Statement::When - A when statement
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
foreach ( qw/ foo bar baz / ) {
|
||||
when ( m/b/ ) {
|
||||
boing($_);
|
||||
}
|
||||
when ( m/f/ ) {
|
||||
boom($_);
|
||||
}
|
||||
default {
|
||||
tchak($_);
|
||||
}
|
||||
}
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Statement::When
|
||||
isa PPI::Statement
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<PPI::Statement::When> objects are used to describe when and default
|
||||
statements, as described in L<perlsyn>.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Structure::When> has no methods beyond those provided by the
|
||||
standard L<PPI::Structure>, L<PPI::Node> and L<PPI::Element> methods.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Statement ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Statement";
|
||||
|
||||
# Lexer clues
|
||||
sub __LEXER__normal() { '' }
|
||||
|
||||
sub _complete {
|
||||
my $child = $_[0]->schild(-1);
|
||||
return !! (
|
||||
defined $child
|
||||
and
|
||||
$child->isa('PPI::Structure::Block')
|
||||
and
|
||||
$child->complete
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Node Methods
|
||||
|
||||
sub scope() {
|
||||
1;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 TO DO
|
||||
|
||||
- Write unit tests for this package
|
||||
|
||||
=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
|
||||
347
database/perl/vendor/lib/PPI/Structure.pm
vendored
Normal file
347
database/perl/vendor/lib/PPI/Structure.pm
vendored
Normal file
@@ -0,0 +1,347 @@
|
||||
package PPI::Structure;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Structure - The base class for Perl braced structures
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Structure
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
PPI::Structure is the root class for all Perl bracing structures. This
|
||||
covers all forms of C< [ ... ] >, C< { ... } >, and C< ( ... ) > brace
|
||||
types, and includes cases where only one half of the pair exist.
|
||||
|
||||
The class PPI::Structure itself is full abstract and no objects of that
|
||||
type should actually exist in the tree.
|
||||
|
||||
=head2 Elements vs Children
|
||||
|
||||
A B<PPI::Structure> has an unusual existence. Unlike a L<PPI::Document>
|
||||
or L<PPI::Statement>, which both simply contain other elements, a
|
||||
structure B<both> contains and consists of content.
|
||||
|
||||
That is, the brace tokens are B<not> considered to be "children" of the
|
||||
structure, but are part of it.
|
||||
|
||||
In practice, this will mean that while the -E<gt>elements and -E<gt>tokens
|
||||
methods (and related) B<will> return a list with the brace tokens at either
|
||||
end, the -E<gt>children method explicitly will B<not> return the brace.
|
||||
|
||||
=head1 STRUCTURE CLASSES
|
||||
|
||||
Excluding the transient L<PPI::Structure::Unknown> that exists briefly
|
||||
inside the parser, there are eight types of structure.
|
||||
|
||||
=head2 L<PPI::Structure::List>
|
||||
|
||||
This covers all round braces used for function arguments, in C<foreach>
|
||||
loops, literal lists, and braces used for precedence-ordering purposes.
|
||||
|
||||
=head2 L<PPI::Structure::For>
|
||||
|
||||
Although B<not> used for the C<foreach> loop list, this B<is> used for
|
||||
the special case of the round-brace three-part semicolon-separated C<for>
|
||||
loop expression (the traditional C style for loop).
|
||||
|
||||
=head2 L<PPI::Structure::Given>
|
||||
|
||||
This is for the expression being matched in switch statements.
|
||||
|
||||
=head2 L<PPI::Structure::When>
|
||||
|
||||
This is for the matching expression in "when" statements.
|
||||
|
||||
=head2 L<PPI::Structure::Condition>
|
||||
|
||||
This round-brace structure covers boolean conditional braces, such as
|
||||
for C<if> and C<while> blocks.
|
||||
|
||||
=head2 L<PPI::Structure::Block>
|
||||
|
||||
This curly-brace and common structure is used for all form of code
|
||||
blocks. This includes those for C<if>, C<do> and similar, as well
|
||||
as C<grep>, C<map>, C<sort>, C<sub> and (labelled or anonymous)
|
||||
scoping blocks.
|
||||
|
||||
=head2 L<PPI::Structure::Constructor>
|
||||
|
||||
This class covers brace structures used for the construction of
|
||||
anonymous C<ARRAY> and C<HASH> references.
|
||||
|
||||
=head2 L<PPI::Structure::Subscript>
|
||||
|
||||
This class covers square-braces and curly-braces used after a
|
||||
-E<gt> pointer to access the subscript of an C<ARRAY> or C<HASH>.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Structure> 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::Structure::Block ();
|
||||
use PPI::Structure::Condition ();
|
||||
use PPI::Structure::Constructor ();
|
||||
use PPI::Structure::For ();
|
||||
use PPI::Structure::Given ();
|
||||
use PPI::Structure::List ();
|
||||
use PPI::Structure::Subscript ();
|
||||
use PPI::Structure::Unknown ();
|
||||
use PPI::Structure::When ();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Constructor
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my $Token = PPI::Token::__LEXER__opens($_[0]) ? shift : return undef;
|
||||
|
||||
# Create the object
|
||||
my $self = bless {
|
||||
children => [],
|
||||
start => $Token,
|
||||
}, $class;
|
||||
|
||||
# Set the start braces parent link
|
||||
Scalar::Util::weaken(
|
||||
$_PARENT{Scalar::Util::refaddr $Token} = $self
|
||||
);
|
||||
|
||||
$self;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Structure API methods
|
||||
|
||||
=pod
|
||||
|
||||
=head2 start
|
||||
|
||||
For lack of better terminology (like "open" and "close") that has not
|
||||
already in use for some other more important purpose, the two individual
|
||||
braces for the structure are known within PPI as the "start" and "finish"
|
||||
braces (at least for method purposes).
|
||||
|
||||
The C<start> method returns the start brace for the structure (i.e. the
|
||||
opening brace).
|
||||
|
||||
Returns the brace as a L<PPI::Token::Structure> or C<undef> if the
|
||||
structure does not have a starting brace.
|
||||
|
||||
Under normal parsing circumstances this should never occur, but may happen
|
||||
due to manipulation of the PDOM tree.
|
||||
|
||||
=cut
|
||||
|
||||
sub start { $_[0]->{start} }
|
||||
|
||||
=pod
|
||||
|
||||
=head2 finish
|
||||
|
||||
The C<finish> method returns the finish brace for the structure (i.e. the
|
||||
closing brace).
|
||||
|
||||
Returns the brace as a L<PPI::Token::Structure> or C<undef> if the
|
||||
structure does not have a finishing brace. This can be quite common if
|
||||
the document is not complete (for example, from an editor where the user
|
||||
may be halfway through typeing a subroutine).
|
||||
|
||||
=cut
|
||||
|
||||
sub finish { $_[0]->{finish} }
|
||||
|
||||
=pod
|
||||
|
||||
=head2 braces
|
||||
|
||||
The C<braces> method is a utility method which returns the brace type,
|
||||
regardless of whether both or just one of the braces is defined.
|
||||
|
||||
Returns one of the three strings C<'[]'>, C<'{}'>, or C<'()'>, or C<undef>
|
||||
on error (primarily not having a start brace, as mentioned above).
|
||||
|
||||
=cut
|
||||
|
||||
sub braces {
|
||||
my $self = $_[0]->{start} ? shift : return undef;
|
||||
return {
|
||||
'[' => '[]',
|
||||
'(' => '()',
|
||||
'{' => '{}',
|
||||
}->{ $self->{start}->{content} };
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head1 complete
|
||||
|
||||
The C<complete> method is a convenience method that returns true if
|
||||
the both braces are defined for the structure, or false if only one
|
||||
brace is defined.
|
||||
|
||||
Unlike the top level C<complete> method which checks for completeness
|
||||
in depth, the structure complete method ONLY confirms completeness
|
||||
for the braces, and does not recurse downwards.
|
||||
|
||||
=cut
|
||||
|
||||
sub complete {
|
||||
!! ($_[0]->{start} and $_[0]->{finish});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Node overloaded methods
|
||||
|
||||
# For us, the "elements" concept includes the brace tokens
|
||||
sub elements {
|
||||
my $self = shift;
|
||||
|
||||
if ( wantarray ) {
|
||||
# Return a list in array context
|
||||
return ( $self->{start} || (), @{$self->{children}}, $self->{finish} || () );
|
||||
} else {
|
||||
# Return the number of elements in scalar context.
|
||||
# This is memory-cheaper than creating another big array
|
||||
return scalar(@{$self->{children}})
|
||||
+ ($self->{start} ? 1 : 0)
|
||||
+ ($self->{finish} ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
# For us, the first element is probably the opening brace
|
||||
sub first_element {
|
||||
# Technically, if we have no children and no opening brace,
|
||||
# then the first element is the closing brace.
|
||||
$_[0]->{start} or $_[0]->{children}->[0] or $_[0]->{finish};
|
||||
}
|
||||
|
||||
# For us, the last element is probably the closing brace
|
||||
sub last_element {
|
||||
# Technically, if we have no children and no closing brace,
|
||||
# then the last element is the opening brace
|
||||
$_[0]->{finish} or $_[0]->{children}->[-1] or $_[0]->{start};
|
||||
}
|
||||
|
||||
# Location is same as the start token, if any
|
||||
sub location {
|
||||
my $self = shift;
|
||||
my $first = $self->first_element or return undef;
|
||||
$first->location;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Element overloaded methods
|
||||
|
||||
# Get the full set of tokens, including start and finish
|
||||
sub tokens {
|
||||
my $self = shift;
|
||||
my @tokens = (
|
||||
$self->{start} || (),
|
||||
$self->SUPER::tokens(@_),
|
||||
$self->{finish} || (),
|
||||
);
|
||||
@tokens;
|
||||
}
|
||||
|
||||
# Like the token method ->content, get our merged contents.
|
||||
# This will recurse downwards through everything
|
||||
### Reimplement this using List::Utils stuff
|
||||
sub content {
|
||||
my $self = shift;
|
||||
my $content = $self->{start} ? $self->{start}->content : '';
|
||||
foreach my $child ( @{$self->{children}} ) {
|
||||
$content .= $child->content;
|
||||
}
|
||||
$content .= $self->{finish}->content if $self->{finish};
|
||||
$content;
|
||||
}
|
||||
|
||||
# Is the structure completed
|
||||
sub _complete {
|
||||
!! ( defined $_[0]->{finish} );
|
||||
}
|
||||
|
||||
# You can insert either another structure, or a token
|
||||
sub insert_before {
|
||||
my $self = shift;
|
||||
my $Element = _INSTANCE(shift, 'PPI::Element') or return undef;
|
||||
if ( $Element->isa('PPI::Structure') ) {
|
||||
return $self->__insert_before($Element);
|
||||
} elsif ( $Element->isa('PPI::Token') ) {
|
||||
return $self->__insert_before($Element);
|
||||
}
|
||||
'';
|
||||
}
|
||||
|
||||
# As above, you can insert either another structure, or a token
|
||||
sub insert_after {
|
||||
my $self = shift;
|
||||
my $Element = _INSTANCE(shift, 'PPI::Element') or return undef;
|
||||
if ( $Element->isa('PPI::Structure') ) {
|
||||
return $self->__insert_after($Element);
|
||||
} elsif ( $Element->isa('PPI::Token') ) {
|
||||
return $self->__insert_after($Element);
|
||||
}
|
||||
'';
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
82
database/perl/vendor/lib/PPI/Structure/Block.pm
vendored
Normal file
82
database/perl/vendor/lib/PPI/Structure/Block.pm
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
package PPI::Structure::Block;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Structure::Block - Curly braces representing a code block
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
sub foo { ... }
|
||||
|
||||
grep { ... } @list;
|
||||
|
||||
if ( condition ) {
|
||||
...
|
||||
}
|
||||
|
||||
LABEL: {
|
||||
...
|
||||
}
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Structure::Block
|
||||
isa PPI::Structure
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<PPI::Structure::Block> is the class used for all curly braces that
|
||||
represent code blocks. This includes subroutines, compound statements
|
||||
and any other block braces.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Structure::Block> has no methods beyond those provided by the
|
||||
standard L<PPI::Structure>, L<PPI::Node> and L<PPI::Element> methods.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Structure ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Structure";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Element Methods
|
||||
|
||||
# This is a scope boundary
|
||||
sub scope() { 1 }
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
67
database/perl/vendor/lib/PPI/Structure/Condition.pm
vendored
Normal file
67
database/perl/vendor/lib/PPI/Structure/Condition.pm
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
package PPI::Structure::Condition;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Structure::Condition - Round braces for boolean context conditions
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
if ( condition ) {
|
||||
...
|
||||
}
|
||||
|
||||
while ( condition ) {
|
||||
...
|
||||
}
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Structure::Condition
|
||||
isa PPI::Structure
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<PPI::Structure::Condition> is the class used for all round braces
|
||||
that represent boolean contexts used in various conditions.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Structure::Condition> has no methods beyond those provided by
|
||||
the standard L<PPI::Structure>, L<PPI::Node> and L<PPI::Element> methods.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Structure ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Structure";
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
62
database/perl/vendor/lib/PPI/Structure/Constructor.pm
vendored
Normal file
62
database/perl/vendor/lib/PPI/Structure/Constructor.pm
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
package PPI::Structure::Constructor;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Structure::Constructor - Anonymous hash or array constructor
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $array = [ 'foo', 'bar' ];
|
||||
my $hash = { foo => 'bar' };
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Structure::Constructor
|
||||
isa PPI::Structure
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<PPI::Structure::Constructor> is the class used for anonymous C<ARRAY>
|
||||
reference of C<HASH> reference constructors.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Structure::Constructor> has no methods beyond those provided by
|
||||
the standard L<PPI::Structure>, L<PPI::Node> and L<PPI::Element> methods.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Structure ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Structure";
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
77
database/perl/vendor/lib/PPI/Structure/For.pm
vendored
Normal file
77
database/perl/vendor/lib/PPI/Structure/For.pm
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
package PPI::Structure::For;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Structure::For - Circular braces for a for expression
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
for ( var $i = 0; $i < $max; $i++ ) {
|
||||
...
|
||||
}
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Structure::For
|
||||
isa PPI::Structure
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<PPI::Structure::For> is the class used for circular braces that
|
||||
contain the three part C<for> expression.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Structure::For> has no methods beyond those provided by the
|
||||
standard L<PPI::Structure>, L<PPI::Node> and L<PPI::Element> methods.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Structure ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Structure";
|
||||
|
||||
# Highly special custom isa method that will continue to respond
|
||||
# positively to ->isa('PPI::Structure::ForLoop') but warns.
|
||||
my $has_warned = 0;
|
||||
sub isa {
|
||||
if ( $_[1] and $_[1] eq 'PPI::Structure::ForLoop' ) {
|
||||
unless ( $has_warned ) {
|
||||
warn("PPI::Structure::ForLoop has been deprecated");
|
||||
$has_warned = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return shift->SUPER::isa(@_);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
63
database/perl/vendor/lib/PPI/Structure/Given.pm
vendored
Normal file
63
database/perl/vendor/lib/PPI/Structure/Given.pm
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
package PPI::Structure::Given;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Structure::Given - Circular braces for a switch statement
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
given ( something ) {
|
||||
...
|
||||
}
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Structure::Given
|
||||
isa PPI::Structure
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<PPI::Structure::Given> is the class used for circular braces that
|
||||
contain the thing to be matched in a switch statement.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Structure::Given> has no methods beyond those provided by the
|
||||
standard L<PPI::Structure>, L<PPI::Node> and L<PPI::Element> methods.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Structure ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Structure";
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
87
database/perl/vendor/lib/PPI/Structure/List.pm
vendored
Normal file
87
database/perl/vendor/lib/PPI/Structure/List.pm
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
package PPI::Structure::List;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Structure::List - Explicit list or precedence ordering braces
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
# A list used for params
|
||||
function( 'param', 'param' );
|
||||
|
||||
# Explicit list
|
||||
return ( 'foo', 'bar' );
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Structure::List
|
||||
isa PPI::Structure
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<PPI::Structure::List> is the class used for circular braces that
|
||||
represent lists, and related.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Structure::List> has no methods beyond those provided by the
|
||||
standard L<PPI::Structure>, L<PPI::Node> and L<PPI::Element> methods.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Carp ();
|
||||
use PPI::Structure ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Structure";
|
||||
|
||||
# Highly special custom isa method that will continue to respond
|
||||
# positively to ->isa('PPI::Structure::ForLoop') but warns.
|
||||
my $has_warned = 0;
|
||||
sub isa {
|
||||
if ( $_[1] and $_[1] eq 'PPI::Structure::ForLoop' ) {
|
||||
if (
|
||||
$_[0]->parent->isa('PPI::Statement::Compound')
|
||||
and
|
||||
$_[0]->parent->type =~ /^for/
|
||||
) {
|
||||
unless ( $has_warned ) {
|
||||
local $Carp::CarpLevel = $Carp::CarpLevel + 1;
|
||||
Carp::carp("PPI::Structure::ForLoop has been deprecated");
|
||||
$has_warned = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return shift->SUPER::isa(@_);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
68
database/perl/vendor/lib/PPI/Structure/Subscript.pm
vendored
Normal file
68
database/perl/vendor/lib/PPI/Structure/Subscript.pm
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
package PPI::Structure::Subscript;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Structure::Subscript - Braces that represent an array or hash subscript
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
# The end braces for all of the following are subscripts
|
||||
$foo->[...]
|
||||
$foo[...]
|
||||
$foo{...}[...]
|
||||
$foo->{...}
|
||||
$foo{...}
|
||||
$foo[]{...}
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Structure::Subscript
|
||||
isa PPI::Structure
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<PPI::Structure::Subscript> is the class used for square and curly
|
||||
braces that specify one element of an array or hash (or a slice/subset
|
||||
of an array or hash)
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Structure::Subscript> has no methods beyond those provided by the
|
||||
standard L<PPI::Structure>, L<PPI::Node> and L<PPI::Element> methods.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Structure ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Structure";
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
69
database/perl/vendor/lib/PPI/Structure/Unknown.pm
vendored
Normal file
69
database/perl/vendor/lib/PPI/Structure/Unknown.pm
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
package PPI::Structure::Unknown;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Structure::Unknown - An unknown or unresolved brace structure
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Structure::Unknown
|
||||
isa PPI::Structure
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<PPI::Structure::Unknown> is class for braces whose type is unknown, or
|
||||
temporarily unknown.
|
||||
|
||||
It primarily exists temporarily inside the lexer. Although some types of
|
||||
braces can be determined immediately at opening, there are a number of
|
||||
different brace types that can only be correctly identified after the
|
||||
braces are closed.
|
||||
|
||||
A structure is typed as unknown during this period it is indeterminate.
|
||||
|
||||
A C<PPI::Structure::Unknown> object should not B<ever> make it out of the
|
||||
lexer without being converted to its final type. Any time you encounter
|
||||
this class in a PDOM tree it should be considered a bug and reported
|
||||
accordingly.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Structure::Unknown> has no methods beyond those provided by the
|
||||
standard L<PPI::Structure>, L<PPI::Node> and L<PPI::Element> methods.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Structure ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Structure";
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
63
database/perl/vendor/lib/PPI/Structure/When.pm
vendored
Normal file
63
database/perl/vendor/lib/PPI/Structure/When.pm
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
package PPI::Structure::When;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Structure::When - Circular braces for a when statement
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
when ( something ) {
|
||||
...
|
||||
}
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Structure::When
|
||||
isa PPI::Structure
|
||||
isa PPI::Node
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<PPI::Structure::When> is the class used for circular braces that
|
||||
contain the thing to be matched in a when statement.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Structure::When> has no methods beyond those provided by the
|
||||
standard L<PPI::Structure>, L<PPI::Node> and L<PPI::Element> methods.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Structure ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Structure";
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
245
database/perl/vendor/lib/PPI/Token.pm
vendored
Normal file
245
database/perl/vendor/lib/PPI/Token.pm
vendored
Normal file
@@ -0,0 +1,245 @@
|
||||
package PPI::Token;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token - A single token of Perl source code
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<PPI::Token> is the abstract base class for all Tokens. In PPI terms, a "Token" is
|
||||
a L<PPI::Element> that directly represents bytes of source code.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Params::Util qw{_INSTANCE};
|
||||
use PPI::Element ();
|
||||
use PPI::Exception ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = 'PPI::Element';
|
||||
|
||||
# We don't load the abstracts, they are loaded
|
||||
# as part of the inheritance process.
|
||||
|
||||
# Load the token classes
|
||||
use PPI::Token::BOM ();
|
||||
use PPI::Token::Whitespace ();
|
||||
use PPI::Token::Comment ();
|
||||
use PPI::Token::Pod ();
|
||||
use PPI::Token::Number ();
|
||||
use PPI::Token::Number::Binary ();
|
||||
use PPI::Token::Number::Octal ();
|
||||
use PPI::Token::Number::Hex ();
|
||||
use PPI::Token::Number::Float ();
|
||||
use PPI::Token::Number::Exp ();
|
||||
use PPI::Token::Number::Version ();
|
||||
use PPI::Token::Word ();
|
||||
use PPI::Token::DashedWord ();
|
||||
use PPI::Token::Symbol ();
|
||||
use PPI::Token::ArrayIndex ();
|
||||
use PPI::Token::Magic ();
|
||||
use PPI::Token::Quote::Single ();
|
||||
use PPI::Token::Quote::Double ();
|
||||
use PPI::Token::Quote::Literal ();
|
||||
use PPI::Token::Quote::Interpolate ();
|
||||
use PPI::Token::QuoteLike::Backtick ();
|
||||
use PPI::Token::QuoteLike::Command ();
|
||||
use PPI::Token::QuoteLike::Regexp ();
|
||||
use PPI::Token::QuoteLike::Words ();
|
||||
use PPI::Token::QuoteLike::Readline ();
|
||||
use PPI::Token::Regexp::Match ();
|
||||
use PPI::Token::Regexp::Substitute ();
|
||||
use PPI::Token::Regexp::Transliterate ();
|
||||
use PPI::Token::Operator ();
|
||||
use PPI::Token::Cast ();
|
||||
use PPI::Token::Structure ();
|
||||
use PPI::Token::Label ();
|
||||
use PPI::Token::HereDoc ();
|
||||
use PPI::Token::Separator ();
|
||||
use PPI::Token::Data ();
|
||||
use PPI::Token::End ();
|
||||
use PPI::Token::Prototype ();
|
||||
use PPI::Token::Attribute ();
|
||||
use PPI::Token::Unknown ();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Constructor and Related
|
||||
|
||||
sub new {
|
||||
bless { content => (defined $_[1] ? "$_[1]" : '') }, $_[0];
|
||||
}
|
||||
|
||||
sub set_class {
|
||||
my $self = shift;
|
||||
# @_ or throw Exception("No arguments to set_class");
|
||||
my $class = substr( $_[0], 0, 12 ) eq 'PPI::Token::' ? shift : 'PPI::Token::' . shift;
|
||||
|
||||
# Find out if the current and new classes are complex
|
||||
my $old_quote = (ref($self) =~ /\b(?:Quote|Regex)\b/o) ? 1 : 0;
|
||||
my $new_quote = ($class =~ /\b(?:Quote|Regex)\b/o) ? 1 : 0;
|
||||
|
||||
# No matter what happens, we will have to rebless
|
||||
bless $self, $class;
|
||||
|
||||
# If we are changing to or from a Quote style token, we
|
||||
# can't just rebless and need to do some extra thing
|
||||
# Otherwise, we have done enough
|
||||
return $class if ($old_quote - $new_quote) == 0;
|
||||
|
||||
# Make a new token from the old content, and overwrite the current
|
||||
# token's attributes with the new token's attributes.
|
||||
my $token = $class->new( $self->{content} );
|
||||
%$self = %$token;
|
||||
|
||||
# Return the class as a convenience
|
||||
return $class;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Token Methods
|
||||
|
||||
=pod
|
||||
|
||||
=head2 set_content $string
|
||||
|
||||
The C<set_content> method allows you to set/change the string that the
|
||||
C<PPI::Token> object represents.
|
||||
|
||||
Returns the string you set the Token to
|
||||
|
||||
=cut
|
||||
|
||||
sub set_content {
|
||||
$_[0]->{content} = $_[1];
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 add_content $string
|
||||
|
||||
The C<add_content> method allows you to add additional bytes of code
|
||||
to the end of the Token.
|
||||
|
||||
Returns the new full string after the bytes have been added.
|
||||
|
||||
=cut
|
||||
|
||||
sub add_content { $_[0]->{content} .= $_[1] }
|
||||
|
||||
=pod
|
||||
|
||||
=head2 length
|
||||
|
||||
The C<length> method returns the length of the string in a Token.
|
||||
|
||||
=cut
|
||||
|
||||
sub length { CORE::length($_[0]->{content}) }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Overloaded PPI::Element methods
|
||||
|
||||
sub content {
|
||||
$_[0]->{content};
|
||||
}
|
||||
|
||||
# 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::Structure') ) {
|
||||
return $self->__insert_before($Element);
|
||||
} elsif ( $Element->isa('PPI::Token') ) {
|
||||
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::Structure') ) {
|
||||
return $self->__insert_after($Element);
|
||||
} elsif ( $Element->isa('PPI::Token') ) {
|
||||
return $self->__insert_after($Element);
|
||||
}
|
||||
'';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Tokenizer Methods
|
||||
|
||||
sub __TOKENIZER__on_line_start() { 1 }
|
||||
sub __TOKENIZER__on_line_end() { 1 }
|
||||
sub __TOKENIZER__on_char() { 'Unknown' }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Lexer Methods
|
||||
|
||||
sub __LEXER__opens {
|
||||
ref($_[0]) eq 'PPI::Token::Structure'
|
||||
and
|
||||
$_[0]->{content} =~ /(?:\(|\[|\{)/
|
||||
}
|
||||
|
||||
sub __LEXER__closes {
|
||||
ref($_[0]) eq 'PPI::Token::Structure'
|
||||
and
|
||||
$_[0]->{content} =~ /(?:\)|\]|\})/
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
77
database/perl/vendor/lib/PPI/Token/ArrayIndex.pm
vendored
Normal file
77
database/perl/vendor/lib/PPI/Token/ArrayIndex.pm
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
package PPI::Token::ArrayIndex;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::ArrayIndex - Token getting the last index for an array
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::ArrayIndex
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The C<PPI::Token::ArrayIndex> token represents an attempt to get the
|
||||
last index of an array, such as C<$#array>.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
There are no additional methods beyond those provided by the parent
|
||||
L<PPI::Token> and L<PPI::Element> classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Tokenizer Methods
|
||||
|
||||
sub __TOKENIZER__on_char {
|
||||
my $t = $_[1];
|
||||
|
||||
# Suck in till the end of the arrayindex
|
||||
pos $t->{line} = $t->{line_cursor};
|
||||
if ( $t->{line} =~ m/\G([\w:']+)/gc ) {
|
||||
$t->{token}->{content} .= $1;
|
||||
$t->{line_cursor} += length $1;
|
||||
}
|
||||
|
||||
# End of token
|
||||
$t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
176
database/perl/vendor/lib/PPI/Token/Attribute.pm
vendored
Normal file
176
database/perl/vendor/lib/PPI/Token/Attribute.pm
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
package PPI::Token::Attribute;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Attribute - A token for a subroutine attribute
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Attribute
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
In Perl, attributes are a relatively recent addition to the language.
|
||||
|
||||
Given the code C< sub foo : bar(something) {} >, the C<bar(something)>
|
||||
part is the attribute.
|
||||
|
||||
A C<PPI::Token::Attribute> token represents the entire of the attribute,
|
||||
as the braces and its contents are not parsed into the tree, and are
|
||||
treated by Perl (and thus by us) as a single string.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
This class provides some additional methods beyond those provided by its
|
||||
L<PPI::Token> and L<PPI::Element> parent classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token";
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Token::Attribute Methods
|
||||
|
||||
=pod
|
||||
|
||||
=head2 identifier
|
||||
|
||||
The C<identifier> attribute returns the identifier part of the attribute.
|
||||
|
||||
That is, for the attribute C<foo(bar)>, the C<identifier> method would
|
||||
return C<"foo">.
|
||||
|
||||
=cut
|
||||
|
||||
sub identifier {
|
||||
my $self = shift;
|
||||
$self->{content} =~ /^(.+?)\(/ ? $1 : $self->{content};
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 parameters
|
||||
|
||||
The C<parameters> method returns the parameter string for the attribute.
|
||||
|
||||
That is, for the attribute C<foo(bar)>, the C<parameters> method would
|
||||
return C<"bar">.
|
||||
|
||||
Returns the parameters as a string (including the null string C<''> for
|
||||
the case of an attribute such as C<foo()>.)
|
||||
|
||||
Returns C<undef> if the attribute does not have parameters.
|
||||
|
||||
=cut
|
||||
|
||||
sub parameters {
|
||||
my $self = shift;
|
||||
$self->{content} =~ /\((.*)\)$/ ? $1 : undef;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Tokenizer Methods
|
||||
|
||||
sub __TOKENIZER__on_char {
|
||||
my $class = shift;
|
||||
my $t = shift;
|
||||
my $char = substr( $t->{line}, $t->{line_cursor}, 1 );
|
||||
|
||||
# Unless this is a '(', we are finished.
|
||||
unless ( $char eq '(' ) {
|
||||
# Finalise and recheck
|
||||
return $t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
# This is a bar(...) style attribute.
|
||||
# We are currently on the ( so scan in until the end.
|
||||
# We finish on the character AFTER our end
|
||||
my $string = $class->__TOKENIZER__scan_for_end( $t );
|
||||
if ( ref $string ) {
|
||||
# EOF
|
||||
$t->{token}->{content} .= $$string;
|
||||
$t->_finalize_token;
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Found the end of the attribute
|
||||
$t->{token}->{content} .= $string;
|
||||
$t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
# Scan for a close braced, and take into account both escaping,
|
||||
# and open close bracket pairs in the string. When complete, the
|
||||
# method leaves the line cursor on the LAST character found.
|
||||
sub __TOKENIZER__scan_for_end {
|
||||
my $t = $_[1];
|
||||
|
||||
# Loop as long as we can get new lines
|
||||
my $string = '';
|
||||
my $depth = 0;
|
||||
while ( exists $t->{line} ) {
|
||||
# Get the search area
|
||||
pos $t->{line} = $t->{line_cursor};
|
||||
|
||||
# Look for a match
|
||||
unless ( $t->{line} =~ /\G((?:\\.|[^()])*?[()])/gc ) {
|
||||
# Load in the next line and push to first character
|
||||
$string .= substr( $t->{line}, $t->{line_cursor} );
|
||||
$t->_fill_line(1) or return \$string;
|
||||
$t->{line_cursor} = 0;
|
||||
next;
|
||||
}
|
||||
|
||||
# Add to the string
|
||||
$string .= $1;
|
||||
$t->{line_cursor} += length $1;
|
||||
|
||||
# Alter the depth and continue if we aren't at the end
|
||||
$depth += ($1 =~ /\($/) ? 1 : -1 and next;
|
||||
|
||||
# Found the end
|
||||
return $string;
|
||||
}
|
||||
|
||||
# Returning the string as a reference indicates EOF
|
||||
\$string;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
113
database/perl/vendor/lib/PPI/Token/BOM.pm
vendored
Normal file
113
database/perl/vendor/lib/PPI/Token/BOM.pm
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
package PPI::Token::BOM;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::BOM - Tokens representing Unicode byte order marks
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::BOM
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is a special token in that it can only occur at the beginning of
|
||||
documents. If a BOM byte mark occurs elsewhere in a file, it should
|
||||
be treated as L<PPI::Token::Whitespace>. We recognize the byte order
|
||||
marks identified at this URL:
|
||||
L<http://www.unicode.org/faq/utf_bom.html#BOM>
|
||||
|
||||
UTF-32, big-endian 00 00 FE FF
|
||||
UTF-32, little-endian FF FE 00 00
|
||||
UTF-16, big-endian FE FF
|
||||
UTF-16, little-endian FF FE
|
||||
UTF-8 EF BB BF
|
||||
|
||||
Note that as of this writing, PPI only has support for UTF-8
|
||||
(namely, in POD and strings) and no support for UTF-16 or UTF-32. We
|
||||
support the BOMs of the latter two for completeness only.
|
||||
|
||||
The BOM is considered non-significant, like white space.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
There are no additional methods beyond those provided by the parent
|
||||
L<PPI::Token> and L<PPI::Element> classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token";
|
||||
|
||||
sub significant() { '' }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Parsing Methods
|
||||
|
||||
my %bom_types = (
|
||||
"\x00\x00\xfe\xff" => 'UTF-32',
|
||||
"\xff\xfe\x00\x00" => 'UTF-32',
|
||||
"\xfe\xff" => 'UTF-16',
|
||||
"\xff\xfe" => 'UTF-16',
|
||||
"\xef\xbb\xbf" => 'UTF-8',
|
||||
);
|
||||
|
||||
sub __TOKENIZER__on_line_start {
|
||||
my $t = $_[1];
|
||||
$_ = $t->{line};
|
||||
|
||||
if (m/^(\x00\x00\xfe\xff | # UTF-32, big-endian
|
||||
\xff\xfe\x00\x00 | # UTF-32, little-endian
|
||||
\xfe\xff | # UTF-16, big-endian
|
||||
\xff\xfe | # UTF-16, little-endian
|
||||
\xef\xbb\xbf) # UTF-8
|
||||
/xs) {
|
||||
my $bom = $1;
|
||||
|
||||
if ($bom_types{$bom} ne 'UTF-8') {
|
||||
return $t->_error("$bom_types{$bom} is not supported");
|
||||
}
|
||||
|
||||
$t->_new_token('BOM', $bom) or return undef;
|
||||
$t->{line_cursor} += length $bom;
|
||||
}
|
||||
|
||||
# Continue just as if there was no BOM
|
||||
$t->{class} = 'PPI::Token::Whitespace';
|
||||
return $t->{class}->__TOKENIZER__on_line_start($t);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
See the L<support section|PPI/SUPPORT> in the main module
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Chris Dolan E<lt>cdolan@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
|
||||
87
database/perl/vendor/lib/PPI/Token/Cast.pm
vendored
Normal file
87
database/perl/vendor/lib/PPI/Token/Cast.pm
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
package PPI::Token::Cast;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Cast - A prefix which forces a value into a different context
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Cast
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A "cast" in PPI terms is one of more characters used as a prefix which force
|
||||
a value into a different class or context.
|
||||
|
||||
This includes referencing, dereferencing, and a few other minor cases.
|
||||
|
||||
For expressions such as C<@$foo> or C<@{ $foo{bar} }> the C<@> in both cases
|
||||
represents a cast. In this case, an array dereference.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
There are no additional methods beyond those provided by the parent
|
||||
L<PPI::Token> and L<PPI::Element> classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token";
|
||||
|
||||
our %POSTFIX = map { $_ => 1 } (
|
||||
qw{
|
||||
%* @* $*
|
||||
},
|
||||
'$#*' # throws warnings if it's inside a qw
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Tokenizer Methods
|
||||
|
||||
# A cast is either % @ $ or $#
|
||||
# and also postfix dereference are %* @* $* $#*
|
||||
sub __TOKENIZER__on_char {
|
||||
my $t = $_[1];
|
||||
my $char = substr( $t->{line}, $t->{line_cursor}, 1 );
|
||||
|
||||
# Are we still an operator if we add the next character
|
||||
my $content = $t->{token}->{content};
|
||||
return 1 if $POSTFIX{ $content . $char };
|
||||
|
||||
$t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
146
database/perl/vendor/lib/PPI/Token/Comment.pm
vendored
Normal file
146
database/perl/vendor/lib/PPI/Token/Comment.pm
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
package PPI::Token::Comment;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Comment - A comment in Perl source code
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Comment
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
# This is a PPI::Token::Comment
|
||||
|
||||
print "Hello World!"; # So it this
|
||||
|
||||
$string =~ s/ foo # This, unfortunately, is not :(
|
||||
bar
|
||||
/w;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
In PPI, comments are represented by C<PPI::Token::Comment> objects.
|
||||
|
||||
These come in two flavours, line comment and inline comments.
|
||||
|
||||
A C<line comment> is a comment that stands on its own line. These comments
|
||||
hold their own newline and whitespace (both leading and trailing) as part
|
||||
of the one C<PPI::Token::Comment> object.
|
||||
|
||||
An inline comment is a comment that appears after some code, and
|
||||
continues to the end of the line. This does B<not> include whitespace,
|
||||
and the terminating newlines is considered a separate
|
||||
L<PPI::Token::Whitespace> token.
|
||||
|
||||
This is largely a convenience, simplifying a lot of normal code relating
|
||||
to the common things people do with comments.
|
||||
|
||||
Most commonly, it means when you C<prune> or C<delete> a comment, a line
|
||||
comment disappears taking the entire line with it, and an inline comment
|
||||
is removed from the inside of the line, allowing the newline to drop
|
||||
back onto the end of the code, as you would expect.
|
||||
|
||||
It also means you can move comments around in blocks much more easily.
|
||||
|
||||
For now, this is a suitably handy way to do things. However, I do reserve
|
||||
the right to change my mind on this one if it gets dangerously
|
||||
anachronistic somewhere down the line.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
Only very limited methods are available, beyond those provided by our
|
||||
parent L<PPI::Token> and L<PPI::Element> classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token";
|
||||
|
||||
### XS -> PPI/XS.xs:_PPI_Token_Comment__significant 0.900+
|
||||
sub significant() { '' }
|
||||
|
||||
# Most stuff goes through __TOKENIZER__commit.
|
||||
# This is such a rare case, do char at a time to keep the code small
|
||||
sub __TOKENIZER__on_char {
|
||||
my $t = $_[1];
|
||||
|
||||
# Make sure not to include the trailing newline
|
||||
if ( substr( $t->{line}, $t->{line_cursor}, 1 ) eq "\n" ) {
|
||||
return $t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
1;
|
||||
}
|
||||
|
||||
sub __TOKENIZER__commit {
|
||||
my $t = $_[1];
|
||||
|
||||
# Get the rest of the line
|
||||
my $rest = substr( $t->{line}, $t->{line_cursor} );
|
||||
if ( chomp $rest ) { # Include the newline separately
|
||||
# Add the current token, and the newline
|
||||
$t->_new_token('Comment', $rest);
|
||||
$t->_new_token('Whitespace', "\n");
|
||||
} else {
|
||||
# Add this token only
|
||||
$t->_new_token('Comment', $rest);
|
||||
}
|
||||
|
||||
# Advance the line cursor to the end
|
||||
$t->{line_cursor} = $t->{line_length} - 1;
|
||||
|
||||
0;
|
||||
}
|
||||
|
||||
# Comments end at the end of the line
|
||||
sub __TOKENIZER__on_line_end {
|
||||
$_[1]->_finalize_token if $_[1]->{token};
|
||||
1;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 line
|
||||
|
||||
The C<line> accessor returns true if the C<PPI::Token::Comment> is a
|
||||
line comment, or false if it is an inline comment.
|
||||
|
||||
=cut
|
||||
|
||||
sub line {
|
||||
# Entire line comments have a newline at the end
|
||||
$_[0]->{content} =~ /\n$/ ? 1 : 0;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
96
database/perl/vendor/lib/PPI/Token/DashedWord.pm
vendored
Normal file
96
database/perl/vendor/lib/PPI/Token/DashedWord.pm
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
package PPI::Token::DashedWord;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::DashedWord - A dashed bareword token
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::DashedWord
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The "dashed bareword" token represents literal values like C<-foo>.
|
||||
|
||||
NOTE: this class is currently unused. All tokens that should be
|
||||
PPI::Token::DashedWords are just normal PPI::Token::Word instead.
|
||||
That actually makes sense, since there really is nothing special about
|
||||
this class except that dashed words cannot be subroutine names or
|
||||
keywords. As such, this class may be removed from PPI in the future.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token";
|
||||
|
||||
=pod
|
||||
|
||||
=head2 literal
|
||||
|
||||
Returns the value of the dashed word as a string. This differs from
|
||||
C<content> because C<-Foo'Bar> expands to C<-Foo::Bar>.
|
||||
|
||||
=cut
|
||||
|
||||
*literal = *PPI::Token::Word::literal;
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Tokenizer Methods
|
||||
|
||||
sub __TOKENIZER__on_char {
|
||||
my $t = $_[1];
|
||||
|
||||
# Suck to the end of the dashed bareword
|
||||
pos $t->{line} = $t->{line_cursor};
|
||||
if ( $t->{line} =~ m/\G(\w+)/gc ) {
|
||||
$t->{token}->{content} .= $1;
|
||||
$t->{line_cursor} += length $1;
|
||||
}
|
||||
|
||||
# Are we a file test operator?
|
||||
if ( $t->{token}->{content} =~ /^\-[rwxoRWXOezsfdlpSbctugkTBMAC]$/ ) {
|
||||
# File test operator
|
||||
$t->{class} = $t->{token}->set_class( 'Operator' );
|
||||
} else {
|
||||
# No, normal dashed bareword
|
||||
$t->{class} = $t->{token}->set_class( 'Word' );
|
||||
}
|
||||
|
||||
$t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
102
database/perl/vendor/lib/PPI/Token/Data.pm
vendored
Normal file
102
database/perl/vendor/lib/PPI/Token/Data.pm
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
package PPI::Token::Data;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Data - The actual data in the __DATA__ section of a file
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Data
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The C<PPI::Token::Data> class is used to represent the actual data inside
|
||||
a file's C<__DATA__> section.
|
||||
|
||||
One C<PPI::Token::Data> object is used to represent the entire of the data,
|
||||
primarily so that it can provide a convenient handle directly to the data.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<PPI::Token::Data> provides one method in addition to those provided by
|
||||
our parent L<PPI::Token> and L<PPI::Element> classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use IO::String 1.07 ();
|
||||
use PPI::Token ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Methods
|
||||
|
||||
=pod
|
||||
|
||||
=head2 handle
|
||||
|
||||
The C<handle> method returns a L<IO::String> handle that allows you
|
||||
to do all the normal handle-y things to the contents of the __DATA__
|
||||
section of the file.
|
||||
|
||||
Unlike in perl itself, this means you can also do things like C<print>
|
||||
new data onto the end of the __DATA__ section, or modify it with
|
||||
any other process that can accept an L<IO::Handle> as input or output.
|
||||
|
||||
Returns an L<IO::String> object.
|
||||
|
||||
=cut
|
||||
|
||||
sub handle {
|
||||
my $self = shift;
|
||||
IO::String->new( \$self->{content} );
|
||||
}
|
||||
|
||||
sub __TOKENIZER__on_line_start {
|
||||
my ( $self, $t ) = @_;
|
||||
|
||||
# Add the line
|
||||
if ( defined $t->{token} ) {
|
||||
$t->{token}->{content} .= $t->{line};
|
||||
}
|
||||
else {
|
||||
defined( $t->{token} = $t->{class}->new( $t->{line} ) ) or return undef;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
111
database/perl/vendor/lib/PPI/Token/End.pm
vendored
Normal file
111
database/perl/vendor/lib/PPI/Token/End.pm
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
package PPI::Token::End;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::End - Completely useless content after the __END__ tag
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::End
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
If you've read L<PPI::Token::Whitespace>, you should understand by now
|
||||
the concept of documents "floating in a sea of PPI::Token::Whitespace".
|
||||
|
||||
Well it doesn't after the __END__ tag.
|
||||
|
||||
Once you __END__, it's all over. Anything after that tag isn't even fit
|
||||
to be called whitespace. It just simply doesn't exist as far as perl
|
||||
(the interpreter) is concerned.
|
||||
|
||||
That's not to say there isn't useful content. Most often people use
|
||||
the __END__ tag to hide POD content, so that perl never has to see it,
|
||||
and presumably providing some small speed up.
|
||||
|
||||
That's fine. PPI likes POD. Any POD after the __END__ tag is parsed
|
||||
into valid L<PPI::Token::Pod> tags as normal. B<This> class, on the
|
||||
other hand, is for "what's after __END__ when it isn't POD".
|
||||
|
||||
Basically, the completely worthless bits of the file :)
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
This class has no method beyond what is provided by its L<PPI::Token> and
|
||||
L<PPI::Element> parent classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Tokenizer Methods
|
||||
|
||||
### XS -> PPI/XS.xs:_PPI_Token_End__significant 0.900+
|
||||
sub significant() { '' }
|
||||
|
||||
sub __TOKENIZER__on_char() { 1 }
|
||||
|
||||
sub __TOKENIZER__on_line_start {
|
||||
my $t = $_[1];
|
||||
|
||||
# Can we classify the entire line in one go
|
||||
if ( $t->{line} =~ /^=(\w+)/ ) {
|
||||
# A Pod tag... change to pod mode
|
||||
$t->_new_token( 'Pod', $t->{line} );
|
||||
unless ( $1 eq 'cut' ) {
|
||||
# Normal start to pod
|
||||
$t->{class} = 'PPI::Token::Pod';
|
||||
}
|
||||
|
||||
# This is an error, but one we'll ignore
|
||||
# Don't go into Pod mode, since =cut normally
|
||||
# signals the end of Pod mode
|
||||
} else {
|
||||
if ( defined $t->{token} ) {
|
||||
# Add to existing token
|
||||
$t->{token}->{content} .= $t->{line};
|
||||
} else {
|
||||
$t->_new_token( 'End', $t->{line} );
|
||||
}
|
||||
}
|
||||
|
||||
0;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
323
database/perl/vendor/lib/PPI/Token/HereDoc.pm
vendored
Normal file
323
database/perl/vendor/lib/PPI/Token/HereDoc.pm
vendored
Normal file
@@ -0,0 +1,323 @@
|
||||
package PPI::Token::HereDoc;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::HereDoc - Token class for the here-doc
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::HereDoc
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Here-docs are incredibly handy when writing Perl, but incredibly tricky
|
||||
when parsing it, primarily because they don't follow the general flow of
|
||||
input.
|
||||
|
||||
They jump ahead and nab lines directly off the input buffer. Whitespace
|
||||
and newlines may not matter in most Perl code, but they matter in here-docs.
|
||||
|
||||
They are also tricky to store as an object. They look sort of like an
|
||||
operator and a string, but they don't act like it. And they have a second
|
||||
section that should be something like a separate token, but isn't because a
|
||||
string can span from above the here-doc content to below it.
|
||||
|
||||
So when parsing, this is what we do.
|
||||
|
||||
Firstly, the PPI::Token::HereDoc object, does not represent the C<<< << >>>
|
||||
operator, or the "END_FLAG", or the content, or even the terminator.
|
||||
|
||||
It represents all of them at once.
|
||||
|
||||
The token itself has only the declaration part as its "content".
|
||||
|
||||
# This is what the content of a HereDoc token is
|
||||
<<FOO
|
||||
|
||||
# Or this
|
||||
<<"FOO"
|
||||
|
||||
# Or even this
|
||||
<< 'FOO'
|
||||
|
||||
That is, the "operator", any whitespace separator, and the quoted or bare
|
||||
terminator. So when you call the C<content> method on a HereDoc token, you
|
||||
get '<< "FOO"'.
|
||||
|
||||
As for the content and the terminator, when treated purely in "content" terms
|
||||
they do not exist.
|
||||
|
||||
The content is made available with the C<heredoc> method, and the name of
|
||||
the terminator with the C<terminator> method.
|
||||
|
||||
To make things work in the way you expect, PPI has to play some games
|
||||
when doing line/column location calculation for tokens, and also during
|
||||
the content parsing and generation processes.
|
||||
|
||||
Documents cannot simply by recreated by stitching together the token
|
||||
contents, and involve a somewhat more expensive procedure, but the extra
|
||||
expense should be relatively negligible unless you are doing huge
|
||||
quantities of them.
|
||||
|
||||
Please note that due to the immature nature of PPI in general, we expect
|
||||
C<HereDocs> to be a rich (bad) source of corner-case bugs for quite a while,
|
||||
but for the most part they should more or less DWYM.
|
||||
|
||||
=head2 Comparison to other string types
|
||||
|
||||
Although technically it can be considered a quote, for the time being
|
||||
C<HereDocs> are being treated as a completely separate C<Token> subclass,
|
||||
and will not be found in a search for L<PPI::Token::Quote> or
|
||||
L<PPI::Token::QuoteLike> objects.
|
||||
|
||||
This may change in the future, with it most likely to end up under
|
||||
QuoteLike.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
Although it has the standard set of C<Token> methods, C<HereDoc> objects
|
||||
have a relatively large number of unique methods all of their own.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Token::HereDoc Methods
|
||||
|
||||
=pod
|
||||
|
||||
=head2 heredoc
|
||||
|
||||
The C<heredoc> method is the authoritative method for accessing the contents
|
||||
of the C<HereDoc> object.
|
||||
|
||||
It returns the contents of the here-doc as a list of newline-terminated
|
||||
strings. If called in scalar context, it returns the number of lines in
|
||||
the here-doc, B<excluding> the terminator line.
|
||||
|
||||
=cut
|
||||
|
||||
sub heredoc { @{shift->{_heredoc}} }
|
||||
|
||||
=pod
|
||||
|
||||
=head2 terminator
|
||||
|
||||
The C<terminator> method returns the name of the terminating string for the
|
||||
here-doc.
|
||||
|
||||
Returns the terminating string as an unescaped string (in the rare case
|
||||
the terminator has an escaped quote in it).
|
||||
|
||||
=cut
|
||||
|
||||
sub terminator {
|
||||
shift->{_terminator};
|
||||
}
|
||||
|
||||
sub _is_terminator {
|
||||
my ( $self, $terminator, $line, $indented ) = @_;
|
||||
if ( $indented ) {
|
||||
return $line =~ /^\s*\Q$terminator\E$/;
|
||||
} else {
|
||||
return $line eq $terminator;
|
||||
}
|
||||
}
|
||||
|
||||
sub _indent {
|
||||
my ( $self, $token ) = @_;
|
||||
my ($indent) = $token->{_terminator_line} =~ /^(\s*)/;
|
||||
return $indent;
|
||||
}
|
||||
|
||||
sub _is_match_indent {
|
||||
my ( $self, $token, $indent ) = @_;
|
||||
return (grep { /^$indent/ } @{$token->{_heredoc}}) == @{$token->{_heredoc}};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Tokenizer Methods
|
||||
|
||||
# Parse in the entire here-doc in one call
|
||||
sub __TOKENIZER__on_char {
|
||||
my ( $self, $t ) = @_;
|
||||
|
||||
# We are currently located on the first char after the <<
|
||||
|
||||
# Handle the most common form first for simplicity and speed reasons
|
||||
### FIXME - This regex, and this method in general, do not yet allow
|
||||
### for the null here-doc, which terminates at the first
|
||||
### empty line.
|
||||
pos $t->{line} = $t->{line_cursor};
|
||||
|
||||
if ( $t->{line} !~ m/\G( ~? \s* (?: "[^"]*" | '[^']*' | `[^`]*` | \\?\w+ ) )/gcx ) {
|
||||
# Degenerate to a left-shift operation
|
||||
$t->{token}->set_class('Operator');
|
||||
return $t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
# Add the rest of the token, work out what type it is,
|
||||
# and suck in the content until the end.
|
||||
my $token = $t->{token};
|
||||
$token->{content} .= $1;
|
||||
$t->{line_cursor} += length $1;
|
||||
|
||||
# Find the terminator, clean it up and determine
|
||||
# the type of here-doc we are dealing with.
|
||||
my $content = $token->{content};
|
||||
if ( $content =~ /^\<\<(~?)(\w+)$/ ) {
|
||||
# Bareword
|
||||
$token->{_mode} = 'interpolate';
|
||||
$token->{_indented} = 1 if $1 eq '~';
|
||||
$token->{_terminator} = $2;
|
||||
|
||||
} elsif ( $content =~ /^\<\<(~?)\s*\'(.*)\'$/ ) {
|
||||
# ''-quoted literal
|
||||
$token->{_mode} = 'literal';
|
||||
$token->{_indented} = 1 if $1 eq '~';
|
||||
$token->{_terminator} = $2;
|
||||
$token->{_terminator} =~ s/\\'/'/g;
|
||||
|
||||
} elsif ( $content =~ /^\<\<(~?)\s*\"(.*)\"$/ ) {
|
||||
# ""-quoted literal
|
||||
$token->{_mode} = 'interpolate';
|
||||
$token->{_indented} = 1 if $1 eq '~';
|
||||
$token->{_terminator} = $2;
|
||||
$token->{_terminator} =~ s/\\"/"/g;
|
||||
|
||||
} elsif ( $content =~ /^\<\<(~?)\s*\`(.*)\`$/ ) {
|
||||
# ``-quoted command
|
||||
$token->{_mode} = 'command';
|
||||
$token->{_indented} = 1 if $1 eq '~';
|
||||
$token->{_terminator} = $2;
|
||||
$token->{_terminator} =~ s/\\`/`/g;
|
||||
|
||||
} elsif ( $content =~ /^\<\<(~?)\\(\w+)$/ ) {
|
||||
# Legacy forward-slashed bareword
|
||||
$token->{_mode} = 'literal';
|
||||
$token->{_indented} = 1 if $1 eq '~';
|
||||
$token->{_terminator} = $2;
|
||||
|
||||
} else {
|
||||
# WTF?
|
||||
return undef;
|
||||
}
|
||||
|
||||
# Suck in the HEREDOC
|
||||
$token->{_heredoc} = \my @heredoc;
|
||||
my $terminator = $token->{_terminator} . "\n";
|
||||
while ( defined( my $line = $t->_get_line ) ) {
|
||||
if ( $self->_is_terminator( $terminator, $line, $token->{_indented} ) ) {
|
||||
# Keep the actual termination line for consistency
|
||||
# when we are re-assembling the file
|
||||
$token->{_terminator_line} = $line;
|
||||
|
||||
if ( $token->{_indented} ) {
|
||||
my $indent = $self->_indent( $token );
|
||||
# Indentation of here-doc doesn't match delimiter
|
||||
unless ( $self->_is_match_indent( $token, $indent ) ) {
|
||||
push @heredoc, $line;
|
||||
last;
|
||||
}
|
||||
|
||||
s/^$indent// for @heredoc, $token->{_terminator_line};
|
||||
}
|
||||
|
||||
# The HereDoc is now fully parsed
|
||||
return $t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
# Add the line
|
||||
push @heredoc, $line;
|
||||
}
|
||||
|
||||
# End of file.
|
||||
# Error: Didn't reach end of here-doc before end of file.
|
||||
|
||||
# If the here-doc block is not empty, look at the last line to determine if
|
||||
# the here-doc terminator is missing a newline (which Perl would fail to
|
||||
# compile but is easy to detect) or if the here-doc block was just not
|
||||
# terminated at all (which Perl would fail to compile as well).
|
||||
$token->{_terminator_line} = undef;
|
||||
if ( @heredoc and defined $heredoc[-1] ) {
|
||||
# See PPI::Tokenizer, the algorithm there adds a space at the end of the
|
||||
# document that we need to make sure we remove.
|
||||
if ( $t->{source_eof_chop} ) {
|
||||
chop $heredoc[-1];
|
||||
$t->{source_eof_chop} = '';
|
||||
}
|
||||
|
||||
# Check if the last line of the file matches the terminator without
|
||||
# newline at the end. If so, remove it from the content and set it as
|
||||
# the terminator line.
|
||||
$token->{_terminator_line} = pop @heredoc
|
||||
if $self->_is_terminator( $token->{_terminator}, $heredoc[-1], $token->{_indented} );
|
||||
}
|
||||
|
||||
if ( $token->{_indented} && $token->{_terminator_line} ) {
|
||||
my $indent = $self->_indent( $token );
|
||||
if ( $self->_is_match_indent( $token, $indent ) ) {
|
||||
# Remove indent from here-doc as much as possible
|
||||
s/^$indent// for @heredoc;
|
||||
}
|
||||
|
||||
s/^$indent// for $token->{_terminator_line};
|
||||
}
|
||||
|
||||
# Set a hint for PPI::Document->serialize so it can
|
||||
# inexpensively repair it if needed when writing back out.
|
||||
$token->{_damaged} = 1;
|
||||
|
||||
# The HereDoc is not fully parsed
|
||||
$t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 TO DO
|
||||
|
||||
- Implement PPI::Token::Quote interface compatibility
|
||||
|
||||
- Check CPAN for any use of the null here-doc or here-doc-in-s///e
|
||||
|
||||
- Add support for the null here-doc
|
||||
|
||||
- Add support for here-doc in s///e
|
||||
|
||||
=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
|
||||
58
database/perl/vendor/lib/PPI/Token/Label.pm
vendored
Normal file
58
database/perl/vendor/lib/PPI/Token/Label.pm
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
package PPI::Token::Label;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Label - Token class for a statement label
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Label
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A label is an identifier attached to a line or statements, to allow for
|
||||
various types of flow control. For example, a loop might have a label
|
||||
attached so that a C<last> or C<next> flow control statement can be used
|
||||
from multiple levels below to reference the loop directly.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
There are no additional methods beyond those provided by the parent
|
||||
L<PPI::Token> and L<PPI::Element> classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token";
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
200
database/perl/vendor/lib/PPI/Token/Magic.pm
vendored
Normal file
200
database/perl/vendor/lib/PPI/Token/Magic.pm
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
package PPI::Token::Magic;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Magic - Tokens representing magic variables
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Magic
|
||||
isa PPI::Token::Symbol
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
# When we say magic variables, we mean these...
|
||||
$1 $2 $3 $4 $5 $6 $7 $8 $9
|
||||
$_ $& $` $' $+ @+ %+ $* $. $/ $|
|
||||
$\ $" $; $% $= $- @- %- $) $#
|
||||
$~ $^ $: $? $! %! $@ $$ $< $>
|
||||
$( $0 $[ $] @_ @* $} $, $#+ $#-
|
||||
$^L $^A $^E $^C $^D $^F $^H
|
||||
$^I $^M $^N $^O $^P $^R $^S
|
||||
$^T $^V $^W $^X %^H
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<PPI::Token::Magic> is a sub-class of L<PPI::Token::Symbol> which
|
||||
identifies the token as "magic variable", one of the strange and
|
||||
unusual variables that are connected to "things" behind the scenes.
|
||||
|
||||
Some are extremely common, like C<$_>, and others you will quite
|
||||
probably never encounter in your Perl career.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
The class provides no additional methods, beyond those provided by
|
||||
L<PPI::Token::Symbol>, L<PPI::Token> and L<PPI::Element>.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token::Symbol ();
|
||||
use PPI::Token::Unknown ();
|
||||
use PPI::Singletons qw' %MAGIC $CURLY_SYMBOL ';
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token::Symbol";
|
||||
|
||||
sub __TOKENIZER__on_char {
|
||||
my $t = $_[1];
|
||||
|
||||
# $c is the candidate new content
|
||||
my $c = $t->{token}->{content} . substr( $t->{line}, $t->{line_cursor}, 1 );
|
||||
|
||||
# Do a quick first test so we don't have to do more than this one.
|
||||
# All of the tests below match this one, so it should provide a
|
||||
# small speed up. This regex should be updated to match the inside
|
||||
# tests if they are changed.
|
||||
if ( $c =~ /^ \$ .* [ \w : \$ \{ ] $/x ) {
|
||||
|
||||
if ( $c =~ /^(\$(?:\_[\w:]|::))/ or $c =~ /^\$\'[\w]/ ) {
|
||||
# If and only if we have $'\d, it is not a
|
||||
# symbol. (this was apparently a conscious choice)
|
||||
# Note that $::0 on the other hand is legal
|
||||
if ( $c =~ /^\$\'\d$/ ) {
|
||||
# In this case, we have a magic plus a digit.
|
||||
# Save the CURRENT token, and rerun the on_char
|
||||
return $t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
# A symbol in the style $_foo or $::foo or $'foo.
|
||||
# Overwrite the current token
|
||||
$t->{class} = $t->{token}->set_class('Symbol');
|
||||
return PPI::Token::Symbol->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
if ( $c =~ /^\$\$\w/ ) {
|
||||
# This is really a scalar dereference. ( $$foo )
|
||||
# Add the current token as the cast...
|
||||
$t->{token} = PPI::Token::Cast->new( '$' );
|
||||
$t->_finalize_token;
|
||||
|
||||
# ... and create a new token for the symbol
|
||||
return $t->_new_token( 'Symbol', '$' );
|
||||
}
|
||||
|
||||
if ( $c eq '$${' ) {
|
||||
# This _might_ be a dereference of one of the
|
||||
# control-character symbols.
|
||||
pos $t->{line} = $t->{line_cursor} + 1;
|
||||
if ( $t->{line} =~ m/$CURLY_SYMBOL/gc ) {
|
||||
# This is really a dereference. ( $${^_foo} )
|
||||
# Add the current token as the cast...
|
||||
$t->{token} = PPI::Token::Cast->new( '$' );
|
||||
$t->_finalize_token;
|
||||
|
||||
# ... and create a new token for the symbol
|
||||
return $t->_new_token( 'Magic', '$' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $c eq '$#$' or $c eq '$#{' ) {
|
||||
# This is really an index dereferencing cast, although
|
||||
# it has the same two chars as the magic variable $#.
|
||||
$t->{class} = $t->{token}->set_class('Cast');
|
||||
return $t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
if ( $c =~ /^(\$\#)\w/ ) {
|
||||
# This is really an array index thingy ( $#array )
|
||||
$t->{token} = PPI::Token::ArrayIndex->new( "$1" );
|
||||
return PPI::Token::ArrayIndex->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
if ( $c =~ /^\$\^\w+$/o ) {
|
||||
# It's an escaped char magic... maybe ( like $^M )
|
||||
my $next = substr( $t->{line}, $t->{line_cursor}+1, 1 ); # Peek ahead
|
||||
if ($MAGIC{$c} && (!$next || $next !~ /\w/)) {
|
||||
$t->{token}->{content} = $c;
|
||||
$t->{line_cursor}++;
|
||||
} else {
|
||||
# Maybe it's a long magic variable like $^WIDE_SYSTEM_CALLS
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $c =~ /^\$\#\{/ ) {
|
||||
# The $# is actually a cast, and { is its block
|
||||
# Add the current token as the cast...
|
||||
$t->{token} = PPI::Token::Cast->new( '$#' );
|
||||
$t->_finalize_token;
|
||||
|
||||
# ... and create a new token for the block
|
||||
return $t->_new_token( 'Structure', '{' );
|
||||
}
|
||||
} elsif ($c =~ /^%\^/) {
|
||||
return 1 if $c eq '%^';
|
||||
# It's an escaped char magic... maybe ( like %^H )
|
||||
if ($MAGIC{$c}) {
|
||||
$t->{token}->{content} = $c;
|
||||
$t->{line_cursor}++;
|
||||
} else {
|
||||
# Back off, treat '%' as an operator
|
||||
chop $t->{token}->{content};
|
||||
bless $t->{token}, $t->{class} = 'PPI::Token::Operator';
|
||||
$t->{line_cursor}--;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $MAGIC{$c} ) {
|
||||
# $#+ and $#-
|
||||
$t->{line_cursor} += length( $c ) - length( $t->{token}->{content} );
|
||||
$t->{token}->{content} = $c;
|
||||
} else {
|
||||
pos $t->{line} = $t->{line_cursor};
|
||||
if ( $t->{line} =~ m/($CURLY_SYMBOL)/gc ) {
|
||||
# control character symbol (e.g. ${^MATCH})
|
||||
$t->{token}->{content} .= $1;
|
||||
$t->{line_cursor} += length $1;
|
||||
} elsif ( $c =~ /^\$\d+$/ and $t->{line} =~ /\G(\d+)/gc ) {
|
||||
# Grab trailing digits of regex capture variables.
|
||||
$t->{token}{content} .= $1;
|
||||
$t->{line_cursor} += length $1;
|
||||
}
|
||||
}
|
||||
|
||||
# End the current magic token, and recheck
|
||||
$t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
# Our version of canonical is plain simple
|
||||
sub canonical { $_[0]->content }
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
163
database/perl/vendor/lib/PPI/Token/Number.pm
vendored
Normal file
163
database/perl/vendor/lib/PPI/Token/Number.pm
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
package PPI::Token::Number;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Number - Token class for a number
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
$n = 1234; # decimal integer
|
||||
$n = 0b1110011; # binary integer
|
||||
$n = 01234; # octal integer
|
||||
$n = 0x1234; # hexadecimal integer
|
||||
$n = 12.34e-56; # exponential notation ( currently not working )
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Number
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The C<PPI::Token::Number> class is used for tokens that represent numbers,
|
||||
in the various types that Perl supports.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token";
|
||||
|
||||
=pod
|
||||
|
||||
=head2 base
|
||||
|
||||
The C<base> method is provided by all of the ::Number subclasses.
|
||||
This is 10 for decimal, 16 for hexadecimal, 2 for binary, etc.
|
||||
|
||||
=cut
|
||||
|
||||
sub base() { 10 }
|
||||
|
||||
=pod
|
||||
|
||||
=head2 literal
|
||||
|
||||
Return the numeric value of this token.
|
||||
|
||||
=cut
|
||||
|
||||
sub literal {
|
||||
return 0 + $_[0]->_literal;
|
||||
}
|
||||
|
||||
sub _literal {
|
||||
# De-sugar the string representation
|
||||
my $self = shift;
|
||||
my $string = $self->content;
|
||||
$string =~ s/^\+//;
|
||||
$string =~ s/_//g;
|
||||
return $string;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Tokenizer Methods
|
||||
|
||||
sub __TOKENIZER__on_char {
|
||||
my $class = shift;
|
||||
my $t = shift;
|
||||
my $char = substr( $t->{line}, $t->{line_cursor}, 1 );
|
||||
|
||||
# Allow underscores straight through
|
||||
return 1 if $char eq '_';
|
||||
|
||||
# Handle the conversion from an unknown to known type.
|
||||
# The regex covers "potential" hex/bin/octal number.
|
||||
my $token = $t->{token};
|
||||
if ( $token->{content} =~ /^-?0_*$/ ) {
|
||||
# This could be special
|
||||
if ( $char eq 'x' || $char eq 'X' ) {
|
||||
$t->{class} = $t->{token}->set_class( 'Number::Hex' );
|
||||
return 1;
|
||||
} elsif ( $char eq 'b' || $char eq 'B' ) {
|
||||
$t->{class} = $t->{token}->set_class( 'Number::Binary' );
|
||||
return 1;
|
||||
} elsif ( $char =~ /\d/ ) {
|
||||
# You cannot have 8s and 9s on octals
|
||||
if ( $char eq '8' or $char eq '9' ) {
|
||||
$token->{_error} = "Illegal character in octal number '$char'";
|
||||
}
|
||||
$t->{class} = $t->{token}->set_class( 'Number::Octal' );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
# Handle the easy case, integer or real.
|
||||
return 1 if $char =~ /\d/o;
|
||||
|
||||
if ( $char eq '.' ) {
|
||||
$t->{class} = $t->{token}->set_class( 'Number::Float' );
|
||||
return 1;
|
||||
}
|
||||
if ( $char eq 'e' || $char eq 'E' ) {
|
||||
$t->{class} = $t->{token}->set_class( 'Number::Exp' );
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Doesn't fit a special case, or is after the end of the token
|
||||
# End of token.
|
||||
$t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 CAVEATS
|
||||
|
||||
Compared to Perl, the number tokenizer is too liberal about allowing
|
||||
underscores anywhere. For example, the following is a syntax error in
|
||||
Perl, but is allowed in PPI:
|
||||
|
||||
0_b10
|
||||
|
||||
=head1 TO DO
|
||||
|
||||
- Treat v-strings as binary strings or barewords, not as "base-256"
|
||||
numbers
|
||||
|
||||
- Break out decimal integers into their own subclass?
|
||||
|
||||
- Implement literal()
|
||||
|
||||
=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
|
||||
117
database/perl/vendor/lib/PPI/Token/Number/Binary.pm
vendored
Normal file
117
database/perl/vendor/lib/PPI/Token/Number/Binary.pm
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
package PPI::Token::Number::Binary;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Number::Binary - Token class for a binary number
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
$n = 0b1110011; # binary integer
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Number::Binary
|
||||
isa PPI::Token::Number
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The C<PPI::Token::Number::Binary> class is used for tokens that
|
||||
represent base-2 numbers.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token::Number ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token::Number";
|
||||
|
||||
=pod
|
||||
|
||||
=head2 base
|
||||
|
||||
Returns the base for the number: 2.
|
||||
|
||||
=cut
|
||||
|
||||
sub base() { 2 }
|
||||
|
||||
=pod
|
||||
|
||||
=head2 literal
|
||||
|
||||
Return the numeric value of this token.
|
||||
|
||||
=cut
|
||||
|
||||
sub literal {
|
||||
my $self = shift;
|
||||
return if $self->{_error};
|
||||
my $str = $self->_literal;
|
||||
my $neg = $str =~ s/^\-//;
|
||||
$str =~ s/^0[bB]//;
|
||||
my $val = 0;
|
||||
for my $bit ( $str =~ m/(.)/g ) {
|
||||
$val = $val * 2 + $bit;
|
||||
}
|
||||
return $neg ? -$val : $val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Tokenizer Methods
|
||||
|
||||
sub __TOKENIZER__on_char {
|
||||
my $class = shift;
|
||||
my $t = shift;
|
||||
my $char = substr( $t->{line}, $t->{line_cursor}, 1 );
|
||||
|
||||
# Allow underscores straight through
|
||||
return 1 if $char eq '_';
|
||||
|
||||
if ( $char =~ /[\w\d]/ ) {
|
||||
unless ( $char eq '1' or $char eq '0' ) {
|
||||
# Add a warning if it contains non-binary chars
|
||||
$t->{token}->{_error} = "Illegal character in binary number '$char'";
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Doesn't fit a special case, or is after the end of the token
|
||||
# End of token.
|
||||
$t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
See the L<support section|PPI/SUPPORT> in the main module.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Chris Dolan E<lt>cdolan@cpan.orgE<gt>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2006 Chris Dolan.
|
||||
|
||||
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
|
||||
146
database/perl/vendor/lib/PPI/Token/Number/Exp.pm
vendored
Normal file
146
database/perl/vendor/lib/PPI/Token/Number/Exp.pm
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
package PPI::Token::Number::Exp;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Number::Exp - Token class for an exponential notation number
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
$n = 1.0e-2;
|
||||
$n = 1e+2;
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Number::Exp
|
||||
isa PPI::Token::Number::Float
|
||||
isa PPI::Token::Number
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The C<PPI::Token::Number::Exp> class is used for tokens that
|
||||
represent floating point numbers with exponential notation.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token::Number::Float ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token::Number::Float";
|
||||
|
||||
=pod
|
||||
|
||||
=head2 literal
|
||||
|
||||
Return the numeric value of this token.
|
||||
|
||||
=cut
|
||||
|
||||
sub literal {
|
||||
my $self = shift;
|
||||
return if $self->{_error};
|
||||
my ($mantissa, $exponent) = split m/e/i, $self->_literal;
|
||||
my $neg = $mantissa =~ s/^\-//;
|
||||
$mantissa =~ s/^\./0./;
|
||||
$exponent =~ s/^\+//;
|
||||
|
||||
# Must cast exponent as numeric type, due to string type '00' exponent
|
||||
# creating false positive condition in for() loop below, causing infinite loop
|
||||
$exponent += 0;
|
||||
|
||||
# This algorithm is reasonably close to the S_mulexp10()
|
||||
# algorithm from the Perl source code, so it should arrive
|
||||
# at the same answer as Perl most of the time.
|
||||
my $negpow = 0;
|
||||
if ($exponent < 0) {
|
||||
$negpow = 1;
|
||||
$exponent *= -1;
|
||||
}
|
||||
|
||||
my $result = 1;
|
||||
my $power = 10;
|
||||
for (my $bit = 1; $exponent; $bit = $bit << 1) {
|
||||
if ($exponent & $bit) {
|
||||
$exponent = $exponent ^ $bit;
|
||||
$result *= $power;
|
||||
}
|
||||
$power *= $power;
|
||||
}
|
||||
|
||||
my $val = $neg ? 0 - $mantissa : $mantissa;
|
||||
return $negpow ? $val / $result : $val * $result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Tokenizer Methods
|
||||
|
||||
sub __TOKENIZER__on_char {
|
||||
my $class = shift;
|
||||
my $t = shift;
|
||||
my $char = substr( $t->{line}, $t->{line_cursor}, 1 );
|
||||
|
||||
# To get here, the token must have already encountered an 'E'
|
||||
|
||||
# Allow underscores straight through
|
||||
return 1 if $char eq '_';
|
||||
|
||||
# Allow digits
|
||||
return 1 if $char =~ /\d/o;
|
||||
|
||||
# Start of exponent is special
|
||||
if ( $t->{token}->{content} =~ /e$/i ) {
|
||||
# Allow leading +/- in exponent
|
||||
return 1 if $char eq '-' || $char eq '+';
|
||||
|
||||
# Invalid character in exponent. Recover
|
||||
if ( $t->{token}->{content} =~ s/\.(e)$//i ) {
|
||||
my $word = $1;
|
||||
$t->{class} = $t->{token}->set_class('Number');
|
||||
$t->_new_token('Operator', '.');
|
||||
$t->_new_token('Word', $word);
|
||||
return $t->{class}->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
else {
|
||||
$t->{token}->{_error} = "Illegal character in exponent '$char'";
|
||||
}
|
||||
}
|
||||
|
||||
# Doesn't fit a special case, or is after the end of the token
|
||||
# End of token.
|
||||
$t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
See the L<support section|PPI/SUPPORT> in the main module.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Chris Dolan E<lt>cdolan@cpan.orgE<gt>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2006 Chris Dolan.
|
||||
|
||||
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
|
||||
140
database/perl/vendor/lib/PPI/Token/Number/Float.pm
vendored
Normal file
140
database/perl/vendor/lib/PPI/Token/Number/Float.pm
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
package PPI::Token::Number::Float;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Number::Float - Token class for a floating-point number
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
$n = 1.234;
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Number::Float
|
||||
isa PPI::Token::Number
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The C<PPI::Token::Number::Float> class is used for tokens that
|
||||
represent floating point numbers. A float is identified by n decimal
|
||||
point. Exponential notation (the C<e> or C<E>) is handled by the
|
||||
PPI::Token::Number::Exp class.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token::Number ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token::Number";
|
||||
|
||||
=pod
|
||||
|
||||
=head2 base
|
||||
|
||||
Returns the base for the number: 10.
|
||||
|
||||
=cut
|
||||
|
||||
sub base() { 10 }
|
||||
|
||||
=pod
|
||||
|
||||
=head2 literal
|
||||
|
||||
Return the numeric value of this token.
|
||||
|
||||
=cut
|
||||
|
||||
sub literal {
|
||||
my $self = shift;
|
||||
my $str = $self->_literal;
|
||||
my $neg = $str =~ s/^\-//;
|
||||
$str =~ s/^\./0./;
|
||||
my $val = 0+$str;
|
||||
return $neg ? -$val : $val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Tokenizer Methods
|
||||
|
||||
sub __TOKENIZER__on_char {
|
||||
my $class = shift;
|
||||
my $t = shift;
|
||||
my $char = substr( $t->{line}, $t->{line_cursor}, 1 );
|
||||
|
||||
# Allow underscores straight through
|
||||
return 1 if $char eq '_';
|
||||
|
||||
# Allow digits
|
||||
return 1 if $char =~ /\d/o;
|
||||
|
||||
if ( $char eq '.' ) { # A second decimal point? That gets complicated.
|
||||
if ( $t->{token}{content} =~ /\.$/ ) {
|
||||
# We have a .., which is an operator. Take the . off the end of the
|
||||
# token and finish it, then make the .. operator.
|
||||
chop $t->{token}{content};
|
||||
$t->{class} = $t->{token}->set_class( 'Number' );
|
||||
$t->_new_token('Operator', '..');
|
||||
return 0;
|
||||
} elsif ( $t->{token}{content} =~ /\._/ ) {
|
||||
($t->{token}{content}, my $bareword)
|
||||
= split /\./, $t->{token}{content};
|
||||
$t->{class} = $t->{token}->set_class( 'Number' );
|
||||
$t->_new_token('Operator', '.');
|
||||
$t->_new_token('Word', $bareword);
|
||||
$t->_new_token('Operator', '.');
|
||||
return 0;
|
||||
} else {
|
||||
$t->{class} = $t->{token}->set_class( 'Number::Version' );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
# perl seems to regard pretty much anything that's not strictly an exp num
|
||||
# as float + stuff
|
||||
my $char2 = substr $t->{line}, $t->{line_cursor}+1, 1;
|
||||
if ("$char$char2" =~ /[eE][0-9+-]/) {
|
||||
$t->{class} = $t->{token}->set_class( 'Number::Exp' );
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Doesn't fit a special case, or is after the end of the token
|
||||
# End of token.
|
||||
$t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
See the L<support section|PPI/SUPPORT> in the main module.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Chris Dolan E<lt>cdolan@cpan.orgE<gt>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2006 Chris Dolan.
|
||||
|
||||
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
|
||||
108
database/perl/vendor/lib/PPI/Token/Number/Hex.pm
vendored
Normal file
108
database/perl/vendor/lib/PPI/Token/Number/Hex.pm
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
package PPI::Token::Number::Hex;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Number::Hex - Token class for a binary number
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
$n = 0x1234; # hexadecimal integer
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Number::Hex
|
||||
isa PPI::Token::Number
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The C<PPI::Token::Number::Hex> class is used for tokens that
|
||||
represent base-16 numbers.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token::Number ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token::Number";
|
||||
|
||||
=pod
|
||||
|
||||
=head2 base
|
||||
|
||||
Returns the base for the number: 16.
|
||||
|
||||
=cut
|
||||
|
||||
sub base() { 16 }
|
||||
|
||||
=pod
|
||||
|
||||
=head2 literal
|
||||
|
||||
Return the numeric value of this token.
|
||||
|
||||
=cut
|
||||
|
||||
sub literal {
|
||||
my $self = shift;
|
||||
my $str = $self->_literal;
|
||||
my $neg = $str =~ s/^\-//;
|
||||
my $val = hex lc( $str ); # lc for compatibility with perls before 5.14
|
||||
return $neg ? -$val : $val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Tokenizer Methods
|
||||
|
||||
sub __TOKENIZER__on_char {
|
||||
my $class = shift;
|
||||
my $t = shift;
|
||||
my $char = substr( $t->{line}, $t->{line_cursor}, 1 );
|
||||
|
||||
# Allow underscores straight through
|
||||
return 1 if $char eq '_';
|
||||
|
||||
if ( $char =~ /[[:xdigit:]]/ ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Doesn't fit a special case, or is after the end of the token
|
||||
# End of token.
|
||||
$t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
See the L<support section|PPI/SUPPORT> in the main module.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Chris Dolan E<lt>cdolan@cpan.orgE<gt>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2006 Chris Dolan.
|
||||
|
||||
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
|
||||
113
database/perl/vendor/lib/PPI/Token/Number/Octal.pm
vendored
Normal file
113
database/perl/vendor/lib/PPI/Token/Number/Octal.pm
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
package PPI::Token::Number::Octal;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Number::Octal - Token class for a binary number
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
$n = 0777; # octal integer
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Number::Octal
|
||||
isa PPI::Token::Number
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The C<PPI::Token::Number::Octal> class is used for tokens that
|
||||
represent base-8 numbers.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token::Number ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token::Number";
|
||||
|
||||
=pod
|
||||
|
||||
=head2 base
|
||||
|
||||
Returns the base for the number: 8.
|
||||
|
||||
=cut
|
||||
|
||||
sub base() { 8 }
|
||||
|
||||
=pod
|
||||
|
||||
=head2 literal
|
||||
|
||||
Return the numeric value of this token.
|
||||
|
||||
=cut
|
||||
|
||||
sub literal {
|
||||
my $self = shift;
|
||||
return if $self->{_error};
|
||||
my $str = $self->_literal;
|
||||
my $neg = $str =~ s/^\-//;
|
||||
my $val = oct $str;
|
||||
return $neg ? -$val : $val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Tokenizer Methods
|
||||
|
||||
sub __TOKENIZER__on_char {
|
||||
my $class = shift;
|
||||
my $t = shift;
|
||||
my $char = substr( $t->{line}, $t->{line_cursor}, 1 );
|
||||
|
||||
# Allow underscores straight through
|
||||
return 1 if $char eq '_';
|
||||
|
||||
if ( $char =~ /\d/ ) {
|
||||
# You cannot have 8s and 9s on octals
|
||||
if ( $char eq '8' or $char eq '9' ) {
|
||||
$t->{token}->{_error} = "Illegal character in octal number '$char'";
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Doesn't fit a special case, or is after the end of the token
|
||||
# End of token.
|
||||
$t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
See the L<support section|PPI/SUPPORT> in the main module.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Chris Dolan E<lt>cdolan@cpan.orgE<gt>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2006 Chris Dolan.
|
||||
|
||||
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
|
||||
164
database/perl/vendor/lib/PPI/Token/Number/Version.pm
vendored
Normal file
164
database/perl/vendor/lib/PPI/Token/Number/Version.pm
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
package PPI::Token::Number::Version;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Number::Version - Token class for a byte-packed number
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
$n = 1.1.0;
|
||||
$n = 127.0.0.1;
|
||||
$n = 10_000.10_000.10_000;
|
||||
$n = v1.2.3.4
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Number::Version
|
||||
isa PPI::Token::Number
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The C<PPI::Token::Number::Version> class is used for tokens that have
|
||||
multiple decimal points. In truth, these aren't treated like numbers
|
||||
at all by Perl, but they look like numbers to a parser.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token::Number ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token::Number";
|
||||
|
||||
=pod
|
||||
|
||||
=head2 base
|
||||
|
||||
Returns the base for the number: 256.
|
||||
|
||||
=cut
|
||||
|
||||
sub base() { 256 }
|
||||
|
||||
=pod
|
||||
|
||||
=head2 literal
|
||||
|
||||
Return the numeric value of this token.
|
||||
|
||||
=cut
|
||||
|
||||
sub literal {
|
||||
my $self = shift;
|
||||
my $content = $self->{content};
|
||||
$content =~ s/^v//;
|
||||
return join '', map { chr $_ } ( split /\./, $content );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Tokenizer Methods
|
||||
|
||||
sub __TOKENIZER__on_char {
|
||||
my $class = shift;
|
||||
my $t = shift;
|
||||
my $char = substr( $t->{line}, $t->{line_cursor}, 1 );
|
||||
|
||||
# Allow digits
|
||||
return 1 if $char =~ /\d/o;
|
||||
|
||||
if( $char eq '_' ) {
|
||||
return 1 if $t->{token}{content} !~ /\.$/;
|
||||
|
||||
chop $t->{token}->{content};
|
||||
$t->{class} = $t->{token}->set_class( 'Number::Float' )
|
||||
if $t->{token}{content} !~ /\..+\./;
|
||||
$t->_new_token('Operator', '.');
|
||||
$t->_new_token('Word', '_');
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Is this a second decimal point in a row? Then the '..' operator
|
||||
if ( $char eq '.' ) {
|
||||
if ( $t->{token}->{content} =~ /\.$/ ) {
|
||||
# We have a .., which is an operator.
|
||||
# Take the . off the end of the token..
|
||||
# and finish it, then make the .. operator.
|
||||
chop $t->{token}->{content};
|
||||
$t->{class} = $t->{token}->set_class( 'Number::Float' )
|
||||
if $t->{token}{content} !~ /\..+\./;
|
||||
$t->_new_token('Operator', '..');
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
# Doesn't fit a special case, or is after the end of the token
|
||||
# End of token.
|
||||
$t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
sub __TOKENIZER__commit {
|
||||
my $t = $_[1];
|
||||
|
||||
# Capture the rest of the token
|
||||
pos $t->{line} = $t->{line_cursor};
|
||||
# This was not a v-string after all (it's a word);
|
||||
return PPI::Token::Word->__TOKENIZER__commit($t)
|
||||
if $t->{line} !~ m/\G(v\d[_\d]*(?:\.\d[_\d]*)+|v\d[_\d]*\b)/gc;
|
||||
|
||||
my $content = $1;
|
||||
|
||||
# If there are no periods this could be a word starting with v\d
|
||||
# Forced to be a word. Done.
|
||||
return PPI::Token::Word->__TOKENIZER__commit($t)
|
||||
if $content !~ /\./ and $t->__current_token_is_forced_word($content);
|
||||
|
||||
# This is a v-string
|
||||
$t->{line_cursor} += length $content;
|
||||
$t->_new_token( 'Number::Version', $content );
|
||||
$t->_finalize_token->__TOKENIZER__on_char($t);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
- Does not handle leading minus sign correctly. Should translate to a DashedWord.
|
||||
See L<http://perlmonks.org/?node_id=574573>
|
||||
|
||||
-95.0.1.0 --> "-_\000\cA\000"
|
||||
-96.0.1.0 --> Argument "`\0^A\0" isn't numeric in negation (-)
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
See the L<support section|PPI/SUPPORT> in the main module.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Chris Dolan E<lt>cdolan@cpan.orgE<gt>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2006 Chris Dolan.
|
||||
|
||||
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
|
||||
124
database/perl/vendor/lib/PPI/Token/Operator.pm
vendored
Normal file
124
database/perl/vendor/lib/PPI/Token/Operator.pm
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
package PPI::Token::Operator;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Operator - Token class for operators
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Operator
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
# This is the list of valid operators
|
||||
++ -- ** ! ~ + -
|
||||
=~ !~ * / % x
|
||||
<< >> lt gt le ge cmp ~~
|
||||
== != <=> . .. ... ,
|
||||
& | ^ && || //
|
||||
? : **= += -= .= *= /=
|
||||
%= x= &= |= ^= <<= >>= &&=
|
||||
||= //= < > <= >= <> => ->
|
||||
and or xor not eq ne <<>>
|
||||
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
All operators in PPI are created as C<PPI::Token::Operator> objects,
|
||||
including the ones that may superficially look like a L<PPI::Token::Word>
|
||||
object.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
There are no additional methods beyond those provided by the parent
|
||||
L<PPI::Token> and L<PPI::Element> classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token ();
|
||||
use PPI::Singletons '%OPERATOR';
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Tokenizer Methods
|
||||
|
||||
sub __TOKENIZER__on_char {
|
||||
my $t = $_[1];
|
||||
my $char = substr( $t->{line}, $t->{line_cursor}, 1 );
|
||||
|
||||
# Are we still an operator if we add the next character
|
||||
my $content = $t->{token}->{content};
|
||||
# special case for <<>> operator
|
||||
if(length($content) < 4 &&
|
||||
$content . substr( $t->{line}, $t->{line_cursor}, 4 - length($content) ) eq '<<>>') {
|
||||
return 1;
|
||||
}
|
||||
return 1 if $OPERATOR{ $content . $char };
|
||||
|
||||
# Handle the special case of a .1234 decimal number
|
||||
if ( $content eq '.' ) {
|
||||
if ( $char =~ /^[0-9]$/ ) {
|
||||
# This is a decimal number
|
||||
$t->{class} = $t->{token}->set_class('Number::Float');
|
||||
return $t->{class}->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
}
|
||||
|
||||
# Handle the special case if we might be a here-doc
|
||||
if ( $content eq '<<' ) {
|
||||
pos $t->{line} = $t->{line_cursor};
|
||||
# Either <<FOO or << 'FOO' or <<\FOO or
|
||||
# <<~FOO or <<~ 'FOO' or <<~\FOO
|
||||
### Is the zero-width look-ahead assertion really
|
||||
### supposed to be there?
|
||||
if ( $t->{line} =~ m/\G ~? (?: (?!\d)\w | \s*['"`] | \\\w ) /gcx ) {
|
||||
# This is a here-doc.
|
||||
# Change the class and move to the HereDoc's own __TOKENIZER__on_char method.
|
||||
$t->{class} = $t->{token}->set_class('HereDoc');
|
||||
return $t->{class}->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
}
|
||||
|
||||
# Handle the special case of the null Readline
|
||||
$t->{class} = $t->{token}->set_class('QuoteLike::Readline')
|
||||
if $content eq '<>' or $content eq '<<>>';
|
||||
|
||||
# Finalize normally
|
||||
$t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
159
database/perl/vendor/lib/PPI/Token/Pod.pm
vendored
Normal file
159
database/perl/vendor/lib/PPI/Token/Pod.pm
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
package PPI::Token::Pod;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Pod - Sections of POD in Perl documents
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Pod
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A single C<PPI::Token::Pod> object represents a complete section of POD
|
||||
documentation within a Perl document.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
This class provides some additional methods beyond those provided by its
|
||||
L<PPI::Token> and L<PPI::Element> parent classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Params::Util qw{_INSTANCE};
|
||||
use PPI::Token ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Token::Pod Methods
|
||||
|
||||
=pod
|
||||
|
||||
=head2 merge @podtokens
|
||||
|
||||
The C<merge> constructor takes a number of C<PPI::Token::Pod> objects,
|
||||
and returns a new object that represents one combined POD block with
|
||||
the content of all of them.
|
||||
|
||||
Returns a new C<PPI::Token::Pod> object, or C<undef> on error.
|
||||
|
||||
=cut
|
||||
|
||||
sub merge {
|
||||
my $class = (! ref $_[0]) ? shift : return undef;
|
||||
|
||||
# Check there are no bad arguments
|
||||
if ( grep { ! _INSTANCE($_, 'PPI::Token::Pod') } @_ ) {
|
||||
return undef;
|
||||
}
|
||||
|
||||
# Get the tokens, and extract the lines
|
||||
my @content = ( map { [ $_->lines ] } @_ ) or return undef;
|
||||
|
||||
# Remove the leading =pod tags, trailing =cut tags, and any empty lines
|
||||
# between them and the pod contents.
|
||||
foreach my $pod ( @content ) {
|
||||
# Leading =pod tag
|
||||
if ( @$pod and $pod->[0] =~ /^=pod\b/o ) {
|
||||
shift @$pod;
|
||||
}
|
||||
|
||||
# Trailing =cut tag
|
||||
if ( @$pod and $pod->[-1] =~ /^=cut\b/o ) {
|
||||
pop @$pod;
|
||||
}
|
||||
|
||||
# Leading and trailing empty lines
|
||||
while ( @$pod and $pod->[0] eq '' ) { shift @$pod }
|
||||
while ( @$pod and $pod->[-1] eq '' ) { pop @$pod }
|
||||
}
|
||||
|
||||
# Remove any empty pod sections, and add the =pod and =cut tags
|
||||
# for the merged pod back to it.
|
||||
@content = ( [ '=pod' ], grep { @$_ } @content, [ '=cut' ] );
|
||||
|
||||
# Create the new object
|
||||
$class->new( join "\n", map { join( "\n", @$_ ) . "\n" } @content );
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 lines
|
||||
|
||||
The C<lines> method takes the string of POD and breaks it into lines,
|
||||
returning them as a list.
|
||||
|
||||
=cut
|
||||
|
||||
sub lines {
|
||||
split /(?:\015{1,2}\012|\015|\012)/, $_[0]->{content};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Element Methods
|
||||
|
||||
### XS -> PPI/XS.xs:_PPI_Token_Pod__significant 0.900+
|
||||
sub significant() { '' }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Tokenizer Methods
|
||||
|
||||
sub __TOKENIZER__on_line_start {
|
||||
my $t = $_[1];
|
||||
|
||||
# Add the line to the token first
|
||||
$t->{token}->{content} .= $t->{line};
|
||||
|
||||
# Check the line to see if it is a =cut line
|
||||
if ( $t->{line} =~ /^=(\w+)/ ) {
|
||||
# End of the token
|
||||
$t->_finalize_token if $1 eq 'cut';
|
||||
}
|
||||
|
||||
0;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
115
database/perl/vendor/lib/PPI/Token/Prototype.pm
vendored
Normal file
115
database/perl/vendor/lib/PPI/Token/Prototype.pm
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
package PPI::Token::Prototype;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Prototype - A subroutine prototype descriptor
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::End
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
sub ($@) prototype;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Although it sort of looks like a list or condition, a subroutine
|
||||
prototype is a lot more like a string. Its job is to provide hints
|
||||
to the perl compiler on what type of arguments a particular subroutine
|
||||
expects, which the compiler uses to validate parameters at compile-time,
|
||||
and allows programmers to use the functions without explicit parameter
|
||||
parens.
|
||||
|
||||
Due to the rise of OO Perl coding, which ignores these prototypes, they
|
||||
are most often used to allow for constant-like things, and to "extend"
|
||||
the language and create things that act like keywords and core functions.
|
||||
|
||||
# Create something that acts like a constant
|
||||
sub MYCONSTANT () { 10 }
|
||||
|
||||
# Create the "any" core-looking function
|
||||
sub any (&@) { ... }
|
||||
|
||||
if ( any { $_->cute } @babies ) {
|
||||
...
|
||||
}
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
This class provides one additional method beyond those defined by the
|
||||
L<PPI::Token> and L<PPI::Element> parent classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token";
|
||||
|
||||
sub __TOKENIZER__on_char {
|
||||
my $class = shift;
|
||||
my $t = shift;
|
||||
|
||||
# Suck in until we find the closing paren (or the end of line)
|
||||
pos $t->{line} = $t->{line_cursor};
|
||||
die "regex should always match" if $t->{line} !~ m/\G(.*?(?:\)|$))/gc;
|
||||
$t->{token}->{content} .= $1;
|
||||
$t->{line_cursor} += length $1;
|
||||
|
||||
# Shortcut if end of line
|
||||
return 0 unless $1 =~ /\)$/;
|
||||
|
||||
# Found the closing paren
|
||||
$t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 prototype
|
||||
|
||||
The C<prototype> accessor returns the actual prototype pattern, stripped
|
||||
of flanking parens and of all whitespace. This mirrors the behavior of
|
||||
the Perl C<prototype> builtin function.
|
||||
|
||||
Note that stripping parens and whitespace means that the return of
|
||||
C<prototype> can be an empty string.
|
||||
|
||||
=cut
|
||||
|
||||
sub prototype {
|
||||
my $self = shift;
|
||||
my $proto = $self->content;
|
||||
$proto =~ s/(^\(|\)$|\s+)//g;
|
||||
$proto;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
120
database/perl/vendor/lib/PPI/Token/Quote.pm
vendored
Normal file
120
database/perl/vendor/lib/PPI/Token/Quote.pm
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
package PPI::Token::Quote;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Quote - String quote abstract base class
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Quote
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The C<PPI::Token::Quote> class is never instantiated, and simply
|
||||
provides a common abstract base class for the four quote classes.
|
||||
In PPI, a "quote" is limited to only the quote-like things that
|
||||
themselves directly represent a string. (although this includes
|
||||
double quotes with interpolated elements inside them, note that
|
||||
L<String::InterpolatedVariables> allows to extract them).
|
||||
|
||||
The subclasses of C<PPI::Token::Quote> are:
|
||||
|
||||
=over 2
|
||||
|
||||
=item C<''> - L<PPI::Token::Quote::Single>
|
||||
|
||||
=item C<q{}> - L<PPI::Token::Quote::Literal>
|
||||
|
||||
=item C<""> - L<PPI::Token::Quote::Double>
|
||||
|
||||
=item C<qq{}> - L<PPI::Token::Quote::Interpolate>
|
||||
|
||||
=back
|
||||
|
||||
The names are hopefully obvious enough not to have to explain what
|
||||
each class is here. See their respective pages for more details.
|
||||
|
||||
Please note that although the here-doc B<does> represent a literal
|
||||
string, it is such a nasty piece of work that in L<PPI> it is given the
|
||||
honor of its own token class (L<PPI::Token::HereDoc>).
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Token::Quote Methods
|
||||
|
||||
=pod
|
||||
|
||||
=head2 string
|
||||
|
||||
The C<string> method is provided by all four ::Quote classes. It won't
|
||||
get you the actual literal Perl value, but it will strip off the wrapping
|
||||
of the quotes.
|
||||
|
||||
# The following all return foo from the ->string method
|
||||
'foo'
|
||||
"foo"
|
||||
q{foo}
|
||||
qq <foo>
|
||||
|
||||
=cut
|
||||
|
||||
#sub string {
|
||||
# my $class = ref $_[0] || $_[0];
|
||||
# die "$class does not implement method ->string";
|
||||
#}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 literal
|
||||
|
||||
The C<literal> method is provided by ::Quote::Literal and
|
||||
::Quote::Single. This returns the value of the string as Perl sees
|
||||
it: without the quote marks and with C<\\> and C<\'> resolved to C<\>
|
||||
and C<'>.
|
||||
|
||||
The C<literal> method is not implemented by ::Quote::Double or
|
||||
::Quote::Interpolate yet.
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
138
database/perl/vendor/lib/PPI/Token/Quote/Double.pm
vendored
Normal file
138
database/perl/vendor/lib/PPI/Token/Quote/Double.pm
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
package PPI::Token::Quote::Double;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Quote::Double - A standard "double quote" token
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Quote::Double
|
||||
isa PPI::Token::Quote
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A C<PPI::Token::Quote::Double> object represents a double-quoted
|
||||
interpolating string.
|
||||
|
||||
The string is treated as a single entity, L<PPI> will not try to
|
||||
understand what is in the string during the parsing process.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
There are several methods available for C<PPI::Token::Quote::Double>, beyond
|
||||
those provided by the parent L<PPI::Token::Quote>, L<PPI::Token> and
|
||||
L<PPI::Element> classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Params::Util qw{_INSTANCE};
|
||||
use PPI::Token::Quote ();
|
||||
use PPI::Token::_QuoteEngine::Simple ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = qw{
|
||||
PPI::Token::_QuoteEngine::Simple
|
||||
PPI::Token::Quote
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Token::Quote::Double Methods
|
||||
|
||||
=pod
|
||||
|
||||
=head2 interpolations
|
||||
|
||||
The interpolations method checks to see if the double quote actually
|
||||
contains any interpolated variables.
|
||||
|
||||
Returns true if the string contains interpolations, or false if not.
|
||||
|
||||
=cut
|
||||
|
||||
# Upgrade: Return the interpolated substrings.
|
||||
# Upgrade: Returns parsed expressions.
|
||||
sub interpolations {
|
||||
# Are there any unescaped $things in the string
|
||||
!! ($_[0]->content =~ /(?<!\\)(?:\\\\)*[\$\@]/);
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 simplify
|
||||
|
||||
For various reasons, some people find themselves compelled to have
|
||||
their code in the simplest form possible.
|
||||
|
||||
The C<simplify> method will, if possible, modify a simple double-quoted
|
||||
string token in place, turning it into the equivalent single-quoted
|
||||
string. If the token is modified, it is reblessed into the
|
||||
L<PPI::Token::Quote::Single> package.
|
||||
|
||||
Because the length of the content is not changed, there is no need
|
||||
to call the document's C<flush_locations> method.
|
||||
|
||||
The object itself is returned as a convenience.
|
||||
|
||||
=cut
|
||||
|
||||
sub simplify {
|
||||
# This only works on EXACTLY this class
|
||||
my $self = _INSTANCE(shift, 'PPI::Token::Quote::Double') or return undef;
|
||||
|
||||
# Don't bother if there are characters that could complicate things
|
||||
my $content = $self->content;
|
||||
my $value = substr($content, 1, length($content) - 2);
|
||||
return $self if $value =~ /[\\\$@\'\"]/;
|
||||
|
||||
# Change the token to a single string
|
||||
$self->{content} = "'$value'";
|
||||
bless $self, 'PPI::Token::Quote::Single';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Token::Quote Methods
|
||||
|
||||
sub string {
|
||||
my $str = $_[0]->{content};
|
||||
substr( $str, 1, length($str) - 2 );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
76
database/perl/vendor/lib/PPI/Token/Quote/Interpolate.pm
vendored
Normal file
76
database/perl/vendor/lib/PPI/Token/Quote/Interpolate.pm
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
package PPI::Token::Quote::Interpolate;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Quote::Interpolate - The interpolation quote-like operator
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Quote::Interpolate
|
||||
isa PPI::Token::Quote
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A C<PPI::Token::Quote::Interpolate> object represents a single
|
||||
interpolation quote-like operator, such as C<qq{$foo bar $baz}>.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
There are no methods available for C<PPI::Token::Quote::Interpolate>
|
||||
beyond those provided by the parent L<PPI::Token::Quote>, L<PPI::Token> and
|
||||
L<PPI::Element> classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token::Quote ();
|
||||
use PPI::Token::_QuoteEngine::Full ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = qw{
|
||||
PPI::Token::_QuoteEngine::Full
|
||||
PPI::Token::Quote
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Token::Quote Methods
|
||||
|
||||
sub string {
|
||||
my $self = shift;
|
||||
my @sections = $self->_sections;
|
||||
my $str = $sections[0];
|
||||
substr( $self->{content}, $str->{position}, $str->{size} );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
80
database/perl/vendor/lib/PPI/Token/Quote/Literal.pm
vendored
Normal file
80
database/perl/vendor/lib/PPI/Token/Quote/Literal.pm
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
package PPI::Token::Quote::Literal;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Quote::Literal - The literal quote-like operator
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Quote::Literal
|
||||
isa PPI::Token::Quote
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A C<PPI::Token::Quote::Literal> object represents a single literal
|
||||
quote-like operator, such as C<q{foo bar}>.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
There are no methods available for C<PPI::Token::Quote::Literal> beyond
|
||||
those provided by the parent L<PPI::Token::Quote>, L<PPI::Token> and
|
||||
L<PPI::Element> classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token::Quote ();
|
||||
use PPI::Token::_QuoteEngine::Full ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = qw{
|
||||
PPI::Token::_QuoteEngine::Full
|
||||
PPI::Token::Quote
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Token::Quote Methods
|
||||
|
||||
sub string {
|
||||
my $self = shift;
|
||||
my @sections = $self->_sections;
|
||||
my $str = $sections[0];
|
||||
substr( $self->{content}, $str->{position}, $str->{size} );
|
||||
}
|
||||
|
||||
|
||||
# Use the same implementation as another module
|
||||
*literal = *PPI::Token::Quote::Single::literal;
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
93
database/perl/vendor/lib/PPI/Token/Quote/Single.pm
vendored
Normal file
93
database/perl/vendor/lib/PPI/Token/Quote/Single.pm
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
package PPI::Token::Quote::Single;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Quote::Single - A 'single quote' token
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Quote::Single
|
||||
isa PPI::Token::Quote
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
'This is a single quote'
|
||||
|
||||
q{This is a literal, but NOT a single quote}
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A C<PPI::Token::Quote::Single> object represents a single quoted string
|
||||
literal.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
There are no methods available for C<PPI::Token::Quote::Single> beyond
|
||||
those provided by the parent L<PPI::Token::Quote>, L<PPI::Token> and
|
||||
L<PPI::Element> classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token::Quote ();
|
||||
use PPI::Token::_QuoteEngine::Simple ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = qw{
|
||||
PPI::Token::_QuoteEngine::Simple
|
||||
PPI::Token::Quote
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Token::Quote Methods
|
||||
|
||||
sub string {
|
||||
my $str = $_[0]->{content};
|
||||
substr( $str, 1, length($str) - 2 );
|
||||
}
|
||||
|
||||
|
||||
my %UNESCAPE = (
|
||||
"\\'" => "'",
|
||||
"\\\\" => "\\",
|
||||
);
|
||||
|
||||
sub literal {
|
||||
# Unescape \\ and \' ONLY
|
||||
my $str = $_[0]->string;
|
||||
$str =~ s/(\\.)/$UNESCAPE{$1} || $1/ge;
|
||||
return $str;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
77
database/perl/vendor/lib/PPI/Token/QuoteLike.pm
vendored
Normal file
77
database/perl/vendor/lib/PPI/Token/QuoteLike.pm
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
package PPI::Token::QuoteLike;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::QuoteLike - Quote-like operator abstract base class
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::QuoteLike
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The C<PPI::Token::QuoteLike> class is never instantiated, and simply
|
||||
provides a common abstract base class for the five quote-like operator
|
||||
classes. In PPI, a "quote-like" is the set of quote-like things that
|
||||
exclude the string quotes and regular expressions.
|
||||
|
||||
The subclasses of C<PPI::Token::QuoteLike> are:
|
||||
|
||||
=over 2
|
||||
|
||||
=item qw{} - L<PPI::Token::QuoteLike::Words>
|
||||
|
||||
=item `` - L<PPI::Token::QuoteLike::Backtick>
|
||||
|
||||
=item qx{} - L<PPI::Token::QuoteLike::Command>
|
||||
|
||||
=item qr// - L<PPI::Token::QuoteLike::Regexp>
|
||||
|
||||
=item <FOO> - L<PPI::Token::QuoteLike::Readline>
|
||||
|
||||
=back
|
||||
|
||||
The names are hopefully obvious enough not to have to explain what
|
||||
each class is. See their pages for more details.
|
||||
|
||||
You may note that the backtick and command quote-like are treated
|
||||
separately, even though they do the same thing. This is intentional,
|
||||
as the inherit from and are processed by two different parts of the
|
||||
PPI's quote engine.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token";
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
62
database/perl/vendor/lib/PPI/Token/QuoteLike/Backtick.pm
vendored
Normal file
62
database/perl/vendor/lib/PPI/Token/QuoteLike/Backtick.pm
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
package PPI::Token::QuoteLike::Backtick;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::QuoteLike::Backtick - A `backticks` command token
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::QuoteLike::Backtick
|
||||
isa PPI::Token::QuoteLike
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A C<PPI::Token::QuoteLike::Backtick> object represents a command output
|
||||
capturing quote.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
There are no methods available for C<PPI::Token::QuoteLike::Backtick>
|
||||
beyond those provided by the parent L<PPI::Token::QuoteLike>, L<PPI::Token>
|
||||
and L<PPI::Element> classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token::QuoteLike ();
|
||||
use PPI::Token::_QuoteEngine::Simple ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = qw{
|
||||
PPI::Token::_QuoteEngine::Simple
|
||||
PPI::Token::QuoteLike
|
||||
};
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
62
database/perl/vendor/lib/PPI/Token/QuoteLike/Command.pm
vendored
Normal file
62
database/perl/vendor/lib/PPI/Token/QuoteLike/Command.pm
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
package PPI::Token::QuoteLike::Command;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::QuoteLike::Command - The command quote-like operator
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::QuoteLike::Command
|
||||
isa PPI::Token::QuoteLike
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A C<PPI::Token::QuoteLike::Command> object represents a command output
|
||||
capturing quote-like operator.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
There are no methods available for C<PPI::Token::QuoteLike::Command>
|
||||
beyond those provided by the parent L<PPI::Token::QuoteLike>, L<PPI::Token>
|
||||
and L<PPI::Element> classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token::QuoteLike ();
|
||||
use PPI::Token::_QuoteEngine::Full ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = qw{
|
||||
PPI::Token::_QuoteEngine::Full
|
||||
PPI::Token::QuoteLike
|
||||
};
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
71
database/perl/vendor/lib/PPI/Token/QuoteLike/Readline.pm
vendored
Normal file
71
database/perl/vendor/lib/PPI/Token/QuoteLike/Readline.pm
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
package PPI::Token::QuoteLike::Readline;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::QuoteLike::Readline - The readline quote-like operator
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::QuoteLike::Readline
|
||||
isa PPI::Token::QuoteLike
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The C<readline> quote-like operator is used to read either a single
|
||||
line from a file, or all the lines from a file, as follows.
|
||||
|
||||
# Read in a single line
|
||||
$line = <FILE>;
|
||||
|
||||
# From a scalar handle
|
||||
$line = <$filehandle>;
|
||||
|
||||
# Read all the lines
|
||||
@lines = <FILE>;
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
There are no methods available for C<PPI::Token::QuoteLike::Readline>
|
||||
beyond those provided by the parent L<PPI::Token::QuoteLike>, L<PPI::Token>
|
||||
and L<PPI::Element> classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token::QuoteLike ();
|
||||
use PPI::Token::_QuoteEngine::Full ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = qw{
|
||||
PPI::Token::_QuoteEngine::Full
|
||||
PPI::Token::QuoteLike
|
||||
};
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
126
database/perl/vendor/lib/PPI/Token/QuoteLike/Regexp.pm
vendored
Normal file
126
database/perl/vendor/lib/PPI/Token/QuoteLike/Regexp.pm
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
package PPI::Token::QuoteLike::Regexp;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::QuoteLike::Regexp - Regexp constructor quote-like operator
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::QuoteLike::Regexp
|
||||
isa PPI::Token::QuoteLike
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A C<PPI::Token::QuoteLike::Regexp> object represents the quote-like
|
||||
operator used to construct anonymous L<Regexp> objects, as follows.
|
||||
|
||||
# Create a Regexp object for a module filename
|
||||
my $module = qr/\.pm$/;
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
The following methods are provided by this class,
|
||||
beyond those provided by the parent L<PPI::Token::QuoteLike>,
|
||||
L<PPI::Token> and L<PPI::Element> classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token::QuoteLike ();
|
||||
use PPI::Token::_QuoteEngine::Full ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = qw{
|
||||
PPI::Token::_QuoteEngine::Full
|
||||
PPI::Token::QuoteLike
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Token::QuoteLike::Regexp Methods
|
||||
|
||||
=pod
|
||||
|
||||
=head2 get_match_string
|
||||
|
||||
The C<get_match_string> method returns the portion of the string that
|
||||
will be compiled into the match portion of the regexp.
|
||||
|
||||
=cut
|
||||
|
||||
sub get_match_string {
|
||||
return $_[0]->_section_content( 0 );
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 get_substitute_string
|
||||
|
||||
The C<get_substitute_string> method always returns C<undef>, since
|
||||
the C<qr{}> construction provides no substitution string. This method
|
||||
is provided for orthogonality with C<PPI::Token::Regexp>.
|
||||
|
||||
=cut
|
||||
|
||||
sub get_substitute_string {
|
||||
return undef;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 get_modifiers
|
||||
|
||||
The C<get_modifiers> method returns the modifiers that will be
|
||||
compiled into the regexp.
|
||||
|
||||
=cut
|
||||
|
||||
sub get_modifiers {
|
||||
return $_[0]->_modifiers();
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 get_delimiters
|
||||
|
||||
The C<get_delimiters> method returns the delimiters of the string as an
|
||||
array. The first and only element is the delimiters of the string to be
|
||||
compiled into a match string.
|
||||
|
||||
=cut
|
||||
|
||||
sub get_delimiters {
|
||||
return $_[0]->_delimiters();
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
88
database/perl/vendor/lib/PPI/Token/QuoteLike/Words.pm
vendored
Normal file
88
database/perl/vendor/lib/PPI/Token/QuoteLike/Words.pm
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
package PPI::Token::QuoteLike::Words;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::QuoteLike::Words - Word list constructor quote-like operator
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::QuoteLike::Words
|
||||
isa PPI::Token::QuoteLike
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A C<PPI::Token::QuoteLike::Words> object represents a quote-like operator
|
||||
that acts as a constructor for a list of words.
|
||||
|
||||
# Create a list for a significant chunk of the alphabet
|
||||
my @list = qw{a b c d e f g h i j k l};
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token::QuoteLike ();
|
||||
use PPI::Token::_QuoteEngine::Full ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = qw{
|
||||
PPI::Token::_QuoteEngine::Full
|
||||
PPI::Token::QuoteLike
|
||||
};
|
||||
|
||||
=pod
|
||||
|
||||
=head2 literal
|
||||
|
||||
Returns the words contained as a list. Note that this method does not check the
|
||||
context that the token is in; it always returns the list and not merely
|
||||
the last element if the token is in scalar context.
|
||||
|
||||
=cut
|
||||
|
||||
sub literal {
|
||||
my ( $self ) = @_;
|
||||
|
||||
my $content = $self->_section_content(0);
|
||||
return if !defined $content;
|
||||
|
||||
# Undo backslash escaping of '\', the left delimiter,
|
||||
# and the right delimiter. The right delimiter will
|
||||
# only exist with paired delimiters: qw() qw[] qw<> qw{}.
|
||||
my ( $left, $right ) = ( $self->_delimiters, '', '' );
|
||||
$content =~ s/\\([\Q$left$right\\\E])/$1/g;
|
||||
|
||||
my @words = split ' ', $content;
|
||||
|
||||
return @words;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
136
database/perl/vendor/lib/PPI/Token/Regexp.pm
vendored
Normal file
136
database/perl/vendor/lib/PPI/Token/Regexp.pm
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
package PPI::Token::Regexp;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Regexp - Regular expression abstract base class
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Regexp
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The C<PPI::Token::Regexp> class is never instantiated, and simply
|
||||
provides a common abstract base class for the three regular expression
|
||||
classes. These being:
|
||||
|
||||
=over 2
|
||||
|
||||
=item m// - L<PPI::Token::Regexp::Match>
|
||||
|
||||
=item s/// - L<PPI::Token::Regexp::Substitute>
|
||||
|
||||
=item tr/// - L<PPI::Token::Regexp::Transliterate>
|
||||
|
||||
=back
|
||||
|
||||
The names are hopefully obvious enough not to have to explain what
|
||||
each class is. See their pages for more details.
|
||||
|
||||
To save some confusion, it's worth pointing out here that C<qr//> is
|
||||
B<not> a regular expression (which PPI takes to mean something that
|
||||
will actually examine or modify a string), but rather a quote-like
|
||||
operator that acts as a constructor for compiled L<Regexp> objects.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
The following methods are inherited by this class' offspring:
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Token::Regexp Methods
|
||||
|
||||
=pod
|
||||
|
||||
=head2 get_match_string
|
||||
|
||||
The C<get_match_string> method returns the portion of the regexp that
|
||||
performs the match.
|
||||
|
||||
=cut
|
||||
|
||||
sub get_match_string {
|
||||
return $_[0]->_section_content( 0 );
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 get_substitute_string
|
||||
|
||||
The C<get_substitute_string> method returns the portion of the regexp
|
||||
that is substituted for the match, if any. If the regexp does not
|
||||
substitute, C<undef> is returned.
|
||||
|
||||
=cut
|
||||
|
||||
sub get_substitute_string {
|
||||
return $_[0]->_section_content( 1 );
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 get_modifiers
|
||||
|
||||
The C<get_modifiers> method returns the modifiers of the regexp.
|
||||
|
||||
=cut
|
||||
|
||||
sub get_modifiers {
|
||||
return $_[0]->_modifiers();
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 get_delimiters
|
||||
|
||||
The C<get_delimiters> method returns the delimiters of the regexp as
|
||||
an array. The first element is the delimiters of the match string, and
|
||||
the second element (if any) is the delimiters of the substitute string
|
||||
(if any).
|
||||
|
||||
=cut
|
||||
|
||||
sub get_delimiters {
|
||||
return $_[0]->_delimiters();
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
76
database/perl/vendor/lib/PPI/Token/Regexp/Match.pm
vendored
Normal file
76
database/perl/vendor/lib/PPI/Token/Regexp/Match.pm
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
package PPI::Token::Regexp::Match;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Regexp::Match - A standard pattern match regex
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Regexp::Match
|
||||
isa PPI::Token::Regexp
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
$text =~ m/match regexp/;
|
||||
$text =~ /match regexp/;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A C<PPI::Token::Regexp::Match> object represents a single match regular
|
||||
expression. Just to be doubly clear, here are things that are and
|
||||
B<aren't> considered a match regexp.
|
||||
|
||||
# Is a match regexp
|
||||
/This is a match regexp/;
|
||||
m/Old McDonald had a farm/eieio;
|
||||
|
||||
# These are NOT match regexp
|
||||
qr/This is a regexp quote-like operator/;
|
||||
s/This is a/replace regexp/;
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
There are no methods available for C<PPI::Token::Regexp::Match> beyond
|
||||
those provided by the parent L<PPI::Token::Regexp>, L<PPI::Token> and
|
||||
L<PPI::Element> classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token::Regexp ();
|
||||
use PPI::Token::_QuoteEngine::Full ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = qw{
|
||||
PPI::Token::_QuoteEngine::Full
|
||||
PPI::Token::Regexp
|
||||
};
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
66
database/perl/vendor/lib/PPI/Token/Regexp/Substitute.pm
vendored
Normal file
66
database/perl/vendor/lib/PPI/Token/Regexp/Substitute.pm
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
package PPI::Token::Regexp::Substitute;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Regexp::Substitute - A match and replace regular expression token
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Regexp::Substitute
|
||||
isa PPI::Token::Regexp
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
$text =~ s/find/$replace/;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A C<PPI::Token::Regexp::Substitute> object represents a single substitution
|
||||
regular expression.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
There are no methods available for C<PPI::Token::Regexp::Substitute>
|
||||
beyond those provided by the parent L<PPI::Token::Regexp>, L<PPI::Token>
|
||||
and L<PPI::Element> classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token::Regexp ();
|
||||
use PPI::Token::_QuoteEngine::Full ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = qw{
|
||||
PPI::Token::_QuoteEngine::Full
|
||||
PPI::Token::Regexp
|
||||
};
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
70
database/perl/vendor/lib/PPI/Token/Regexp/Transliterate.pm
vendored
Normal file
70
database/perl/vendor/lib/PPI/Token/Regexp/Transliterate.pm
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
package PPI::Token::Regexp::Transliterate;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Regexp::Transliterate - A transliteration regular expression token
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Regexp::Transliterate
|
||||
isa PPI::Token::Regexp
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
$text =~ tr/abc/xyz/;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A C<PPI::Token::Regexp::Transliterate> object represents a single
|
||||
transliteration regular expression.
|
||||
|
||||
I'm afraid you'll have to excuse the ridiculously long class name, but
|
||||
when push came to shove I ended up going for pedantically correct
|
||||
names for things (practically cut and paste from the various docs).
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
There are no methods available for C<PPI::Token::Regexp::Transliterate>
|
||||
beyond those provided by the parent L<PPI::Token::Regexp>, L<PPI::Token>
|
||||
and L<PPI::Element> classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token::Regexp ();
|
||||
use PPI::Token::_QuoteEngine::Full ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = qw{
|
||||
PPI::Token::_QuoteEngine::Full
|
||||
PPI::Token::Regexp
|
||||
};
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
64
database/perl/vendor/lib/PPI/Token/Separator.pm
vendored
Normal file
64
database/perl/vendor/lib/PPI/Token/Separator.pm
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
package PPI::Token::Separator;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Separator - The __DATA__ and __END__ tags
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Separator
|
||||
isa PPI::Token::Word
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Although superficially looking like a normal L<PPI::Token::Word> object,
|
||||
when the C<__DATA__> and C<__END__> compiler tags appear at the beginning of
|
||||
a line (on supposedly) their own line, these tags become file section
|
||||
separators.
|
||||
|
||||
The indicate that the time for Perl code is over, and the rest of the
|
||||
file is dedicated to something else (data in the case of C<__DATA__>) or
|
||||
to nothing at all (in the case of C<__END__>).
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
This class has no methods beyond what is provided by its
|
||||
L<PPI::Token::Word>, L<PPI::Token> and L<PPI::Element>
|
||||
parent classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token::Word ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token::Word";
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
209
database/perl/vendor/lib/PPI/Token/Structure.pm
vendored
Normal file
209
database/perl/vendor/lib/PPI/Token/Structure.pm
vendored
Normal file
@@ -0,0 +1,209 @@
|
||||
package PPI::Token::Structure;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Structure - Token class for characters that define code structure
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Structure
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The C<PPI::Token::Structure> class is used for tokens that control the
|
||||
general tree structure or code.
|
||||
|
||||
This consists of seven characters. These are the six brace characters from
|
||||
the "round", "curly" and "square" pairs, plus the semi-colon statement
|
||||
separator C<;>.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
This class has no methods beyond what is provided by its
|
||||
L<PPI::Token> and L<PPI::Element> parent classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token";
|
||||
|
||||
# Set the matching braces, done as an array
|
||||
# for slightly faster lookups.
|
||||
my %MATCH = (
|
||||
ord '{' => '}',
|
||||
ord '}' => '{',
|
||||
ord '[' => ']',
|
||||
ord ']' => '[',
|
||||
ord '(' => ')',
|
||||
ord ')' => '(',
|
||||
);
|
||||
my %OPENS = (
|
||||
ord '{' => 1,
|
||||
ord '[' => 1,
|
||||
ord '(' => 1,
|
||||
);
|
||||
my %CLOSES = (
|
||||
ord '}' => 1,
|
||||
ord ']' => 1,
|
||||
ord ')' => 1,
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Tokenizer Methods
|
||||
|
||||
sub __TOKENIZER__on_char {
|
||||
# Structures are one character long, always.
|
||||
# Finalize and process again.
|
||||
$_[1]->_finalize_token->__TOKENIZER__on_char( $_[1] );
|
||||
}
|
||||
|
||||
sub __TOKENIZER__commit {
|
||||
my $t = $_[1];
|
||||
$t->_new_token( 'Structure', substr( $t->{line}, $t->{line_cursor}, 1 ) );
|
||||
$t->_finalize_token;
|
||||
0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Lexer Methods
|
||||
|
||||
# For a given brace, find its opposing pair
|
||||
sub __LEXER__opposite {
|
||||
$MATCH{ord $_[0]->{content}};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Element Methods
|
||||
|
||||
# There is a unusual situation in regards to "siblings".
|
||||
#
|
||||
# As an Element, braces sit outside the normal tree structure, and in
|
||||
# this context they NEVER have siblings.
|
||||
#
|
||||
# However, as tokens they DO have siblings.
|
||||
#
|
||||
# As such, we need special versions of _all_ of the sibling methods to
|
||||
# handle this.
|
||||
#
|
||||
# Statement terminators do not have these problems, and for them sibling
|
||||
# calls work as normal, and so they can just be passed upwards.
|
||||
|
||||
sub next_sibling {
|
||||
return $_[0]->SUPER::next_sibling if $_[0]->{content} eq ';';
|
||||
return '';
|
||||
}
|
||||
|
||||
sub snext_sibling {
|
||||
return $_[0]->SUPER::snext_sibling if $_[0]->{content} eq ';';
|
||||
return '';
|
||||
}
|
||||
|
||||
sub previous_sibling {
|
||||
return $_[0]->SUPER::previous_sibling if $_[0]->{content} eq ';';
|
||||
return '';
|
||||
}
|
||||
|
||||
sub sprevious_sibling {
|
||||
return $_[0]->SUPER::sprevious_sibling if $_[0]->{content} eq ';';
|
||||
return '';
|
||||
}
|
||||
|
||||
sub next_token {
|
||||
my $self = shift;
|
||||
return $self->SUPER::next_token if $self->{content} eq ';';
|
||||
my $structure = $self->parent or return '';
|
||||
|
||||
# If this is an opening brace, descend down into our parent
|
||||
# structure, if it has children.
|
||||
if ( $OPENS{ ord $self->{content} } ) {
|
||||
my $child = $structure->child(0);
|
||||
if ( $child ) {
|
||||
# Decend deeper, or return if it is a token
|
||||
return $child->isa('PPI::Token') ? $child : $child->first_token;
|
||||
} elsif ( $structure->finish ) {
|
||||
# Empty structure, so next is closing brace
|
||||
return $structure->finish;
|
||||
}
|
||||
|
||||
# Anything that slips through to here is a structure
|
||||
# with an opening brace, but no closing brace, so we
|
||||
# just have to go with it, and continue as we would
|
||||
# if we started with a closing brace.
|
||||
}
|
||||
|
||||
# We can use the default implement, if we call it from the
|
||||
# parent structure of the closing brace.
|
||||
$structure->next_token;
|
||||
}
|
||||
|
||||
sub previous_token {
|
||||
my $self = shift;
|
||||
return $self->SUPER::previous_token if $self->{content} eq ';';
|
||||
my $structure = $self->parent or return '';
|
||||
|
||||
# If this is a closing brace, descend down into our parent
|
||||
# structure, if it has children.
|
||||
if ( $CLOSES{ ord $self->{content} } ) {
|
||||
my $child = $structure->child(-1);
|
||||
if ( $child ) {
|
||||
# Decend deeper, or return if it is a token
|
||||
return $child->isa('PPI::Token') ? $child : $child->last_token;
|
||||
} elsif ( $structure->start ) {
|
||||
# Empty structure, so next is closing brace
|
||||
return $structure->start;
|
||||
}
|
||||
|
||||
# Anything that slips through to here is a structure
|
||||
# with a closing brace, but no opening brace, so we
|
||||
# just have to go with it, and continue as we would
|
||||
# if we started with an opening brace.
|
||||
}
|
||||
|
||||
# We can use the default implement, if we call it from the
|
||||
# parent structure of the closing brace.
|
||||
$structure->previous_token;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
241
database/perl/vendor/lib/PPI/Token/Symbol.pm
vendored
Normal file
241
database/perl/vendor/lib/PPI/Token/Symbol.pm
vendored
Normal file
@@ -0,0 +1,241 @@
|
||||
package PPI::Token::Symbol;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Symbol - A token class for variables and other symbols
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Symbol
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The C<PPI::Token::Symbol> class is used to cover all tokens that represent
|
||||
variables and other things that start with a sigil.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
This class has several methods beyond what is provided by its
|
||||
L<PPI::Token> and L<PPI::Element> parent classes.
|
||||
|
||||
Most methods are provided to help work out what the object is actually
|
||||
pointing at, rather than what it might appear to be pointing at.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Params::Util qw{_INSTANCE};
|
||||
use PPI::Token ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# PPI::Token::Symbol Methods
|
||||
|
||||
=pod
|
||||
|
||||
=head2 canonical
|
||||
|
||||
The C<canonical> method returns a normalized, canonical version of the
|
||||
symbol.
|
||||
|
||||
For example, it converts C<$ ::foo'bar::baz> to C<$main::foo::bar::baz>.
|
||||
|
||||
This does not fully resolve the symbol, but merely removes syntax
|
||||
variations.
|
||||
|
||||
=cut
|
||||
|
||||
sub canonical {
|
||||
my $symbol = shift->content;
|
||||
$symbol =~ s/\s+//;
|
||||
$symbol =~ s/\'/::/g;
|
||||
$symbol =~ s/(?<=[\$\@\%\&\*])::/main::/;
|
||||
$symbol;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 symbol
|
||||
|
||||
The C<symbol> method returns the ACTUAL symbol this token refers to.
|
||||
|
||||
A token of C<$foo> might actually be referring to C<@foo>, if it is found
|
||||
in the form C<$foo[1]>.
|
||||
|
||||
This method attempts to resolve these issues to determine the actual
|
||||
symbol.
|
||||
|
||||
Returns the symbol as a string.
|
||||
|
||||
=cut
|
||||
|
||||
my %cast_which_trumps_braces = map { $_ => 1 } qw{ $ @ % };
|
||||
|
||||
sub symbol {
|
||||
my $self = shift;
|
||||
my $symbol = $self->canonical;
|
||||
|
||||
# Immediately return the cases where it can't be anything else
|
||||
my $type = substr( $symbol, 0, 1 );
|
||||
return $symbol if $type eq '&';
|
||||
|
||||
# Unless the next significant Element is a structure, it's correct.
|
||||
my $after = $self->snext_sibling;
|
||||
return $symbol unless _INSTANCE($after, 'PPI::Structure');
|
||||
|
||||
# Process the rest for cases where it might actually be something else
|
||||
my $braces = $after->braces;
|
||||
return $symbol unless defined $braces;
|
||||
if ( $type eq '$' ) {
|
||||
|
||||
# If it is cast to '$' or '@', that trumps any braces
|
||||
my $before = $self->sprevious_sibling;
|
||||
return $symbol if $before &&
|
||||
$before->isa( 'PPI::Token::Cast' ) &&
|
||||
$cast_which_trumps_braces{ $before->content };
|
||||
|
||||
# Otherwise the braces rule
|
||||
substr( $symbol, 0, 1, '@' ) if $braces eq '[]';
|
||||
substr( $symbol, 0, 1, '%' ) if $braces eq '{}';
|
||||
|
||||
} elsif ( $type eq '@' ) {
|
||||
substr( $symbol, 0, 1, '%' ) if $braces eq '{}';
|
||||
|
||||
} elsif ( $type eq '%' ) {
|
||||
substr( $symbol, 0, 1, '@' ) if $braces eq '[]';
|
||||
|
||||
}
|
||||
|
||||
$symbol;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 raw_type
|
||||
|
||||
The C<raw_type> method returns the B<apparent> type of the symbol in the
|
||||
form of its sigil.
|
||||
|
||||
Returns the sigil as a string.
|
||||
|
||||
=cut
|
||||
|
||||
sub raw_type {
|
||||
substr( $_[0]->content, 0, 1 );
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 symbol_type
|
||||
|
||||
The C<symbol_type> method returns the B<actual> type of the symbol in the
|
||||
form of its sigil.
|
||||
|
||||
Returns the sigil as a string.
|
||||
|
||||
=cut
|
||||
|
||||
sub symbol_type {
|
||||
substr( $_[0]->symbol, 0, 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Tokenizer Methods
|
||||
|
||||
sub __TOKENIZER__on_char {
|
||||
my $t = $_[1];
|
||||
|
||||
# Suck in till the end of the symbol
|
||||
pos $t->{line} = $t->{line_cursor};
|
||||
if ( $t->{line} =~ m/\G([\w:\']+)/gc ) {
|
||||
$t->{token}->{content} .= $1;
|
||||
$t->{line_cursor} += length $1;
|
||||
}
|
||||
|
||||
# Handle magic things
|
||||
my $content = $t->{token}->{content};
|
||||
if ( $content eq '@_' or $content eq '$_' ) {
|
||||
$t->{class} = $t->{token}->set_class( 'Magic' );
|
||||
return $t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
# Shortcut for most of the X:: symbols
|
||||
if ( $content eq '$::' ) {
|
||||
# May well be an alternate form of a Magic
|
||||
my $nextchar = substr( $t->{line}, $t->{line_cursor}, 1 );
|
||||
if ( $nextchar eq '|' ) {
|
||||
$t->{token}->{content} .= $nextchar;
|
||||
$t->{line_cursor}++;
|
||||
$t->{class} = $t->{token}->set_class( 'Magic' );
|
||||
}
|
||||
return $t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
if ( $content =~ /^[\$%*@&]::(?:[^\w]|$)/ ) {
|
||||
my $current = substr( $content, 0, 3, '' );
|
||||
$t->{token}->{content} = $current;
|
||||
$t->{line_cursor} -= length( $content );
|
||||
return $t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
if ( $content =~ /^(?:\$|\@)\d+/ ) {
|
||||
$t->{class} = $t->{token}->set_class( 'Magic' );
|
||||
return $t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
# Trim off anything we oversucked...
|
||||
$content =~ /^(
|
||||
[\$@%&*]
|
||||
(?: : (?!:) | # Allow single-colon non-magic variables
|
||||
(?: \w+ | \' (?!\d) \w+ | \:: \w+ )
|
||||
(?:
|
||||
# Allow both :: and ' in namespace separators
|
||||
(?: \' (?!\d) \w+ | \:: \w+ )
|
||||
)*
|
||||
(?: :: )? # Technically a compiler-magic hash, but keep it here
|
||||
)
|
||||
)/x or return undef;
|
||||
unless ( length $1 eq length $content ) {
|
||||
$t->{line_cursor} += length($1) - length($content);
|
||||
$t->{token}->{content} = $1;
|
||||
}
|
||||
|
||||
$t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
479
database/perl/vendor/lib/PPI/Token/Unknown.pm
vendored
Normal file
479
database/perl/vendor/lib/PPI/Token/Unknown.pm
vendored
Normal file
@@ -0,0 +1,479 @@
|
||||
package PPI::Token::Unknown;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Unknown - Token of unknown or as-yet undetermined type
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Unknown
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Object of the type C<PPI::Token::Unknown> exist primarily inside the
|
||||
tokenizer, where they are temporarily brought into existing for a very
|
||||
short time to represent a token that could be one of a number of types.
|
||||
|
||||
Generally, they only exist for a character or two, after which they are
|
||||
resolved and converted into the correct type. For an object of this type
|
||||
to survive the parsing process is considered a major bug.
|
||||
|
||||
Please report any C<PPI::Token::Unknown> you encounter in a L<PPI::Document>
|
||||
object as a bug.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token ();
|
||||
use PPI::Exception ();
|
||||
use PPI::Singletons qw' %MAGIC $CURLY_SYMBOL ';
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Tokenizer Methods
|
||||
|
||||
sub __TOKENIZER__on_char {
|
||||
my ( $self, $t ) = @_; # Self and Tokenizer
|
||||
my $c = $t->{token}->{content}; # Current token
|
||||
my $char = substr( $t->{line}, $t->{line_cursor}, 1 ); # Current character
|
||||
|
||||
# Now, we split on the different values of the current content
|
||||
if ( $c eq '*' ) {
|
||||
# Is it a number?
|
||||
if ( $char =~ /\d/ ) {
|
||||
# bitwise operator
|
||||
$t->{class} = $t->{token}->set_class( 'Operator' );
|
||||
return $t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
if ( $char =~ /[\w:]/ ) {
|
||||
# Symbol (unless the thing before it is a number
|
||||
my ( $prev ) = $t->_previous_significant_tokens(1);
|
||||
if ( not $prev or not $prev->isa('PPI::Token::Number') ) {
|
||||
$t->{class} = $t->{token}->set_class( 'Symbol' );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $char eq '{' ) {
|
||||
# Get rest of line
|
||||
pos $t->{line} = $t->{line_cursor} + 1;
|
||||
if ( $t->{line} =~ m/$CURLY_SYMBOL/gc ) {
|
||||
# control-character symbol (e.g. *{^_Foo})
|
||||
$t->{class} = $t->{token}->set_class( 'Magic' );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
# Postfix dereference: ->**
|
||||
if ( $char eq '*' ) {
|
||||
my ( $prev ) = $t->_previous_significant_tokens(1);
|
||||
if ( $prev and $prev->isa('PPI::Token::Operator') and $prev->content eq '->' ) {
|
||||
$t->{class} = $t->{token}->set_class( 'Cast' );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $char eq '*' || $char eq '=' ) {
|
||||
# Power operator '**' or mult-assign '*='
|
||||
$t->{class} = $t->{token}->set_class( 'Operator' );
|
||||
return 1;
|
||||
}
|
||||
|
||||
return $self->_as_cast_or_op($t) if $self->_is_cast_or_op($char);
|
||||
|
||||
$t->{class} = $t->{token}->set_class( 'Operator' );
|
||||
return $t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
|
||||
|
||||
|
||||
} elsif ( $c eq '$' ) {
|
||||
# Postfix dereference: ->$* ->$#*
|
||||
if ( $char eq '*' || $char eq '#' ) {
|
||||
my ( $prev ) = $t->_previous_significant_tokens(1);
|
||||
if ( $prev and $prev->isa('PPI::Token::Operator') and $prev->content eq '->' ) {
|
||||
$t->{class} = $t->{token}->set_class( 'Cast' );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $char =~ /[a-z_]/i ) {
|
||||
# Symbol
|
||||
$t->{class} = $t->{token}->set_class( 'Symbol' );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( $MAGIC{ $c . $char } ) {
|
||||
# Magic variable
|
||||
$t->{class} = $t->{token}->set_class( 'Magic' );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( $char eq '{' ) {
|
||||
# Get rest of line
|
||||
pos $t->{line} = $t->{line_cursor} + 1;
|
||||
if ( $t->{line} =~ m/$CURLY_SYMBOL/gc ) {
|
||||
# control-character symbol (e.g. ${^MATCH})
|
||||
$t->{class} = $t->{token}->set_class( 'Magic' );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
# Must be a cast
|
||||
$t->{class} = $t->{token}->set_class( 'Cast' );
|
||||
return $t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
|
||||
|
||||
|
||||
} elsif ( $c eq '@' ) {
|
||||
# Postfix dereference: ->@*
|
||||
if ( $char eq '*' ) {
|
||||
my ( $prev ) = $t->_previous_significant_tokens(1);
|
||||
if ( $prev and $prev->isa('PPI::Token::Operator') and $prev->content eq '->' ) {
|
||||
$t->{class} = $t->{token}->set_class( 'Cast' );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $char =~ /[\w:]/ ) {
|
||||
# Symbol
|
||||
$t->{class} = $t->{token}->set_class( 'Symbol' );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( $MAGIC{ $c . $char } ) {
|
||||
# Magic variable
|
||||
$t->{class} = $t->{token}->set_class( 'Magic' );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( $char eq '{' ) {
|
||||
# Get rest of line
|
||||
pos $t->{line} = $t->{line_cursor} + 1;
|
||||
if ( $t->{line} =~ m/$CURLY_SYMBOL/gc ) {
|
||||
# control-character symbol (e.g. @{^_Foo})
|
||||
$t->{class} = $t->{token}->set_class( 'Magic' );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
# Must be a cast
|
||||
$t->{class} = $t->{token}->set_class( 'Cast' );
|
||||
return $t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
|
||||
|
||||
|
||||
} elsif ( $c eq '%' ) {
|
||||
# Postfix dereference: ->%* ->%[...]
|
||||
if ( $char eq '*' || $char eq '[' ) {
|
||||
my ( $prev ) = $t->_previous_significant_tokens(1);
|
||||
if ( $prev and $prev->isa('PPI::Token::Operator') and $prev->content eq '->' ) {
|
||||
if ( $char eq '*' ) {
|
||||
$t->{class} = $t->{token}->set_class( 'Cast' );
|
||||
return 1;
|
||||
}
|
||||
if ( $char eq '[' ) {
|
||||
$t->{class} = $t->{token}->set_class( 'Cast' );
|
||||
return $t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Is it a number?
|
||||
if ( $char =~ /\d/ ) {
|
||||
# bitwise operator
|
||||
$t->{class} = $t->{token}->set_class( 'Operator' );
|
||||
return $t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
# Is it a magic variable?
|
||||
if ( $char eq '^' || $MAGIC{ $c . $char } ) {
|
||||
$t->{class} = $t->{token}->set_class( 'Magic' );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( $char =~ /[\w:]/ ) {
|
||||
# Symbol (unless the thing before it is a number
|
||||
my ( $prev ) = $t->_previous_significant_tokens(1);
|
||||
if ( not $prev or not $prev->isa('PPI::Token::Number') ) {
|
||||
$t->{class} = $t->{token}->set_class( 'Symbol' );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $char eq '{' ) {
|
||||
# Get rest of line
|
||||
pos $t->{line} = $t->{line_cursor} + 1;
|
||||
if ( $t->{line} =~ m/$CURLY_SYMBOL/gc ) {
|
||||
# control-character symbol (e.g. %{^_Foo})
|
||||
$t->{class} = $t->{token}->set_class( 'Magic' );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return $self->_as_cast_or_op($t) if $self->_is_cast_or_op($char);
|
||||
|
||||
# Probably the mod operator
|
||||
$t->{class} = $t->{token}->set_class( 'Operator' );
|
||||
return $t->{class}->__TOKENIZER__on_char( $t );
|
||||
|
||||
|
||||
|
||||
} elsif ( $c eq '&' ) {
|
||||
# Postfix dereference: ->&*
|
||||
if ( $char eq '*' ) {
|
||||
my ( $prev ) = $t->_previous_significant_tokens(1);
|
||||
if ( $prev and $prev->isa('PPI::Token::Operator') and $prev->content eq '->' ) {
|
||||
$t->{class} = $t->{token}->set_class( 'Cast' );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
# Is it a number?
|
||||
if ( $char =~ /\d/ ) {
|
||||
# bitwise operator
|
||||
$t->{class} = $t->{token}->set_class( 'Operator' );
|
||||
return $t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
if ( $char =~ /[\w:]/ ) {
|
||||
# Symbol (unless the thing before it is a number
|
||||
my ( $prev ) = $t->_previous_significant_tokens(1);
|
||||
if ( not $prev or not $prev->isa('PPI::Token::Number') ) {
|
||||
$t->{class} = $t->{token}->set_class( 'Symbol' );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return $self->_as_cast_or_op($t) if $self->_is_cast_or_op($char);
|
||||
|
||||
# Probably the binary and operator
|
||||
$t->{class} = $t->{token}->set_class( 'Operator' );
|
||||
return $t->{class}->__TOKENIZER__on_char( $t );
|
||||
|
||||
|
||||
|
||||
} elsif ( $c eq '-' ) {
|
||||
if ( $char =~ /\d/o ) {
|
||||
# Number
|
||||
$t->{class} = $t->{token}->set_class( 'Number' );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( $char eq '.' ) {
|
||||
# Number::Float
|
||||
$t->{class} = $t->{token}->set_class( 'Number::Float' );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( $char =~ /[a-zA-Z]/ ) {
|
||||
$t->{class} = $t->{token}->set_class( 'DashedWord' );
|
||||
return 1;
|
||||
}
|
||||
|
||||
# The numeric negative operator
|
||||
$t->{class} = $t->{token}->set_class( 'Operator' );
|
||||
return $t->{class}->__TOKENIZER__on_char( $t );
|
||||
|
||||
|
||||
|
||||
} elsif ( $c eq ':' ) {
|
||||
if ( $char eq ':' ) {
|
||||
# ::foo style bareword
|
||||
$t->{class} = $t->{token}->set_class( 'Word' );
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Now, : acts very very differently in different contexts.
|
||||
# Mainly, we need to find out if this is a subroutine attribute.
|
||||
# We'll leave a hint in the token to indicate that, if it is.
|
||||
if ( $self->__TOKENIZER__is_an_attribute( $t ) ) {
|
||||
# This : is an attribute indicator
|
||||
$t->{class} = $t->{token}->set_class( 'Operator' );
|
||||
$t->{token}->{_attribute} = 1;
|
||||
return $t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
# It MIGHT be a label, but it's probably the ?: trinary operator
|
||||
$t->{class} = $t->{token}->set_class( 'Operator' );
|
||||
return $t->{class}->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
# erm...
|
||||
PPI::Exception->throw('Unknown value in PPI::Token::Unknown token');
|
||||
}
|
||||
|
||||
sub _is_cast_or_op {
|
||||
my ( $self, $char ) = @_;
|
||||
return 1 if $char eq '$';
|
||||
return 1 if $char eq '@';
|
||||
return 1 if $char eq '%';
|
||||
return 1 if $char eq '*';
|
||||
return 1 if $char eq '{';
|
||||
return;
|
||||
}
|
||||
|
||||
sub _as_cast_or_op {
|
||||
my ( $self, $t ) = @_;
|
||||
my $class = _cast_or_op( $t );
|
||||
$t->{class} = $t->{token}->set_class( $class );
|
||||
return $t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
sub _prev_significant_w_cursor {
|
||||
my ( $tokens, $cursor, $extra_check ) = @_;
|
||||
while ( $cursor >= 0 ) {
|
||||
my $token = $tokens->[ $cursor-- ];
|
||||
next if !$token->significant;
|
||||
next if $extra_check and !$extra_check->($token);
|
||||
return ( $token, $cursor );
|
||||
}
|
||||
return ( undef, $cursor );
|
||||
}
|
||||
|
||||
# Operator/operand-sensitive, multiple or GLOB cast
|
||||
sub _cast_or_op {
|
||||
my ( $t ) = @_;
|
||||
|
||||
my $tokens = $t->{tokens};
|
||||
my $cursor = scalar( @$tokens ) - 1;
|
||||
my $token;
|
||||
|
||||
( $token, $cursor ) = _prev_significant_w_cursor( $tokens, $cursor );
|
||||
return 'Cast' if !$token; # token was first in the document
|
||||
|
||||
if ( $token->isa( 'PPI::Token::Structure' ) and $token->content eq '}' ) {
|
||||
|
||||
# Scan the token stream backwards an arbitrarily long way,
|
||||
# looking for the matching opening curly brace.
|
||||
my $structure_depth = 1;
|
||||
( $token, $cursor ) = _prev_significant_w_cursor(
|
||||
$tokens, $cursor,
|
||||
sub {
|
||||
my ( $token ) = @_;
|
||||
return if !$token->isa( 'PPI::Token::Structure' );
|
||||
if ( $token eq '}' ) {
|
||||
$structure_depth++;
|
||||
return;
|
||||
}
|
||||
if ( $token eq '{' ) {
|
||||
$structure_depth--;
|
||||
return if $structure_depth;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
);
|
||||
return 'Operator' if !$token; # no matching '{', probably an unbalanced '}'
|
||||
|
||||
# Scan past any whitespace
|
||||
( $token, $cursor ) = _prev_significant_w_cursor( $tokens, $cursor );
|
||||
return 'Operator' if !$token; # Document began with what must be a hash constructor.
|
||||
return 'Operator' if $token->isa( 'PPI::Token::Symbol' ); # subscript
|
||||
|
||||
my %meth_or_subscript_end = map { $_ => 1 } qw@ -> } ] @;
|
||||
return 'Operator' if $meth_or_subscript_end{ $token->content }; # subscript
|
||||
|
||||
my $content = $token->content;
|
||||
my $produces_or_wants_value =
|
||||
( $token->isa( 'PPI::Token::Word' ) and ( $content eq 'do' or $content eq 'eval' ) );
|
||||
return $produces_or_wants_value ? 'Operator' : 'Cast';
|
||||
}
|
||||
|
||||
my %list_start_or_term_end = map { $_ => 1 } qw@ ; ( { [ @;
|
||||
return 'Cast'
|
||||
if $token->isa( 'PPI::Token::Structure' ) and $list_start_or_term_end{ $token->content }
|
||||
or $token->isa( 'PPI::Token::Cast' )
|
||||
or $token->isa( 'PPI::Token::Operator' )
|
||||
or $token->isa( 'PPI::Token::Label' );
|
||||
|
||||
return 'Operator' if !$token->isa( 'PPI::Token::Word' );
|
||||
|
||||
( $token, $cursor ) = _prev_significant_w_cursor( $tokens, $cursor );
|
||||
return 'Cast' if !$token || $token->content ne '->';
|
||||
|
||||
return 'Operator';
|
||||
}
|
||||
|
||||
# Are we at a location where a ':' would indicate a subroutine attribute
|
||||
sub __TOKENIZER__is_an_attribute {
|
||||
my $t = $_[1]; # Tokenizer object
|
||||
my @tokens = $t->_previous_significant_tokens(3);
|
||||
my $p0 = $tokens[0];
|
||||
return '' if not $p0;
|
||||
|
||||
# If we just had another attribute, we are also an attribute
|
||||
return 1 if $p0->isa('PPI::Token::Attribute');
|
||||
|
||||
# If we just had a prototype, then we are an attribute
|
||||
return 1 if $p0->isa('PPI::Token::Prototype');
|
||||
|
||||
# Other than that, we would need to have had a bareword
|
||||
return '' unless $p0->isa('PPI::Token::Word');
|
||||
|
||||
# We could be an anonymous subroutine
|
||||
if ( $p0->isa('PPI::Token::Word') and $p0->content eq 'sub' ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Or, we could be a named subroutine
|
||||
my $p1 = $tokens[1];
|
||||
my $p2 = $tokens[2];
|
||||
if (
|
||||
$p1
|
||||
and
|
||||
$p1->isa('PPI::Token::Word')
|
||||
and
|
||||
$p1->content eq 'sub'
|
||||
and (
|
||||
not $p2
|
||||
or
|
||||
$p2->isa('PPI::Token::Structure')
|
||||
or (
|
||||
$p2->isa('PPI::Token::Whitespace')
|
||||
and
|
||||
$p2->content eq ''
|
||||
)
|
||||
)
|
||||
) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
# We aren't an attribute
|
||||
'';
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
454
database/perl/vendor/lib/PPI/Token/Whitespace.pm
vendored
Normal file
454
database/perl/vendor/lib/PPI/Token/Whitespace.pm
vendored
Normal file
@@ -0,0 +1,454 @@
|
||||
package PPI::Token::Whitespace;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Whitespace - Tokens representing ordinary white space
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Whitespace
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
As a full "round-trip" parser, PPI records every last byte in a
|
||||
file and ensure that it is included in the L<PPI::Document> object.
|
||||
|
||||
This even includes whitespace. In fact, Perl documents are seen
|
||||
as "floating in a sea of whitespace", and thus any document will
|
||||
contain vast quantities of C<PPI::Token::Whitespace> objects.
|
||||
|
||||
For the most part, you shouldn't notice them. Or at least, you
|
||||
shouldn't B<have> to notice them.
|
||||
|
||||
This means doing things like consistently using the "S for significant"
|
||||
series of L<PPI::Node> and L<PPI::Element> methods to do things.
|
||||
|
||||
If you want the nth child element, you should be using C<schild> rather
|
||||
than C<child>, and likewise C<snext_sibling>, C<sprevious_sibling>, and
|
||||
so on and so forth.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
Again, for the most part you should really B<not> need to do anything
|
||||
very significant with whitespace.
|
||||
|
||||
But there are a couple of convenience methods provided, beyond those
|
||||
provided by the parent L<PPI::Token> and L<PPI::Element> classes.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Clone ();
|
||||
use PPI::Token ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token";
|
||||
|
||||
=pod
|
||||
|
||||
=head2 null
|
||||
|
||||
Because L<PPI> sees documents as sitting on a sort of substrate made of
|
||||
whitespace, there are a couple of corner cases that get particularly
|
||||
nasty if they don't find whitespace in certain places.
|
||||
|
||||
Imagine walking down the beach to go into the ocean, and then quite
|
||||
unexpectedly falling off the side of the planet. Well it's somewhat
|
||||
equivalent to that, including the whole screaming death bit.
|
||||
|
||||
The C<null> method is a convenience provided to get some internals
|
||||
out of some of these corner cases.
|
||||
|
||||
Specifically it create a whitespace token that represents nothing,
|
||||
or at least the null string C<''>. It's a handy way to have some
|
||||
"whitespace" right where you need it, without having to have any
|
||||
actual characters.
|
||||
|
||||
=cut
|
||||
|
||||
my $null;
|
||||
|
||||
sub null {
|
||||
$null ||= $_[0]->new('');
|
||||
Clone::clone($null);
|
||||
}
|
||||
|
||||
### XS -> PPI/XS.xs:_PPI_Token_Whitespace__significant 0.900+
|
||||
sub significant() { '' }
|
||||
|
||||
=pod
|
||||
|
||||
=head2 tidy
|
||||
|
||||
C<tidy> is a convenience method for removing unneeded whitespace.
|
||||
|
||||
Specifically, it removes any whitespace from the end of a line.
|
||||
|
||||
Note that this B<doesn't> include POD, where you may well need
|
||||
to keep certain types of whitespace. The entire POD chunk lives
|
||||
in its own L<PPI::Token::Pod> object.
|
||||
|
||||
=cut
|
||||
|
||||
sub tidy {
|
||||
$_[0]->{content} =~ s/^\s+?(?>\n)//;
|
||||
1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Parsing Methods
|
||||
|
||||
# Build the class and commit maps
|
||||
my %COMMITMAP = (
|
||||
map( { ord $_ => 'PPI::Token::Word' } 'a' .. 'u', 'A' .. 'Z', qw" w y z _ " ), # no v or x
|
||||
map( { ord $_ => 'PPI::Token::Structure' } qw" ; [ ] { } ) " ),
|
||||
ord '#' => 'PPI::Token::Comment',
|
||||
ord 'v' => 'PPI::Token::Number::Version',
|
||||
);
|
||||
my %CLASSMAP = (
|
||||
map( { ord $_ => 'Number' } 0 .. 9 ),
|
||||
map( { ord $_ => 'Operator' } qw" = ? | + > . ! ~ ^ " ),
|
||||
map( { ord $_ => 'Unknown' } qw" * $ @ & : % " ),
|
||||
ord ',' => 'PPI::Token::Operator',
|
||||
ord "'" => 'Quote::Single',
|
||||
ord '"' => 'Quote::Double',
|
||||
ord '`' => 'QuoteLike::Backtick',
|
||||
ord '\\' => 'Cast',
|
||||
ord '_' => 'Word',
|
||||
9 => 'Whitespace', # A horizontal tab
|
||||
10 => 'Whitespace', # A newline
|
||||
12 => 'Whitespace', # A form feed
|
||||
13 => 'Whitespace', # A carriage return
|
||||
32 => 'Whitespace', # A normal space
|
||||
);
|
||||
|
||||
# Words (functions and keywords) after which a following / is
|
||||
# almost certainly going to be a regex
|
||||
my %MATCHWORD = map { $_ => 1 } qw{
|
||||
return
|
||||
split
|
||||
if
|
||||
unless
|
||||
grep
|
||||
map
|
||||
};
|
||||
|
||||
sub __TOKENIZER__on_line_start {
|
||||
my $t = $_[1];
|
||||
my $line = $t->{line};
|
||||
|
||||
# Can we classify the entire line in one go
|
||||
if ( $line =~ /^\s*$/ ) {
|
||||
# A whitespace line
|
||||
$t->_new_token( 'Whitespace', $line );
|
||||
return 0;
|
||||
|
||||
} elsif ( $line =~ /^\s*#/ ) {
|
||||
# A comment line
|
||||
$t->_new_token( 'Comment', $line );
|
||||
$t->_finalize_token;
|
||||
return 0;
|
||||
|
||||
} elsif ( $line =~ /^=(\w+)/ ) {
|
||||
# A Pod tag... change to pod mode
|
||||
$t->_new_token( 'Pod', $line );
|
||||
if ( $1 eq 'cut' ) {
|
||||
# This is an error, but one we'll ignore
|
||||
# Don't go into Pod mode, since =cut normally
|
||||
# signals the end of Pod mode
|
||||
} else {
|
||||
$t->{class} = 'PPI::Token::Pod';
|
||||
}
|
||||
return 0;
|
||||
|
||||
} elsif ( $line =~ /^use v6\-alpha\;/ ) {
|
||||
# Indicates a Perl 6 block. Make the initial
|
||||
# implementation just suck in the entire rest of the
|
||||
# file.
|
||||
my @perl6;
|
||||
while ( 1 ) {
|
||||
my $line6 = $t->_get_line;
|
||||
last unless defined $line6;
|
||||
push @perl6, $line6;
|
||||
}
|
||||
push @{ $t->{perl6} }, join '', @perl6;
|
||||
|
||||
# We only sucked in the block, we don't actually do
|
||||
# anything to the "use v6..." line. So return as if
|
||||
# we didn't find anything at all.
|
||||
return 1;
|
||||
}
|
||||
|
||||
1;
|
||||
}
|
||||
|
||||
sub __TOKENIZER__on_char {
|
||||
my $t = $_[1];
|
||||
my $c = substr $t->{line}, $t->{line_cursor}, 1;
|
||||
my $char = ord $c;
|
||||
|
||||
# Do we definitely know what something is?
|
||||
return $COMMITMAP{$char}->__TOKENIZER__commit($t) if $COMMITMAP{$char};
|
||||
|
||||
# Handle the simple option first
|
||||
return $CLASSMAP{$char} if $CLASSMAP{$char};
|
||||
|
||||
if ( $char == 40 ) { # $char eq '('
|
||||
# Finalise any whitespace token...
|
||||
$t->_finalize_token if $t->{token};
|
||||
|
||||
# Is this the beginning of a sub prototype?
|
||||
# We are a sub prototype IF
|
||||
# 1. The previous significant token is a bareword.
|
||||
# 2. The one before that is the word 'sub'.
|
||||
# 3. The one before that is a 'structure'
|
||||
|
||||
# Get the three previous significant tokens
|
||||
my @tokens = $t->_previous_significant_tokens(3);
|
||||
|
||||
# A normal subroutine declaration
|
||||
my $p1 = $tokens[1];
|
||||
my $p2 = $tokens[2];
|
||||
if (
|
||||
$tokens[0]
|
||||
and
|
||||
$tokens[0]->isa('PPI::Token::Word')
|
||||
and
|
||||
$p1
|
||||
and
|
||||
$p1->isa('PPI::Token::Word')
|
||||
and
|
||||
$p1->content eq 'sub'
|
||||
and (
|
||||
not $p2
|
||||
or
|
||||
$p2->isa('PPI::Token::Structure')
|
||||
or (
|
||||
$p2->isa('PPI::Token::Whitespace')
|
||||
and
|
||||
$p2->content eq ''
|
||||
)
|
||||
or (
|
||||
# Lexical subroutine
|
||||
$p2->isa('PPI::Token::Word')
|
||||
and
|
||||
$p2->content =~ /^(?:my|our|state)$/
|
||||
)
|
||||
)
|
||||
) {
|
||||
# This is a sub prototype
|
||||
return 'Prototype';
|
||||
}
|
||||
|
||||
# A prototyped anonymous subroutine
|
||||
my $p0 = $tokens[0];
|
||||
if ( $p0 and $p0->isa('PPI::Token::Word') and $p0->content eq 'sub'
|
||||
# Maybe it's invoking a method named 'sub'
|
||||
and not ( $p1 and $p1->isa('PPI::Token::Operator') and $p1->content eq '->')
|
||||
) {
|
||||
return 'Prototype';
|
||||
}
|
||||
|
||||
# This is a normal open bracket
|
||||
return 'Structure';
|
||||
|
||||
} elsif ( $char == 60 ) { # $char eq '<'
|
||||
# Finalise any whitespace token...
|
||||
$t->_finalize_token if $t->{token};
|
||||
|
||||
# This is either "less than" or "readline quote-like"
|
||||
# Do some context stuff to guess which.
|
||||
my $prev = $t->_last_significant_token;
|
||||
|
||||
# The most common group of less-thans are used like
|
||||
# $foo < $bar
|
||||
# 1 < $bar
|
||||
# $#foo < $bar
|
||||
return 'Operator' if $prev and $prev->isa('PPI::Token::Symbol');
|
||||
return 'Operator' if $prev and $prev->isa('PPI::Token::Magic');
|
||||
return 'Operator' if $prev and $prev->isa('PPI::Token::Number');
|
||||
return 'Operator' if $prev and $prev->isa('PPI::Token::ArrayIndex');
|
||||
|
||||
# If it is <<... it's a here-doc instead
|
||||
my $next_char = substr( $t->{line}, $t->{line_cursor} + 1, 2 );
|
||||
return 'Operator' if $next_char =~ /<[^>]/;
|
||||
|
||||
return 'Operator' if not $prev;
|
||||
|
||||
# The most common group of readlines are used like
|
||||
# while ( <...> )
|
||||
# while <>;
|
||||
my $prec = $prev->content;
|
||||
return 'QuoteLike::Readline'
|
||||
if ( $prev->isa('PPI::Token::Structure') and $prec eq '(' )
|
||||
or ( $prev->isa('PPI::Token::Structure') and $prec eq ';' )
|
||||
or ( $prev->isa('PPI::Token::Word') and $prec eq 'while' )
|
||||
or ( $prev->isa('PPI::Token::Operator') and $prec eq '=' )
|
||||
or ( $prev->isa('PPI::Token::Operator') and $prec eq ',' );
|
||||
|
||||
if ( $prev->isa('PPI::Token::Structure') and $prec eq '}' ) {
|
||||
# Could go either way... do a regex check
|
||||
# $foo->{bar} < 2;
|
||||
# grep { .. } <foo>;
|
||||
pos $t->{line} = $t->{line_cursor};
|
||||
if ( $t->{line} =~ m/\G<(?!\d)\w+>/gc ) {
|
||||
# Almost definitely readline
|
||||
return 'QuoteLike::Readline';
|
||||
}
|
||||
}
|
||||
|
||||
# Otherwise, we guess operator, which has been the default up
|
||||
# until this more comprehensive section was created.
|
||||
return 'Operator';
|
||||
|
||||
} elsif ( $char == 47 ) { # $char eq '/'
|
||||
# Finalise any whitespace token...
|
||||
$t->_finalize_token if $t->{token};
|
||||
|
||||
# This is either a "divided by" or a "start regex"
|
||||
# Do some context stuff to guess ( ack ) which.
|
||||
# Hopefully the guess will be good enough.
|
||||
my $prev = $t->_last_significant_token;
|
||||
|
||||
# Or as the very first thing in a file
|
||||
return 'Regexp::Match' if not $prev;
|
||||
|
||||
my $prec = $prev->content;
|
||||
|
||||
# Most times following an operator, we are a regex.
|
||||
# This includes cases such as:
|
||||
# , - As an argument in a list
|
||||
# .. - The second condition in a flip flop
|
||||
# =~ - A bound regex
|
||||
# !~ - Ditto
|
||||
return 'Regexp::Match' if $prev->isa('PPI::Token::Operator');
|
||||
|
||||
# After a symbol
|
||||
return 'Operator' if $prev->isa('PPI::Token::Symbol');
|
||||
if ( $prec eq ']' and $prev->isa('PPI::Token::Structure') ) {
|
||||
return 'Operator';
|
||||
}
|
||||
|
||||
# After another number
|
||||
return 'Operator' if $prev->isa('PPI::Token::Number');
|
||||
|
||||
# After going into scope/brackets
|
||||
if (
|
||||
$prev->isa('PPI::Token::Structure')
|
||||
and (
|
||||
$prec eq '('
|
||||
or
|
||||
$prec eq '{'
|
||||
or
|
||||
$prec eq ';'
|
||||
)
|
||||
) {
|
||||
return 'Regexp::Match';
|
||||
}
|
||||
|
||||
# Functions and keywords
|
||||
if (
|
||||
$MATCHWORD{$prec}
|
||||
and
|
||||
$prev->isa('PPI::Token::Word')
|
||||
) {
|
||||
return 'Regexp::Match';
|
||||
}
|
||||
|
||||
# What about the char after the slash? There's some things
|
||||
# that would be highly illogical to see if it's an operator.
|
||||
my $next_char = substr $t->{line}, $t->{line_cursor} + 1, 1;
|
||||
if ( defined $next_char and length $next_char ) {
|
||||
if ( $next_char =~ /(?:\^|\[|\\)/ ) {
|
||||
return 'Regexp::Match';
|
||||
}
|
||||
}
|
||||
|
||||
# Otherwise... erm... assume operator?
|
||||
# Add more tests here as potential cases come to light
|
||||
return 'Operator';
|
||||
|
||||
} elsif ( $char == 120 ) { # $char eq 'x'
|
||||
# Could be a word, the x= operator, the x operator
|
||||
# followed by whitespace, or the x operator without any
|
||||
# space between itself and its operand, e.g.: '$a x3',
|
||||
# which is the same as '$a x 3'. _current_x_is_operator
|
||||
# assumes we have a complete 'x' token, but we don't
|
||||
# yet. We may need to split this x character apart from
|
||||
# what follows it.
|
||||
if ( $t->_current_x_is_operator ) {
|
||||
pos $t->{line} = $t->{line_cursor} + 1;
|
||||
return 'Operator' if $t->{line} =~ m/\G(?:
|
||||
\d # x op with no whitespace e.g. 'x3'
|
||||
|
|
||||
(?!( # negative lookahead
|
||||
=> # not on left of fat comma
|
||||
|
|
||||
\w # not a word like "xyzzy"
|
||||
|
|
||||
\s # not x op plus whitespace
|
||||
))
|
||||
)/gcx;
|
||||
}
|
||||
|
||||
# Otherwise, commit like a normal bareword, including x
|
||||
# operator followed by whitespace.
|
||||
return PPI::Token::Word->__TOKENIZER__commit($t);
|
||||
|
||||
} elsif ( $char == 45 ) { # $char eq '-'
|
||||
# Look for an obvious operator operand context
|
||||
my $context = $t->_opcontext;
|
||||
if ( $context eq 'operator' ) {
|
||||
return 'Operator';
|
||||
} else {
|
||||
# More logic needed
|
||||
return 'Unknown';
|
||||
}
|
||||
|
||||
} elsif ( $char >= 128 ) { # Outside ASCII
|
||||
return 'PPI::Token::Word'->__TOKENIZER__commit($t) if $c =~ /\w/;
|
||||
return 'Whitespace' if $c =~ /\s/;
|
||||
}
|
||||
|
||||
|
||||
# All the whitespaces are covered, so what to do
|
||||
### For now, die
|
||||
PPI::Exception->throw("Encountered unexpected character '$char'");
|
||||
}
|
||||
|
||||
sub __TOKENIZER__on_line_end {
|
||||
$_[1]->_finalize_token if $_[1]->{token};
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
373
database/perl/vendor/lib/PPI/Token/Word.pm
vendored
Normal file
373
database/perl/vendor/lib/PPI/Token/Word.pm
vendored
Normal file
@@ -0,0 +1,373 @@
|
||||
package PPI::Token::Word;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::Word - The generic "word" Token
|
||||
|
||||
=head1 INHERITANCE
|
||||
|
||||
PPI::Token::Word
|
||||
isa PPI::Token
|
||||
isa PPI::Element
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A C<PPI::Token::Word> object is a PPI-specific representation of several
|
||||
different types of word-like things, and is one of the most common Token
|
||||
classes found in typical documents.
|
||||
|
||||
Specifically, it includes not only barewords, but also any other valid
|
||||
Perl identifier including non-operator keywords and core functions, and
|
||||
any include C<::> separators inside it, as long as it fits the
|
||||
format of a class, function, etc.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
There are no methods available for C<PPI::Token::Word> beyond those
|
||||
provided by its L<PPI::Token> and L<PPI::Element> parent
|
||||
classes.
|
||||
|
||||
We expect to add additional methods to help further resolve a Word as
|
||||
a function, method, etc over time. If you need such a thing right
|
||||
now, look at L<Perl::Critic::Utils>.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use PPI::Token ();
|
||||
use PPI::Singletons qw' %OPERATOR %QUOTELIKE %KEYWORDS ';
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = "PPI::Token";
|
||||
|
||||
=pod
|
||||
|
||||
=head2 literal
|
||||
|
||||
Returns the value of the Word as a string. This assumes (often
|
||||
incorrectly) that the Word is a bareword and not a function, method,
|
||||
keyword, etc. This differs from C<content> because C<Foo'Bar> expands
|
||||
to C<Foo::Bar>.
|
||||
|
||||
=cut
|
||||
|
||||
sub literal {
|
||||
my $self = shift;
|
||||
my $word = $self->content;
|
||||
|
||||
# Expand Foo'Bar to Foo::Bar
|
||||
$word =~ s/\'/::/g;
|
||||
|
||||
return $word;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 method_call
|
||||
|
||||
Answers whether this is the name of a method in a method call. Returns true if
|
||||
yes, false if no, and nothing if unknown.
|
||||
|
||||
=cut
|
||||
|
||||
sub method_call {
|
||||
my $self = shift;
|
||||
|
||||
my $previous = $self->sprevious_sibling;
|
||||
if (
|
||||
$previous
|
||||
and
|
||||
$previous->isa('PPI::Token::Operator')
|
||||
and
|
||||
$previous->content eq '->'
|
||||
) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
my $snext = $self->snext_sibling;
|
||||
return 0 unless $snext;
|
||||
|
||||
if (
|
||||
$snext->isa('PPI::Structure::List')
|
||||
or
|
||||
$snext->isa('PPI::Token::Structure')
|
||||
or
|
||||
$snext->isa('PPI::Token::Operator')
|
||||
and (
|
||||
$snext->content eq ','
|
||||
or
|
||||
$snext->content eq '=>'
|
||||
)
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (
|
||||
$snext->isa('PPI::Token::Word')
|
||||
and
|
||||
$snext->content =~ m< \w :: \z >xms
|
||||
) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
sub __TOKENIZER__on_char {
|
||||
my $class = shift;
|
||||
my $t = shift;
|
||||
|
||||
# Suck in till the end of the bareword
|
||||
pos $t->{line} = $t->{line_cursor};
|
||||
if ( $t->{line} =~ m/\G(\w+(?:(?:\'|::)\w+)*(?:::)?)/gc ) {
|
||||
my $word = $1;
|
||||
# Special Case: If we accidentally treat eq'foo' like
|
||||
# the word "eq'foo", then just make 'eq' (or whatever
|
||||
# else is in the %KEYWORDS hash.
|
||||
if ( $word =~ /^(\w+)'/ && $KEYWORDS{$1} ) {
|
||||
$word = $1;
|
||||
}
|
||||
$t->{token}->{content} .= $word;
|
||||
$t->{line_cursor} += length $word;
|
||||
|
||||
}
|
||||
|
||||
# We might be a subroutine attribute.
|
||||
if ( __current_token_is_attribute($t) ) {
|
||||
$t->{class} = $t->{token}->set_class( 'Attribute' );
|
||||
return $t->{class}->__TOKENIZER__commit( $t );
|
||||
}
|
||||
|
||||
my $word = $t->{token}->{content};
|
||||
if ( $KEYWORDS{$word} ) {
|
||||
# Check for a Perl keyword that is forced to be a normal word instead
|
||||
if ( $t->__current_token_is_forced_word ) {
|
||||
$t->{class} = $t->{token}->set_class( 'Word' );
|
||||
return $t->{class}->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
# Check for a quote like operator. %QUOTELIKE must be subset of %KEYWORDS
|
||||
if ( $QUOTELIKE{$word} ) {
|
||||
$t->{class} = $t->{token}->set_class( $QUOTELIKE{$word} );
|
||||
return $t->{class}->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
# Or one of the word operators. %OPERATOR must be subset of %KEYWORDS
|
||||
if ( $OPERATOR{$word} ) {
|
||||
$t->{class} = $t->{token}->set_class( 'Operator' );
|
||||
return $t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
}
|
||||
|
||||
# Unless this is a simple identifier, at this point
|
||||
# it has to be a normal bareword
|
||||
if ( $word =~ /\:/ ) {
|
||||
return $t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
# If the NEXT character in the line is a colon, this
|
||||
# is a label.
|
||||
my $char = substr( $t->{line}, $t->{line_cursor}, 1 );
|
||||
if ( $char eq ':' ) {
|
||||
$t->{token}->{content} .= ':';
|
||||
$t->{line_cursor}++;
|
||||
$t->{class} = $t->{token}->set_class( 'Label' );
|
||||
|
||||
# If not a label, '_' on its own is the magic filehandle
|
||||
} elsif ( $word eq '_' ) {
|
||||
$t->{class} = $t->{token}->set_class( 'Magic' );
|
||||
|
||||
}
|
||||
|
||||
# Finalise and process the character again
|
||||
$t->_finalize_token->__TOKENIZER__on_char( $t );
|
||||
}
|
||||
|
||||
|
||||
|
||||
# We are committed to being a bareword.
|
||||
# Or so we would like to believe.
|
||||
sub __TOKENIZER__commit {
|
||||
my ($class, $t) = @_;
|
||||
|
||||
# Our current position is the first character of the bareword.
|
||||
# Capture the bareword.
|
||||
pos $t->{line} = $t->{line_cursor};
|
||||
unless ( $t->{line} =~ m/\G((?!\d)\w+(?:(?:\'|::)\w+)*(?:::)?)/gc ) {
|
||||
# Programmer error
|
||||
die sprintf "Fatal error... regex failed to match in '%s' when expected", substr $t->{line}, $t->{line_cursor};
|
||||
}
|
||||
|
||||
# Special Case: If we accidentally treat eq'foo' like the word "eq'foo",
|
||||
# then unwind it and just make it 'eq' (or the other stringy comparitors)
|
||||
my $word = $1;
|
||||
if ( $word =~ /^(\w+)'/ && $KEYWORDS{$1} ) {
|
||||
$word = $1;
|
||||
}
|
||||
|
||||
# Advance the position one after the end of the bareword
|
||||
$t->{line_cursor} += length $word;
|
||||
|
||||
# We might be a subroutine attribute.
|
||||
if ( __current_token_is_attribute($t) ) {
|
||||
$t->_new_token( 'Attribute', $word );
|
||||
return ($t->{line_cursor} >= $t->{line_length}) ? 0
|
||||
: $t->{class}->__TOKENIZER__on_char($t);
|
||||
}
|
||||
|
||||
# Check for the end of the file
|
||||
if ( $word eq '__END__' ) {
|
||||
# Create the token for the __END__ itself
|
||||
$t->_new_token( 'Separator', $1 );
|
||||
$t->_finalize_token;
|
||||
|
||||
# Move into the End zone (heh)
|
||||
$t->{zone} = 'PPI::Token::End';
|
||||
|
||||
# Add the rest of the line as a comment, and a whitespace newline
|
||||
# Anything after the __END__ on the line is "ignored". So we must
|
||||
# also ignore it, by turning it into a comment.
|
||||
my $end_rest = substr( $t->{line}, $t->{line_cursor} );
|
||||
$t->{line_cursor} = length $t->{line};
|
||||
if ( $end_rest =~ /\n$/ ) {
|
||||
chomp $end_rest;
|
||||
$t->_new_token( 'Comment', $end_rest ) if length $end_rest;
|
||||
$t->_new_token( 'Whitespace', "\n" );
|
||||
} else {
|
||||
$t->_new_token( 'Comment', $end_rest ) if length $end_rest;
|
||||
}
|
||||
$t->_finalize_token;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Check for the data section
|
||||
if ( $word eq '__DATA__' ) {
|
||||
# Create the token for the __DATA__ itself
|
||||
$t->_new_token( 'Separator', "$1" );
|
||||
$t->_finalize_token;
|
||||
|
||||
# Move into the Data zone
|
||||
$t->{zone} = 'PPI::Token::Data';
|
||||
|
||||
# Add the rest of the line as the Data token
|
||||
my $data_rest = substr( $t->{line}, $t->{line_cursor} );
|
||||
$t->{line_cursor} = length $t->{line};
|
||||
if ( $data_rest =~ /\n$/ ) {
|
||||
chomp $data_rest;
|
||||
$t->_new_token( 'Comment', $data_rest ) if length $data_rest;
|
||||
$t->_new_token( 'Whitespace', "\n" );
|
||||
} else {
|
||||
$t->_new_token( 'Comment', $data_rest ) if length $data_rest;
|
||||
}
|
||||
$t->_finalize_token;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
my $token_class;
|
||||
if ( $word =~ /\:/ ) {
|
||||
# Since it's not a simple identifier...
|
||||
$token_class = 'Word';
|
||||
|
||||
} elsif ( $KEYWORDS{$word} and $t->__current_token_is_forced_word ) {
|
||||
$token_class = 'Word';
|
||||
|
||||
} elsif ( $QUOTELIKE{$word} ) {
|
||||
# Special Case: A Quote-like operator
|
||||
$t->_new_token( $QUOTELIKE{$word}, $word );
|
||||
return ($t->{line_cursor} >= $t->{line_length}) ? 0
|
||||
: $t->{class}->__TOKENIZER__on_char( $t );
|
||||
|
||||
} elsif ( $OPERATOR{$word} && ($word ne 'x' || $t->_current_x_is_operator) ) {
|
||||
# Word operator
|
||||
$token_class = 'Operator';
|
||||
|
||||
} else {
|
||||
# Get tokens early to be sure to not disturb state set up by pos and m//gc.
|
||||
my @tokens = $t->_previous_significant_tokens(1);
|
||||
|
||||
# If the next character is a ':' then it's a label...
|
||||
pos $t->{line} = $t->{line_cursor};
|
||||
if ( $t->{line} =~ m/\G(\s*:)(?!:)/gc ) {
|
||||
if ( $tokens[0] and $tokens[0]->{content} eq 'sub' ) {
|
||||
# ... UNLESS it's after 'sub' in which
|
||||
# case it is a sub name and an attribute
|
||||
# operator.
|
||||
# We COULD have checked this at the top
|
||||
# level of checks, but this would impose
|
||||
# an additional performance per-word
|
||||
# penalty, and every other case where the
|
||||
# attribute operator doesn't directly
|
||||
# touch the object name already works.
|
||||
$token_class = 'Word';
|
||||
} else {
|
||||
$word .= $1;
|
||||
$t->{line_cursor} += length($1);
|
||||
$token_class = 'Label';
|
||||
}
|
||||
} elsif ( $word eq '_' ) {
|
||||
$token_class = 'Magic';
|
||||
} else {
|
||||
$token_class = 'Word';
|
||||
}
|
||||
}
|
||||
|
||||
# Create the new token and finalise
|
||||
$t->_new_token( $token_class, $word );
|
||||
if ( $t->{line_cursor} >= $t->{line_length} ) {
|
||||
# End of the line
|
||||
$t->_finalize_token;
|
||||
return 0;
|
||||
}
|
||||
$t->_finalize_token->__TOKENIZER__on_char($t);
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Is the current Word really a subroutine attribute?
|
||||
sub __current_token_is_attribute {
|
||||
my ( $t ) = @_;
|
||||
my @tokens = $t->_previous_significant_tokens(1);
|
||||
return (
|
||||
$tokens[0]
|
||||
and (
|
||||
# hint from tokenizer
|
||||
$tokens[0]->{_attribute}
|
||||
# nothing between attribute and us except whitespace
|
||||
or $tokens[0]->isa('PPI::Token::Attribute')
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 TO DO
|
||||
|
||||
- Add C<function>, C<method> etc detector methods
|
||||
|
||||
=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
|
||||
240
database/perl/vendor/lib/PPI/Token/_QuoteEngine.pm
vendored
Normal file
240
database/perl/vendor/lib/PPI/Token/_QuoteEngine.pm
vendored
Normal file
@@ -0,0 +1,240 @@
|
||||
package PPI::Token::_QuoteEngine;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Token::_QuoteEngine - The PPI Quote Engine
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The C<PPI::Token::_QuoteEngine> package is designed hold functionality
|
||||
for processing quotes and quote like operators, including regexes.
|
||||
These have special requirements in parsing.
|
||||
|
||||
The C<PPI::Token::_QuoteEngine> package itself provides various parsing
|
||||
methods, which the L<PPI::Token::Quote>, L<PPI::Token::QuoteLike> and
|
||||
L<PPI::Token::Regexp> can inherit from. In this sense, it serves
|
||||
as a base class.
|
||||
|
||||
=head2 Using this class
|
||||
|
||||
I<(Refers only to internal uses. This class does not provide a
|
||||
public interface)>
|
||||
|
||||
To use these, you should initialize them as normal C<'$Class-E<gt>new'>,
|
||||
and then call the 'fill' method, which will cause the specialised
|
||||
parser to scan forwards and parse the quote to its end point.
|
||||
|
||||
If -E<gt>fill returns true, finalise the token.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Carp ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Hook for the __TOKENIZER__on_char token call
|
||||
sub __TOKENIZER__on_char {
|
||||
my $class = shift;
|
||||
my $t = $_[0]->{token} ? shift : return undef;
|
||||
|
||||
# Call the fill method to process the quote
|
||||
my $rv = $t->{token}->_fill( $t );
|
||||
return undef unless defined $rv;
|
||||
|
||||
## Doesn't support "end of file" indicator
|
||||
|
||||
# Finalize the token and return 0 to tell the tokenizer
|
||||
# to go to the next character.
|
||||
$t->_finalize_token;
|
||||
|
||||
0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Optimised character processors, used for quotes
|
||||
# and quote like stuff, and accessible to the child classes
|
||||
|
||||
# An outright scan, raw and fast.
|
||||
# Searches for a particular character, not escaped, loading in new
|
||||
# lines as needed.
|
||||
# When called, we start at the current position.
|
||||
# When leaving, the position should be set to the position
|
||||
# of the character, NOT the one after it.
|
||||
sub _scan_for_unescaped_character {
|
||||
my $class = shift;
|
||||
my $t = shift;
|
||||
my $char = (length $_[0] == 1) ? quotemeta shift : return undef;
|
||||
|
||||
# Create the search regex.
|
||||
# Same as above but with a negative look-behind assertion.
|
||||
my $search = qr/(.*?(?<!\\)(?:\\\\)*$char)/;
|
||||
|
||||
my $string = '';
|
||||
while ( exists $t->{line} ) {
|
||||
# Get the search area for the current line
|
||||
pos $t->{line} = $t->{line_cursor};
|
||||
|
||||
# Can we find a match on this line
|
||||
if ( $t->{line} =~ m/\G$search/gc ) {
|
||||
# Found the character on this line
|
||||
$t->{line_cursor} += length($1) - 1;
|
||||
return $string . $1;
|
||||
}
|
||||
|
||||
# Load in the next line
|
||||
$string .= substr $t->{line}, $t->{line_cursor};
|
||||
my $rv = $t->_fill_line('inscan');
|
||||
if ( $rv ) {
|
||||
# Push to first character
|
||||
$t->{line_cursor} = 0;
|
||||
} elsif ( defined $rv ) {
|
||||
# We hit the End of File
|
||||
return \$string;
|
||||
} else {
|
||||
# Unexpected error
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
# We shouldn't be able to get here
|
||||
return undef;
|
||||
}
|
||||
|
||||
# Scan for a close braced, and take into account both escaping,
|
||||
# and open close bracket pairs in the string. When complete, the
|
||||
# method leaves the line cursor on the LAST character found.
|
||||
sub _scan_for_brace_character {
|
||||
my $class = shift;
|
||||
my $t = shift;
|
||||
my $close_brace = $_[0] =~ /^(?:\>|\)|\}|\])$/ ? shift : Carp::confess(''); # return undef;
|
||||
my $open_brace = $close_brace;
|
||||
$open_brace =~ tr/\>\)\}\]/\<\(\{\[/;
|
||||
|
||||
# Create the search string
|
||||
$close_brace = quotemeta $close_brace;
|
||||
$open_brace = quotemeta $open_brace;
|
||||
my $search = qr/\G(.*?(?<!\\)(?:\\\\)*(?:$open_brace|$close_brace))/;
|
||||
|
||||
# Loop as long as we can get new lines
|
||||
my $string = '';
|
||||
my $depth = 1;
|
||||
while ( exists $t->{line} ) {
|
||||
# Get the search area
|
||||
pos $t->{line} = $t->{line_cursor};
|
||||
|
||||
# Look for a match
|
||||
unless ( $t->{line} =~ /$search/gc ) {
|
||||
# Load in the next line
|
||||
$string .= substr( $t->{line}, $t->{line_cursor} );
|
||||
my $rv = $t->_fill_line('inscan');
|
||||
if ( $rv ) {
|
||||
# Push to first character
|
||||
$t->{line_cursor} = 0;
|
||||
next;
|
||||
}
|
||||
if ( defined $rv ) {
|
||||
# We hit the End of File
|
||||
return \$string;
|
||||
}
|
||||
|
||||
# Unexpected error
|
||||
return undef;
|
||||
}
|
||||
|
||||
# Add to the string
|
||||
$string .= $1;
|
||||
$t->{line_cursor} += length $1;
|
||||
|
||||
# Alter the depth and continue if we aren't at the end
|
||||
$depth += ($1 =~ /$open_brace$/) ? 1 : -1 and next;
|
||||
|
||||
# Rewind the cursor by one character ( cludgy hack )
|
||||
$t->{line_cursor} -= 1;
|
||||
return $string;
|
||||
}
|
||||
|
||||
# Returning the string as a reference indicates EOF
|
||||
\$string;
|
||||
}
|
||||
|
||||
# Find all spaces and comments, up to, but not including
|
||||
# the first non-whitespace character.
|
||||
#
|
||||
# Although it doesn't return it, it leaves the cursor
|
||||
# on the character following the gap
|
||||
sub _scan_quote_like_operator_gap {
|
||||
my $t = $_[1];
|
||||
|
||||
my $string = '';
|
||||
while ( exists $t->{line} ) {
|
||||
# Get the search area for the current line
|
||||
pos $t->{line} = $t->{line_cursor};
|
||||
|
||||
# Since this regex can match zero characters, it should always match
|
||||
$t->{line} =~ /\G(\s*(?:\#.*)?)/gc or return undef;
|
||||
|
||||
# Add the chars found to the string
|
||||
$string .= $1;
|
||||
|
||||
# Did we match the entire line?
|
||||
unless ( $t->{line_cursor} + length $1 == length $t->{line} ) {
|
||||
# Partial line match, which means we are at
|
||||
# the end of the gap. Fix the cursor and return
|
||||
# the string.
|
||||
$t->{line_cursor} += length $1;
|
||||
return $string;
|
||||
}
|
||||
|
||||
# Load in the next line.
|
||||
# If we reach the EOF, $t->{line} gets deleted,
|
||||
# which is caught by the while.
|
||||
my $rv = $t->_fill_line('inscan');
|
||||
if ( $rv ) {
|
||||
# Set the cursor to the first character
|
||||
$t->{line_cursor} = 0;
|
||||
} elsif ( defined $rv ) {
|
||||
# Returning the string as a reference indicates EOF
|
||||
return \$string;
|
||||
} else {
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
# Shouldn't be able to get here
|
||||
return undef;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
448
database/perl/vendor/lib/PPI/Token/_QuoteEngine/Full.pm
vendored
Normal file
448
database/perl/vendor/lib/PPI/Token/_QuoteEngine/Full.pm
vendored
Normal file
@@ -0,0 +1,448 @@
|
||||
package PPI::Token::_QuoteEngine::Full;
|
||||
|
||||
# Full quote engine
|
||||
|
||||
use strict;
|
||||
use Clone ();
|
||||
use Carp ();
|
||||
use PPI::Token::_QuoteEngine ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = 'PPI::Token::_QuoteEngine';
|
||||
|
||||
# Prototypes for the different braced sections
|
||||
my %SECTIONS = (
|
||||
'(' => { type => '()', _close => ')' },
|
||||
'<' => { type => '<>', _close => '>' },
|
||||
'[' => { type => '[]', _close => ']' },
|
||||
'{' => { type => '{}', _close => '}' },
|
||||
);
|
||||
|
||||
# For each quote type, the extra fields that should be set.
|
||||
# This should give us faster initialization.
|
||||
my %QUOTES = (
|
||||
'q' => { operator => 'q', braced => undef, separator => undef, _sections => 1 },
|
||||
'qq' => { operator => 'qq', braced => undef, separator => undef, _sections => 1 },
|
||||
'qx' => { operator => 'qx', braced => undef, separator => undef, _sections => 1 },
|
||||
'qw' => { operator => 'qw', braced => undef, separator => undef, _sections => 1 },
|
||||
'qr' => { operator => 'qr', braced => undef, separator => undef, _sections => 1, modifiers => 1 },
|
||||
'm' => { operator => 'm', braced => undef, separator => undef, _sections => 1, modifiers => 1 },
|
||||
's' => { operator => 's', braced => undef, separator => undef, _sections => 2, modifiers => 1 },
|
||||
'tr' => { operator => 'tr', braced => undef, separator => undef, _sections => 2, modifiers => 1 },
|
||||
|
||||
# Y is the little-used variant of tr
|
||||
'y' => { operator => 'y', braced => undef, separator => undef, _sections => 2, modifiers => 1 },
|
||||
|
||||
'/' => { operator => undef, braced => 0, separator => '/', _sections => 1, modifiers => 1 },
|
||||
|
||||
# Angle brackets quotes mean "readline(*FILEHANDLE)"
|
||||
'<' => { operator => undef, braced => 1, separator => undef, _sections => 1, },
|
||||
|
||||
# The final ( and kind of depreciated ) "first match only" one is not
|
||||
# used yet, since I'm not sure on the context differences between
|
||||
# this and the trinary operator, but it's here for completeness.
|
||||
'?' => { operator => undef, braced => 0, separator => '?', _sections => 1, modifiers => 1 },
|
||||
);
|
||||
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my $init = defined $_[0]
|
||||
? shift
|
||||
: Carp::croak("::Full->new called without init string");
|
||||
|
||||
# Create the token
|
||||
### This manual SUPER'ing ONLY works because none of
|
||||
### Token::Quote, Token::QuoteLike and Token::Regexp
|
||||
### implement a new function of their own.
|
||||
my $self = PPI::Token::new( $class, $init ) or return undef;
|
||||
|
||||
# Do we have a prototype for the initializer? If so, add the extra fields
|
||||
my $options = $QUOTES{$init} or return $self->_error(
|
||||
"Unknown quote type '$init'"
|
||||
);
|
||||
foreach ( keys %$options ) {
|
||||
$self->{$_} = $options->{$_};
|
||||
}
|
||||
|
||||
# Set up the modifiers hash if needed
|
||||
$self->{modifiers} = {} if $self->{modifiers};
|
||||
|
||||
# Handle the special < base
|
||||
if ( $init eq '<' ) {
|
||||
$self->{sections}->[0] = Clone::clone( $SECTIONS{'<'} );
|
||||
}
|
||||
|
||||
$self;
|
||||
}
|
||||
|
||||
sub _fill {
|
||||
my $class = shift;
|
||||
my $t = shift;
|
||||
my $self = $t->{token}
|
||||
or Carp::croak("::Full->_fill called without current token");
|
||||
|
||||
# Load in the operator stuff if needed
|
||||
if ( $self->{operator} ) {
|
||||
# In an operator based quote-like, handle the gap between the
|
||||
# operator and the opening separator.
|
||||
if ( substr( $t->{line}, $t->{line_cursor}, 1 ) =~ /\s/ ) {
|
||||
# Go past the gap
|
||||
my $gap = $self->_scan_quote_like_operator_gap( $t );
|
||||
return undef unless defined $gap;
|
||||
if ( ref $gap ) {
|
||||
# End of file
|
||||
$self->{content} .= $$gap;
|
||||
return 0;
|
||||
}
|
||||
$self->{content} .= $gap;
|
||||
}
|
||||
|
||||
# The character we are now on is the separator. Capture,
|
||||
# and advance into the first section.
|
||||
my $sep = substr( $t->{line}, $t->{line_cursor}++, 1 );
|
||||
$self->{content} .= $sep;
|
||||
|
||||
# Determine if these are normal or braced type sections
|
||||
if ( my $section = $SECTIONS{$sep} ) {
|
||||
$self->{braced} = 1;
|
||||
$self->{sections}->[0] = Clone::clone($section);
|
||||
} else {
|
||||
$self->{braced} = 0;
|
||||
$self->{separator} = $sep;
|
||||
}
|
||||
}
|
||||
|
||||
# Parse different based on whether we are normal or braced
|
||||
my $rv = $self->{braced}
|
||||
? $self->_fill_braced($t)
|
||||
: $self->_fill_normal($t);
|
||||
return $rv if !$rv;
|
||||
|
||||
# Return now unless it has modifiers ( i.e. s/foo//eieio )
|
||||
return 1 unless $self->{modifiers};
|
||||
|
||||
# Check for modifiers
|
||||
my $char;
|
||||
my $len = 0;
|
||||
while ( ($char = substr( $t->{line}, $t->{line_cursor} + 1, 1 )) =~ /[^\W\d_]/ ) {
|
||||
$len++;
|
||||
$self->{content} .= $char;
|
||||
$self->{modifiers}->{lc $char} = 1;
|
||||
$t->{line_cursor}++;
|
||||
}
|
||||
}
|
||||
|
||||
# Handle the content parsing path for normally separated
|
||||
sub _fill_normal {
|
||||
my $self = shift;
|
||||
my $t = shift;
|
||||
|
||||
# Get the content up to the next separator
|
||||
my $string = $self->_scan_for_unescaped_character( $t, $self->{separator} );
|
||||
return undef unless defined $string;
|
||||
if ( ref $string ) {
|
||||
# End of file
|
||||
if ( length($$string) > 1 ) {
|
||||
# Complete the properties for the first section
|
||||
my $str = $$string;
|
||||
chop $str;
|
||||
$self->{sections}->[0] = {
|
||||
position => length($self->{content}),
|
||||
size => length($$string) - 1,
|
||||
type => "$self->{separator}$self->{separator}",
|
||||
};
|
||||
$self->{_sections} = 1;
|
||||
} else {
|
||||
# No sections at all
|
||||
$self->{sections} = [ ];
|
||||
$self->{_sections} = 0;
|
||||
}
|
||||
$self->{content} .= $$string;
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Complete the properties of the first section
|
||||
$self->{sections}->[0] = {
|
||||
position => length $self->{content},
|
||||
size => length($string) - 1,
|
||||
type => "$self->{separator}$self->{separator}",
|
||||
};
|
||||
$self->{content} .= $string;
|
||||
|
||||
# We are done if there is only one section
|
||||
return 1 if $self->{_sections} == 1;
|
||||
|
||||
# There are two sections.
|
||||
|
||||
# Advance into the next section
|
||||
$t->{line_cursor}++;
|
||||
|
||||
# Get the content up to the end separator
|
||||
$string = $self->_scan_for_unescaped_character( $t, $self->{separator} );
|
||||
return undef unless defined $string;
|
||||
if ( ref $string ) {
|
||||
# End of file
|
||||
if ( length($$string) > 1 ) {
|
||||
# Complete the properties for the second section
|
||||
my $str = $$string;
|
||||
chop $str;
|
||||
$self->{sections}->[1] = {
|
||||
position => length($self->{content}),
|
||||
size => length($$string) - 1,
|
||||
type => "$self->{separator}$self->{separator}",
|
||||
};
|
||||
} else {
|
||||
# No sections at all
|
||||
$self->{_sections} = 1;
|
||||
}
|
||||
$self->{content} .= $$string;
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Complete the properties of the second section
|
||||
$self->{sections}->[1] = {
|
||||
position => length($self->{content}),
|
||||
size => length($string) - 1
|
||||
};
|
||||
$self->{content} .= $string;
|
||||
|
||||
1;
|
||||
}
|
||||
|
||||
# Handle content parsing for matching brace separated
|
||||
sub _fill_braced {
|
||||
my $self = shift;
|
||||
my $t = shift;
|
||||
|
||||
# Get the content up to the close character
|
||||
my $section = $self->{sections}->[0];
|
||||
my $brace_str = $self->_scan_for_brace_character( $t, $section->{_close} );
|
||||
return undef unless defined $brace_str;
|
||||
if ( ref $brace_str ) {
|
||||
# End of file
|
||||
if ( length($$brace_str) > 1 ) {
|
||||
# Complete the properties for the first section
|
||||
my $str = $$brace_str;
|
||||
chop $str;
|
||||
$self->{sections}->[0] = {
|
||||
position => length($self->{content}),
|
||||
size => length($$brace_str) - 1,
|
||||
type => $section->{type},
|
||||
};
|
||||
$self->{_sections} = 1;
|
||||
} else {
|
||||
# No sections at all
|
||||
$self->{sections} = [ ];
|
||||
$self->{_sections} = 0;
|
||||
}
|
||||
$self->{content} .= $$brace_str;
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Complete the properties of the first section
|
||||
$section->{position} = length $self->{content};
|
||||
$section->{size} = length($brace_str) - 1;
|
||||
$self->{content} .= $brace_str;
|
||||
delete $section->{_close};
|
||||
|
||||
# We are done if there is only one section
|
||||
return 1 if $self->{_sections} == 1;
|
||||
|
||||
# There are two sections.
|
||||
|
||||
# Is there a gap between the sections.
|
||||
my $char = substr( $t->{line}, ++$t->{line_cursor}, 1 );
|
||||
if ( $char =~ /\s/ ) {
|
||||
# Go past the gap
|
||||
my $gap_str = $self->_scan_quote_like_operator_gap( $t );
|
||||
return undef unless defined $gap_str;
|
||||
if ( ref $gap_str ) {
|
||||
# End of file
|
||||
$self->{content} .= $$gap_str;
|
||||
return 0;
|
||||
}
|
||||
$self->{content} .= $gap_str;
|
||||
$char = substr( $t->{line}, $t->{line_cursor}, 1 );
|
||||
}
|
||||
|
||||
$section = $SECTIONS{$char};
|
||||
|
||||
if ( $section ) {
|
||||
# It's a brace
|
||||
|
||||
# Initialize the second section
|
||||
$self->{content} .= $char;
|
||||
$section = { %$section };
|
||||
|
||||
# Advance into the second section
|
||||
$t->{line_cursor}++;
|
||||
|
||||
# Get the content up to the close character
|
||||
$brace_str = $self->_scan_for_brace_character( $t, $section->{_close} );
|
||||
return undef unless defined $brace_str;
|
||||
if ( ref $brace_str ) {
|
||||
# End of file
|
||||
if ( length($$brace_str) > 1 ) {
|
||||
# Complete the properties for the second section
|
||||
my $str = $$brace_str;
|
||||
chop $str;
|
||||
$self->{sections}->[1] = {
|
||||
position => length($self->{content}),
|
||||
size => length($$brace_str) - 1,
|
||||
type => $section->{type},
|
||||
};
|
||||
$self->{_sections} = 2;
|
||||
} else {
|
||||
# No sections at all
|
||||
$self->{_sections} = 1;
|
||||
}
|
||||
$self->{content} .= $$brace_str;
|
||||
return 0;
|
||||
} else {
|
||||
# Complete the properties for the second section
|
||||
$self->{sections}->[1] = {
|
||||
position => length($self->{content}),
|
||||
size => length($brace_str) - 1,
|
||||
type => $section->{type},
|
||||
};
|
||||
$self->{content} .= $brace_str;
|
||||
}
|
||||
} elsif ( $char =~ m/ \A [^\w\s] \z /smx ) {
|
||||
# It is some other delimiter (weird, but possible)
|
||||
|
||||
# Add the delimiter to the content.
|
||||
$self->{content} .= $char;
|
||||
|
||||
# Advance into the next section
|
||||
$t->{line_cursor}++;
|
||||
|
||||
# Get the content up to the end separator
|
||||
my $string = $self->_scan_for_unescaped_character( $t, $char );
|
||||
return undef unless defined $string;
|
||||
if ( ref $string ) {
|
||||
# End of file
|
||||
if ( length($$string) > 1 ) {
|
||||
# Complete the properties for the second section
|
||||
my $str = $$string;
|
||||
chop $str;
|
||||
$self->{sections}->[1] = {
|
||||
position => length($self->{content}),
|
||||
size => length($$string) - 1,
|
||||
type => "$char$char",
|
||||
};
|
||||
} else {
|
||||
# Only the one section
|
||||
$self->{_sections} = 1;
|
||||
}
|
||||
$self->{content} .= $$string;
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Complete the properties of the second section
|
||||
$self->{sections}->[1] = {
|
||||
position => length($self->{content}),
|
||||
size => length($string) - 1,
|
||||
type => "$char$char",
|
||||
};
|
||||
$self->{content} .= $string;
|
||||
|
||||
} else {
|
||||
|
||||
# Error, it has to be a delimiter of some sort.
|
||||
# Although this will result in a REALLY illegal regexp,
|
||||
# we allow it anyway.
|
||||
|
||||
# Create a null second section
|
||||
$self->{sections}->[1] = {
|
||||
position => length($self->{content}),
|
||||
size => 0,
|
||||
type => '',
|
||||
};
|
||||
|
||||
# Attach an error to the token and move on
|
||||
$self->{_error} = "No second section of regexp, or does not start with a balanced character";
|
||||
|
||||
# Roll back the cursor one char and return signalling end of regexp
|
||||
$t->{line_cursor}--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Additional methods to find out about the quote
|
||||
|
||||
# In a scalar context, get the number of sections
|
||||
# In an array context, get the section information
|
||||
sub _sections {
|
||||
wantarray ? @{$_[0]->{sections}} : scalar @{$_[0]->{sections}}
|
||||
}
|
||||
|
||||
# Get a section's content
|
||||
sub _section_content {
|
||||
my $self = shift;
|
||||
my $i = shift;
|
||||
$self->{sections} or return;
|
||||
my $section = $self->{sections}->[$i] or return;
|
||||
return substr( $self->content, $section->{position}, $section->{size} );
|
||||
}
|
||||
|
||||
# Get the modifiers if any.
|
||||
# In list context, return the modifier hash.
|
||||
# In scalar context, clone the hash and return a reference to it.
|
||||
# If there are no modifiers, simply return.
|
||||
sub _modifiers {
|
||||
my $self = shift;
|
||||
$self->{modifiers} or return;
|
||||
wantarray and return %{ $self->{modifiers} };
|
||||
return +{ %{ $self->{modifiers} } };
|
||||
}
|
||||
|
||||
# Get the delimiters, or at least give it a good try to get them.
|
||||
sub _delimiters {
|
||||
my $self = shift;
|
||||
$self->{sections} or return;
|
||||
my @delims;
|
||||
foreach my $sect ( @{ $self->{sections} } ) {
|
||||
if ( exists $sect->{type} ) {
|
||||
push @delims, $sect->{type};
|
||||
} else {
|
||||
my $content = $self->content;
|
||||
push @delims,
|
||||
substr( $content, $sect->{position} - 1, 1 ) .
|
||||
substr( $content, $sect->{position} + $sect->{size}, 1 );
|
||||
}
|
||||
}
|
||||
return @delims;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
67
database/perl/vendor/lib/PPI/Token/_QuoteEngine/Simple.pm
vendored
Normal file
67
database/perl/vendor/lib/PPI/Token/_QuoteEngine/Simple.pm
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
package PPI::Token::_QuoteEngine::Simple;
|
||||
|
||||
# Simple quote engine
|
||||
|
||||
use strict;
|
||||
use PPI::Token::_QuoteEngine ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = 'PPI::Token::_QuoteEngine';
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my $separator = shift or return undef;
|
||||
|
||||
# Create a new token containing the separator
|
||||
### This manual SUPER'ing ONLY works because none of
|
||||
### Token::Quote, Token::QuoteLike and Token::Regexp
|
||||
### implement a new function of their own.
|
||||
my $self = PPI::Token::new( $class, $separator ) or return undef;
|
||||
$self->{separator} = $separator;
|
||||
|
||||
$self;
|
||||
}
|
||||
|
||||
sub _fill {
|
||||
my $class = shift;
|
||||
my $t = shift;
|
||||
my $self = $t->{token} or return undef;
|
||||
|
||||
# Scan for the end separator
|
||||
my $string = $self->_scan_for_unescaped_character( $t, $self->{separator} );
|
||||
return undef unless defined $string;
|
||||
if ( ref $string ) {
|
||||
# End of file
|
||||
$self->{content} .= $$string;
|
||||
return 0;
|
||||
} else {
|
||||
# End of string
|
||||
$self->{content} .= $string;
|
||||
return $self;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
1093
database/perl/vendor/lib/PPI/Tokenizer.pm
vendored
Normal file
1093
database/perl/vendor/lib/PPI/Tokenizer.pm
vendored
Normal file
File diff suppressed because it is too large
Load Diff
240
database/perl/vendor/lib/PPI/Transform.pm
vendored
Normal file
240
database/perl/vendor/lib/PPI/Transform.pm
vendored
Normal file
@@ -0,0 +1,240 @@
|
||||
package PPI::Transform;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Transform - Abstract base class for document transformation classes
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<PPI::Transform> provides an API for the creation of classes and objects
|
||||
that modify or transform PPI documents.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Carp ();
|
||||
use List::Util ();
|
||||
use PPI::Document ();
|
||||
use Params::Util qw{_INSTANCE _CLASS _CODE _SCALAR0};
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Apply Handler Registration
|
||||
|
||||
my %HANDLER;
|
||||
my @ORDER;
|
||||
|
||||
# Yes, you can use this yourself.
|
||||
# I'm just leaving it undocumented for now.
|
||||
sub register_apply_handler {
|
||||
my $class = shift;
|
||||
my $handler = _CLASS(shift) or Carp::croak("Invalid PPI::Transform->register_apply_handler param");
|
||||
my $get = _CODE(shift) or Carp::croak("Invalid PPI::Transform->register_apply_handler param");
|
||||
my $set = _CODE(shift) or Carp::croak("Invalid PPI::Transform->register_apply_handler param");
|
||||
if ( $HANDLER{$handler} ) {
|
||||
Carp::croak("PPI::Transform->apply handler '$handler' already exists");
|
||||
}
|
||||
|
||||
# Register the handler
|
||||
$HANDLER{$handler} = [ $get, $set ];
|
||||
unshift @ORDER, $handler;
|
||||
}
|
||||
|
||||
# Register the default handlers
|
||||
__PACKAGE__->register_apply_handler( 'SCALAR', \&_SCALAR_get, \&_SCALAR_set );
|
||||
__PACKAGE__->register_apply_handler( 'PPI::Document', sub { $_[0] }, sub() { 1 } );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Constructor
|
||||
|
||||
=pod
|
||||
|
||||
=head2 new
|
||||
|
||||
my $transform = PPI::Transform->new(
|
||||
param1 => 'value1',
|
||||
param2 => 'value2',
|
||||
);
|
||||
|
||||
The C<new> constructor creates a new object for your C<PPI::Transform>
|
||||
subclass. A default constructor is provided for you which takes no params
|
||||
and creates a basic, empty, object.
|
||||
|
||||
If you wish to have your transform constructor take params, these B<must>
|
||||
be in the form of a list of key/value pairs.
|
||||
|
||||
Returns a new C<PPI::Transform>-compatible object, or returns
|
||||
C<undef> on error.
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
bless { @_ }, $class;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 document
|
||||
|
||||
The C<document> method should be implemented by each subclass, and
|
||||
takes a single argument of a L<PPI::Document> object, modifying it
|
||||
B<in place> as appropriate for the particular transform class.
|
||||
|
||||
That's right, this method B<will not clone> and B<should not clone>
|
||||
the document object. If you do not want the original to be modified,
|
||||
you need to clone it yourself before passing it in.
|
||||
|
||||
Returns the numbers of changes made to the document. If the transform
|
||||
is unable to track the quantity (including the situation where it cannot
|
||||
tell B<IF> it made a change) it should return 1. Returns zero if no
|
||||
changes were made to the document, or C<undef> if an error occurs.
|
||||
|
||||
By default this error is likely to only mean that you passed in something
|
||||
that wasn't a L<PPI::Document>, but may include additional errors
|
||||
depending on the subclass.
|
||||
|
||||
=cut
|
||||
|
||||
sub document {
|
||||
my $class = shift;
|
||||
die "$class does not implement the required ->document method";
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 apply
|
||||
|
||||
The C<apply> method is used to apply the transform to something. The
|
||||
argument must be a L<PPI::Document>, or something which can be turned
|
||||
into one and then be written back to again.
|
||||
|
||||
Currently, this list is limited to a C<SCALAR> reference, although a
|
||||
handler registration process is available for you to add support for
|
||||
additional types of object should you wish (see the source for this module).
|
||||
|
||||
Returns true if the transform was applied, false if there is an error in the
|
||||
transform process, or may die if there is a critical error in the apply
|
||||
handler.
|
||||
|
||||
=cut
|
||||
|
||||
sub apply {
|
||||
my $self = _SELF(shift);
|
||||
my $it = defined $_[0] ? shift : return undef;
|
||||
|
||||
# Try to find an apply handler
|
||||
my $class = _SCALAR0($it) ? 'SCALAR'
|
||||
: List::Util::first { _INSTANCE($it, $_) } @ORDER
|
||||
or return undef;
|
||||
my $handler = $HANDLER{$class}
|
||||
or die("->apply handler for $class missing! Panic");
|
||||
|
||||
# Get, change, set
|
||||
my $Document = _INSTANCE($handler->[0]->($it), 'PPI::Document')
|
||||
or Carp::croak("->apply handler for $class failed to get a PPI::Document");
|
||||
$self->document( $Document ) or return undef;
|
||||
$handler->[1]->($it, $Document)
|
||||
or Carp::croak("->apply handler for $class failed to save the changed document");
|
||||
1;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 file
|
||||
|
||||
# Read from one file and write to another
|
||||
$transform->file( 'Input.pm' => 'Output.pm' );
|
||||
|
||||
# Change a file in place
|
||||
$transform->file( 'Change.pm' );
|
||||
|
||||
The C<file> method modifies a Perl document by filename. If passed a single
|
||||
parameter, it modifies the file in-place. If provided a second parameter,
|
||||
it will attempt to save the modified file to the alternative filename.
|
||||
|
||||
Returns true on success, or C<undef> on error.
|
||||
|
||||
=cut
|
||||
|
||||
sub file {
|
||||
my $self = _SELF(shift);
|
||||
|
||||
# Where do we read from and write to
|
||||
my $input = defined $_[0] ? shift : return undef;
|
||||
my $output = @_ ? defined $_[0] ? "$_[0]" : undef : $input or return undef;
|
||||
|
||||
# Process the file
|
||||
my $Document = PPI::Document->new( "$input" ) or return undef;
|
||||
$self->document( $Document ) or return undef;
|
||||
$Document->save( $output );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Apply Hander Methods
|
||||
|
||||
sub _SCALAR_get {
|
||||
PPI::Document->new( $_[0] );
|
||||
}
|
||||
|
||||
sub _SCALAR_set {
|
||||
my $it = shift;
|
||||
$$it = $_[0]->serialize;
|
||||
1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Support Functions
|
||||
|
||||
sub _SELF {
|
||||
return shift if ref $_[0];
|
||||
my $self = $_[0]->new or Carp::croak(
|
||||
"Failed to auto-instantiate new $_[0] object"
|
||||
);
|
||||
$self;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=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
|
||||
179
database/perl/vendor/lib/PPI/Transform/UpdateCopyright.pm
vendored
Normal file
179
database/perl/vendor/lib/PPI/Transform/UpdateCopyright.pm
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
package PPI::Transform::UpdateCopyright;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PPI::Transform::UpdateCopyright - Demonstration PPI::Transform class
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $transform = PPI::Transform::UpdateCopyright->new(
|
||||
name => 'Adam Kennedy'
|
||||
);
|
||||
|
||||
$transform->file('Module.pm');
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<PPI::Transform::UpdateCopyright> provides a demonstration of a typical
|
||||
L<PPI::Transform> class.
|
||||
|
||||
This class implements a document transform that will take the name of an
|
||||
author and update the copyright statement to refer to the current year,
|
||||
if it does not already do so.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Params::Util qw{_STRING};
|
||||
use PPI::Transform ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Constructor and Accessors
|
||||
|
||||
=pod
|
||||
|
||||
=head2 new
|
||||
|
||||
my $transform = PPI::Transform::UpdateCopyright->new(
|
||||
name => 'Adam Kennedy'
|
||||
);
|
||||
|
||||
The C<new> constructor creates a new transform object for a specific
|
||||
author. It takes a single C<name> parameter that should be the name
|
||||
(or longer string) for the author.
|
||||
|
||||
Specifying the name is required to allow the changing of a subset of
|
||||
copyright statements that refer to you from a larger set in a file.
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my $self = shift->SUPER::new(@_);
|
||||
|
||||
# Must provide a name
|
||||
unless ( defined _STRING($self->name) ) {
|
||||
PPI::Exception->throw("Did not provide a valid name param");
|
||||
}
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=head2 name
|
||||
|
||||
The C<name> accessor returns the author name that the transform will be
|
||||
searching for copyright statements of.
|
||||
|
||||
=cut
|
||||
|
||||
sub name {
|
||||
$_[0]->{name};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Transform
|
||||
|
||||
sub document {
|
||||
my $self = shift;
|
||||
my $document = _INSTANCE(shift, 'PPI::Document') or return undef;
|
||||
|
||||
# Find things to transform
|
||||
my $name = quotemeta $self->name;
|
||||
my $regexp = qr/\bcopyright\b.*$name/m;
|
||||
my $elements = $document->find( sub {
|
||||
$_[1]->isa('PPI::Token::Pod') or return '';
|
||||
$_[1]->content =~ $regexp or return '';
|
||||
return 1;
|
||||
} );
|
||||
return undef unless defined $elements;
|
||||
return 0 unless $elements;
|
||||
|
||||
# Try to transform any elements
|
||||
my $changes = 0;
|
||||
my $change = sub {
|
||||
my $copyright = shift;
|
||||
my $thisyear = (localtime time)[5] + 1900;
|
||||
my @year = $copyright =~ m/(\d{4})/g;
|
||||
|
||||
if ( @year == 1 ) {
|
||||
# Handle the single year format
|
||||
if ( $year[0] == $thisyear ) {
|
||||
# No change
|
||||
return $copyright;
|
||||
} else {
|
||||
# Convert from single year to multiple year
|
||||
$changes++;
|
||||
$copyright =~ s/(\d{4})/$1 - $thisyear/;
|
||||
return $copyright;
|
||||
}
|
||||
}
|
||||
|
||||
if ( @year == 2 ) {
|
||||
# Handle the range format
|
||||
if ( $year[1] == $thisyear ) {
|
||||
# No change
|
||||
return $copyright;
|
||||
} else {
|
||||
# Change the second year to the current one
|
||||
$changes++;
|
||||
$copyright =~ s/$year[1]/$thisyear/;
|
||||
return $copyright;
|
||||
}
|
||||
}
|
||||
|
||||
# huh?
|
||||
die "Invalid or unknown copyright line '$copyright'";
|
||||
};
|
||||
|
||||
# Attempt to transform each element
|
||||
my $pattern = qr/\b(copyright.*\d)({4}(?:\s*-\s*\d{4})?)(.*$name)/mi;
|
||||
foreach my $element ( @$elements ) {
|
||||
$element =~ s/$pattern/$1 . $change->($2) . $2/eg;
|
||||
}
|
||||
|
||||
return $changes;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 TO DO
|
||||
|
||||
- May need to overload some methods to forcefully prevent Document
|
||||
objects becoming children of another Node.
|
||||
|
||||
=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 2009 - 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
|
||||
72
database/perl/vendor/lib/PPI/Util.pm
vendored
Normal file
72
database/perl/vendor/lib/PPI/Util.pm
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
package PPI::Util;
|
||||
|
||||
# Provides some common utility functions that can be imported
|
||||
|
||||
use strict;
|
||||
use Exporter ();
|
||||
use Digest::MD5 ();
|
||||
use Params::Util qw{_INSTANCE _SCALAR0 _ARRAY0};
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
our @ISA = 'Exporter';
|
||||
our @EXPORT_OK = qw{ _Document _slurp };
|
||||
|
||||
# 5.8.7 was the first version to resolve the notorious
|
||||
# "unicode length caching" bug.
|
||||
use constant HAVE_UNICODE => !! ( $] >= 5.008007 );
|
||||
|
||||
# Common reusable true and false functions
|
||||
# This makes it easy to upgrade many places in PPI::XS
|
||||
sub TRUE () { 1 }
|
||||
sub FALSE () { '' }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
# Functions
|
||||
|
||||
# Allows a sub that takes a L<PPI::Document> to handle the full range
|
||||
# of different things, including file names, SCALAR source, etc.
|
||||
sub _Document {
|
||||
shift if @_ > 1;
|
||||
return undef unless defined $_[0];
|
||||
require PPI::Document;
|
||||
return PPI::Document->new(shift) unless ref $_[0];
|
||||
return PPI::Document->new(shift) if _SCALAR0($_[0]);
|
||||
return PPI::Document->new(shift) if _ARRAY0($_[0]);
|
||||
return shift if _INSTANCE($_[0], 'PPI::Document');
|
||||
return undef;
|
||||
}
|
||||
|
||||
# Provide a simple _slurp implementation
|
||||
sub _slurp {
|
||||
my $file = shift;
|
||||
local $/ = undef;
|
||||
local *FILE;
|
||||
open( FILE, '<', $file ) or return "open($file) failed: $!";
|
||||
my $source = <FILE>;
|
||||
close( FILE ) or return "close($file) failed: $!";
|
||||
return \$source;
|
||||
}
|
||||
|
||||
# Provides a version of Digest::MD5's md5hex that explicitly
|
||||
# works on the unix-newlined version of the content.
|
||||
sub md5hex {
|
||||
my $string = shift;
|
||||
$string =~ s/(?:\015{1,2}\012|\015|\012)/\015/gs;
|
||||
Digest::MD5::md5_hex($string);
|
||||
}
|
||||
|
||||
# As above but slurps and calculates the id for a file by name
|
||||
sub md5hex_file {
|
||||
my $file = shift;
|
||||
my $content = _slurp($file);
|
||||
return undef unless ref $content;
|
||||
$$content =~ s/(?:\015{1,2}\012|\015|\012)/\n/gs;
|
||||
md5hex($$content);
|
||||
}
|
||||
|
||||
1;
|
||||
165
database/perl/vendor/lib/PPI/XSAccessor.pm
vendored
Normal file
165
database/perl/vendor/lib/PPI/XSAccessor.pm
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
package PPI::XSAccessor;
|
||||
|
||||
# This is an experimental prototype, use at your own risk.
|
||||
# Provides optional enhancement of PPI with Class::XSAccessor (if installed)
|
||||
|
||||
use 5.006;
|
||||
use strict;
|
||||
use PPI ();
|
||||
|
||||
our $VERSION = '1.270'; # VERSION
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
######################################################################
|
||||
# Replacement Methods
|
||||
|
||||
# Packages are implemented here in alphabetical order
|
||||
|
||||
package #hide from indexer
|
||||
PPI::Document;
|
||||
|
||||
use Class::XSAccessor
|
||||
replace => 1,
|
||||
getters => {
|
||||
readonly => 'readonly',
|
||||
},
|
||||
true => [
|
||||
'scope'
|
||||
];
|
||||
|
||||
package #hide from indexer
|
||||
PPI::Document::File;
|
||||
|
||||
use Class::XSAccessor
|
||||
replace => 1,
|
||||
getters => {
|
||||
filename => 'filename',
|
||||
};
|
||||
|
||||
package #hide from indexer
|
||||
PPI::Document::Fragment;
|
||||
|
||||
use Class::XSAccessor
|
||||
replace => 1,
|
||||
false => [
|
||||
'scope',
|
||||
];
|
||||
|
||||
package #hide from indexer
|
||||
PPI::Document::Normalized;
|
||||
|
||||
use Class::XSAccessor
|
||||
replace => 1,
|
||||
getters => {
|
||||
'_Document' => 'Document',
|
||||
'version' => 'version',
|
||||
'functions' => 'functions',
|
||||
};
|
||||
|
||||
package #hide from indexer
|
||||
PPI::Element;
|
||||
|
||||
use Class::XSAccessor
|
||||
replace => 1,
|
||||
true => [
|
||||
'significant',
|
||||
];
|
||||
|
||||
package #hide from indexer
|
||||
PPI::Exception;
|
||||
|
||||
use Class::XSAccessor
|
||||
replace => 1,
|
||||
getters => {
|
||||
message => 'message',
|
||||
};
|
||||
|
||||
package #hide from indexer
|
||||
PPI::Node;
|
||||
|
||||
use Class::XSAccessor
|
||||
replace => 1,
|
||||
false => [
|
||||
'scope',
|
||||
];
|
||||
|
||||
package #hide from indexer
|
||||
PPI::Normal;
|
||||
|
||||
use Class::XSAccessor
|
||||
replace => 1,
|
||||
getters => {
|
||||
'layer' => 'layer',
|
||||
};
|
||||
|
||||
package #hide from indexer
|
||||
PPI::Statement;
|
||||
|
||||
use Class::XSAccessor
|
||||
replace => 1,
|
||||
true => [
|
||||
'__LEXER__normal',
|
||||
];
|
||||
|
||||
package #hide from indexer
|
||||
PPI::Statement::Compound;
|
||||
|
||||
use Class::XSAccessor
|
||||
replace => 1,
|
||||
true => [
|
||||
'scope',
|
||||
],
|
||||
false => [
|
||||
'__LEXER__normal',
|
||||
];
|
||||
|
||||
package #hide from indexer
|
||||
PPI::Statement::Data;
|
||||
|
||||
use Class::XSAccessor
|
||||
replace => 1,
|
||||
false => [
|
||||
'_complete',
|
||||
];
|
||||
|
||||
package #hide from indexer
|
||||
PPI::Statement::End;
|
||||
|
||||
use Class::XSAccessor
|
||||
replace => 1,
|
||||
true => [
|
||||
'_complete',
|
||||
];
|
||||
|
||||
package #hide from indexer
|
||||
PPI::Statement::Given;
|
||||
|
||||
use Class::XSAccessor
|
||||
replace => 1,
|
||||
true => [
|
||||
'scope',
|
||||
],
|
||||
false => [
|
||||
'__LEXER__normal',
|
||||
];
|
||||
|
||||
package #hide from indexer
|
||||
PPI::Token;
|
||||
|
||||
use Class::XSAccessor
|
||||
replace => 1,
|
||||
getters => {
|
||||
content => 'content',
|
||||
},
|
||||
setters => {
|
||||
set_content => 'content',
|
||||
},
|
||||
true => [
|
||||
'__TOKENIZER__on_line_start',
|
||||
'__TOKENIZER__on_line_end',
|
||||
];
|
||||
|
||||
1;
|
||||
Reference in New Issue
Block a user