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