1package PPI::Token; 2 3=pod 4 5=head1 NAME 6 7PPI::Token - A single token of Perl source code 8 9=head1 INHERITANCE 10 11 PPI::Token 12 isa PPI::Element 13 14=head1 DESCRIPTION 15 16C<PPI::Token> is the abstract base class for all Tokens. In PPI terms, a "Token" is 17a L<PPI::Element> that directly represents bytes of source code. 18 19=head1 METHODS 20 21=cut 22 23use strict; 24use Params::Util qw{_INSTANCE}; 25use PPI::Element (); 26use PPI::Exception (); 27 28our $VERSION = '1.270'; # VERSION 29 30our @ISA = 'PPI::Element'; 31 32# We don't load the abstracts, they are loaded 33# as part of the inheritance process. 34 35# Load the token classes 36use PPI::Token::BOM (); 37use PPI::Token::Whitespace (); 38use PPI::Token::Comment (); 39use PPI::Token::Pod (); 40use PPI::Token::Number (); 41use PPI::Token::Number::Binary (); 42use PPI::Token::Number::Octal (); 43use PPI::Token::Number::Hex (); 44use PPI::Token::Number::Float (); 45use PPI::Token::Number::Exp (); 46use PPI::Token::Number::Version (); 47use PPI::Token::Word (); 48use PPI::Token::DashedWord (); 49use PPI::Token::Symbol (); 50use PPI::Token::ArrayIndex (); 51use PPI::Token::Magic (); 52use PPI::Token::Quote::Single (); 53use PPI::Token::Quote::Double (); 54use PPI::Token::Quote::Literal (); 55use PPI::Token::Quote::Interpolate (); 56use PPI::Token::QuoteLike::Backtick (); 57use PPI::Token::QuoteLike::Command (); 58use PPI::Token::QuoteLike::Regexp (); 59use PPI::Token::QuoteLike::Words (); 60use PPI::Token::QuoteLike::Readline (); 61use PPI::Token::Regexp::Match (); 62use PPI::Token::Regexp::Substitute (); 63use PPI::Token::Regexp::Transliterate (); 64use PPI::Token::Operator (); 65use PPI::Token::Cast (); 66use PPI::Token::Structure (); 67use PPI::Token::Label (); 68use PPI::Token::HereDoc (); 69use PPI::Token::Separator (); 70use PPI::Token::Data (); 71use PPI::Token::End (); 72use PPI::Token::Prototype (); 73use PPI::Token::Attribute (); 74use PPI::Token::Unknown (); 75 76 77 78 79 80##################################################################### 81# Constructor and Related 82 83sub new { 84 bless { content => (defined $_[1] ? "$_[1]" : '') }, $_[0]; 85} 86 87sub set_class { 88 my $self = shift; 89 # @_ or throw Exception("No arguments to set_class"); 90 my $class = substr( $_[0], 0, 12 ) eq 'PPI::Token::' ? shift : 'PPI::Token::' . shift; 91 92 # Find out if the current and new classes are complex 93 my $old_quote = (ref($self) =~ /\b(?:Quote|Regex)\b/o) ? 1 : 0; 94 my $new_quote = ($class =~ /\b(?:Quote|Regex)\b/o) ? 1 : 0; 95 96 # No matter what happens, we will have to rebless 97 bless $self, $class; 98 99 # If we are changing to or from a Quote style token, we 100 # can't just rebless and need to do some extra thing 101 # Otherwise, we have done enough 102 return $class if ($old_quote - $new_quote) == 0; 103 104 # Make a new token from the old content, and overwrite the current 105 # token's attributes with the new token's attributes. 106 my $token = $class->new( $self->{content} ); 107 %$self = %$token; 108 109 # Return the class as a convenience 110 return $class; 111} 112 113 114 115 116 117##################################################################### 118# PPI::Token Methods 119 120=pod 121 122=head2 set_content $string 123 124The C<set_content> method allows you to set/change the string that the 125C<PPI::Token> object represents. 126 127Returns the string you set the Token to 128 129=cut 130 131sub set_content { 132 $_[0]->{content} = $_[1]; 133} 134 135=pod 136 137=head2 add_content $string 138 139The C<add_content> method allows you to add additional bytes of code 140to the end of the Token. 141 142Returns the new full string after the bytes have been added. 143 144=cut 145 146sub add_content { $_[0]->{content} .= $_[1] } 147 148=pod 149 150=head2 length 151 152The C<length> method returns the length of the string in a Token. 153 154=cut 155 156sub length { CORE::length($_[0]->{content}) } 157 158 159 160 161 162##################################################################### 163# Overloaded PPI::Element methods 164 165sub content { 166 $_[0]->{content}; 167} 168 169# You can insert either a statement, or a non-significant token. 170sub insert_before { 171 my $self = shift; 172 my $Element = _INSTANCE(shift, 'PPI::Element') or return undef; 173 if ( $Element->isa('PPI::Structure') ) { 174 return $self->__insert_before($Element); 175 } elsif ( $Element->isa('PPI::Token') ) { 176 return $self->__insert_before($Element); 177 } 178 ''; 179} 180 181# As above, you can insert a statement, or a non-significant token 182sub insert_after { 183 my $self = shift; 184 my $Element = _INSTANCE(shift, 'PPI::Element') or return undef; 185 if ( $Element->isa('PPI::Structure') ) { 186 return $self->__insert_after($Element); 187 } elsif ( $Element->isa('PPI::Token') ) { 188 return $self->__insert_after($Element); 189 } 190 ''; 191} 192 193 194 195 196 197##################################################################### 198# Tokenizer Methods 199 200sub __TOKENIZER__on_line_start() { 1 } 201sub __TOKENIZER__on_line_end() { 1 } 202sub __TOKENIZER__on_char() { 'Unknown' } 203 204 205 206 207 208##################################################################### 209# Lexer Methods 210 211sub __LEXER__opens { 212 ref($_[0]) eq 'PPI::Token::Structure' 213 and 214 $_[0]->{content} =~ /(?:\(|\[|\{)/ 215} 216 217sub __LEXER__closes { 218 ref($_[0]) eq 'PPI::Token::Structure' 219 and 220 $_[0]->{content} =~ /(?:\)|\]|\})/ 221} 222 2231; 224 225=pod 226 227=head1 SUPPORT 228 229See the L<support section|PPI/SUPPORT> in the main module. 230 231=head1 AUTHOR 232 233Adam Kennedy E<lt>adamk@cpan.orgE<gt> 234 235=head1 COPYRIGHT 236 237Copyright 2001 - 2011 Adam Kennedy. 238 239This program is free software; you can redistribute 240it and/or modify it under the same terms as Perl itself. 241 242The full text of the license can be found in the 243LICENSE file included with this module. 244 245=cut 246