Add built local::lib
[catagits/Gitalist.git] / local-lib5 / lib / perl5 / PPI / Token / Unknown.pm
1 package PPI::Token::Unknown;
2
3 =pod
4
5 =head1 NAME
6
7 PPI::Token::Unknown - Token of unknown or as-yet undetermined type
8
9 =head1 INHERITANCE
10
11   PPI::Token::Unknown
12   isa PPI::Token
13       isa PPI::Element
14
15 =head1 DESCRIPTION
16
17 Object of the type C<PPI::Token::Unknown> exist primarily inside the
18 tokenizer, where they are temporarily brought into existing for a very
19 short time to represent a token that could be one of a number of types.
20
21 Generally, they only exist for a character or two, after which they are
22 resolved and converted into the correct type. For an object of this type
23 to survive the parsing process is considered a major bug.
24
25 Please report any C<PPI::Token::Unknown> you encounter in a L<PPI::Document>
26 object as a bug.
27
28 =cut
29
30 use strict;
31 use PPI::Token     ();
32 use PPI::Exception ();
33
34 use vars qw{$VERSION @ISA};
35 BEGIN {
36         $VERSION = '1.206';
37         @ISA     = 'PPI::Token';
38 }
39
40
41
42
43
44 #####################################################################
45 # Tokenizer Methods
46
47 sub __TOKENIZER__on_char {
48         my $t    = $_[1];                                      # Tokenizer object
49         my $c    = $t->{token}->{content};                     # Current token
50         my $char = substr( $t->{line}, $t->{line_cursor}, 1 ); # Current character
51
52         # Now, we split on the different values of the current content
53         if ( $c eq '*' ) {
54                 if ( $char =~ /(?:(?!\d)\w|\:)/ ) {
55                         # Symbol (unless the thing before it is a number
56                         my $tokens = $t->_previous_significant_tokens(1);
57                         my $p0     = $tokens->[0];
58                         if ( $p0 and ! $p0->isa('PPI::Token::Number') ) {
59                                 $t->{class} = $t->{token}->set_class( 'Symbol' );
60                                 return 1;
61                         }
62                 }
63
64                 if ( $char eq '{' ) {
65                         # Obvious GLOB cast
66                         $t->{class} = $t->{token}->set_class( 'Cast' );
67                         return $t->_finalize_token->__TOKENIZER__on_char( $t );
68                 }
69
70                 if ( $char eq '$' ) {
71                         # Operator/operand-sensitive, multiple or GLOB cast
72                         my $_class = undef;
73                         my $tokens = $t->_previous_significant_tokens(1);
74                         my $p0     = $tokens->[0];
75                         if ( $p0 ) {
76                                 # Is it a token or a number
77                                 if ( $p0->isa('PPI::Token::Symbol') ) {
78                                         $_class = 'Operator';
79                                 } elsif ( $p0->isa('PPI::Token::Number') ) {
80                                         $_class = 'Operator';
81                                 } elsif (
82                                         $p0->isa('PPI::Token::Structure')
83                                         and
84                                         $p0->content =~ /^(?:\)|\])$/
85                                 ) {
86                                         $_class = 'Operator';
87                                 } else {
88                                         ### This is pretty weak, there's
89                                         ### room for a dozen more tests
90                                         ### before going with a default.
91                                         ### Or even better, a proper
92                                         ### operator/operand method :(
93                                         $_class = 'Cast';
94                                 }
95                         } else {
96                                 # Nothing before it, must be glob cast
97                                 $_class = 'Cast';
98                         }
99
100                         # Set class and rerun
101                         $t->{class} = $t->{token}->set_class( $_class );
102                         return $t->_finalize_token->__TOKENIZER__on_char( $t );
103                 }
104
105                 if ( $char eq '*' || $char eq '=' ) {
106                         # Power operator '**' or mult-assign '*='
107                         $t->{class} = $t->{token}->set_class( 'Operator' );
108                         return 1;
109                 }
110
111                 $t->{class} = $t->{token}->set_class( 'Operator' );
112                 return $t->_finalize_token->__TOKENIZER__on_char( $t );
113
114
115
116         } elsif ( $c eq '$' ) {
117                 if ( $char =~ /[a-z_]/i ) {
118                         # Symbol
119                         $t->{class} = $t->{token}->set_class( 'Symbol' );
120                         return 1;
121                 }
122
123                 if ( $PPI::Token::Magic::magic{ $c . $char } ) {
124                         # Magic variable
125                         $t->{class} = $t->{token}->set_class( 'Magic' );
126                         return 1;
127                 }
128
129                 # Must be a cast
130                 $t->{class} = $t->{token}->set_class( 'Cast' );
131                 return $t->_finalize_token->__TOKENIZER__on_char( $t );
132
133
134
135         } elsif ( $c eq '@' ) {
136                 if ( $char =~ /[\w:]/ ) {
137                         # Symbol
138                         $t->{class} = $t->{token}->set_class( 'Symbol' );
139                         return 1;
140                 }
141
142                 if ( $char =~ /[\-\+\*]/ ) {
143                         # Magic variable
144                         $t->{class} = $t->{token}->set_class( 'Magic' );
145                         return 1;
146                 }
147
148                 # Must be a cast
149                 $t->{class} = $t->{token}->set_class( 'Cast' );
150                 return $t->_finalize_token->__TOKENIZER__on_char( $t );
151
152
153
154         } elsif ( $c eq '%' ) {
155                 # Is it a number?
156                 if ( $char =~ /\d/ ) {
157                         # This is %2 (modulus number)
158                         $t->{class} = $t->{token}->set_class( 'Operator' );
159                         return $t->_finalize_token->__TOKENIZER__on_char( $t );
160                 }
161
162                 # Is it a magic variable?
163                 if ( $char =~ /[!^]/ ) {
164                         $t->{class} = $t->{token}->set_class( 'Magic' );
165                         return 1;
166                 }
167
168                 # Is it a symbol?
169                 if ( $char =~ /[\w:]/ ) {
170                         $t->{class} = $t->{token}->set_class( 'Symbol' );
171                         return 1;
172                 }
173
174                 if ( $char =~ /[\$@%*{]/ ) {
175                         # It's a cast
176                         $t->{class} = $t->{token}->set_class( 'Cast' );
177                         return $t->_finalize_token->__TOKENIZER__on_char( $t );
178
179                 }
180
181                 # Probably the mod operator
182                 $t->{class} = $t->{token}->set_class( 'Operator' );
183                 return $t->{class}->__TOKENIZER__on_char( $t );
184
185
186
187         } elsif ( $c eq '&' ) {
188                 # Is it a number?
189                 if ( $char =~ /\d/ ) {
190                         # This is &2 (bitwise-and number)
191                         $t->{class} = $t->{token}->set_class( 'Operator' );
192                         return $t->_finalize_token->__TOKENIZER__on_char( $t );
193                 }
194
195                 # Is it a symbol
196                 if ( $char =~ /[\w:]/ ) {
197                         $t->{class} = $t->{token}->set_class( 'Symbol' );
198                         return 1;
199                 }
200
201                 if ( $char =~ /[\$@%{]/ ) {
202                         # The ampersand is a cast
203                         $t->{class} = $t->{token}->set_class( 'Cast' );
204                         return $t->_finalize_token->__TOKENIZER__on_char( $t );
205                 }
206
207                 # Probably the binary and operator
208                 $t->{class} = $t->{token}->set_class( 'Operator' );
209                 return $t->{class}->__TOKENIZER__on_char( $t );
210
211
212
213         } elsif ( $c eq '-' ) {
214                 if ( $char =~ /\d/o ) {
215                         # Number
216                         $t->{class} = $t->{token}->set_class( 'Number' );
217                         return 1;
218                 }
219
220                 if ( $char eq '.' ) {
221                         # Number::Float
222                         $t->{class} = $t->{token}->set_class( 'Number::Float' );
223                         return 1;
224                 }
225
226                 if ( $char =~ /[a-zA-Z]/ ) {
227                         $t->{class} = $t->{token}->set_class( 'DashedWord' );
228                         return 1;
229                 }
230
231                 # The numeric negative operator
232                 $t->{class} = $t->{token}->set_class( 'Operator' );
233                 return $t->{class}->__TOKENIZER__on_char( $t );
234
235
236
237         } elsif ( $c eq ':' ) {
238                 if ( $char eq ':' ) {
239                         # ::foo style bareword
240                         $t->{class} = $t->{token}->set_class( 'Word' );
241                         return 1;
242                 }
243
244                 # Now, : acts very very differently in different contexts.
245                 # Mainly, we need to find out if this is a subroutine attribute.
246                 # We'll leave a hint in the token to indicate that, if it is.
247                 if ( $_[0]->__TOKENIZER__is_an_attribute( $t ) ) {
248                         # This : is an attribute indicator
249                         $t->{class} = $t->{token}->set_class( 'Operator' );
250                         $t->{token}->{_attribute} = 1;
251                         return $t->_finalize_token->__TOKENIZER__on_char( $t );
252                 }
253
254                 # It MIGHT be a label, but its probably the ?: trinary operator
255                 $t->{class} = $t->{token}->set_class( 'Operator' );
256                 return $t->{class}->__TOKENIZER__on_char( $t );
257         }
258
259         # erm...
260         PPI::Exception->throw('Unknown value in PPI::Token::Unknown token');
261 }
262
263 # Are we at a location where a ':' would indicate a subroutine attribute
264 sub __TOKENIZER__is_an_attribute {
265         my $t      = $_[1]; # Tokenizer object
266         my $tokens = $t->_previous_significant_tokens(3);
267         my $p0     = $tokens->[0];
268
269         # If we just had another attribute, we are also an attribute
270         return 1 if $p0->isa('PPI::Token::Attribute');
271
272         # If we just had a prototype, then we are an attribute
273         return 1 if $p0->isa('PPI::Token::Prototype');
274
275         # Other than that, we would need to have had a bareword
276         return '' unless $p0->isa('PPI::Token::Word');
277
278         # We could be an anonymous subroutine
279         if ( $p0->isa('PPI::Token::Word') and $p0->content eq 'sub' ) {
280                 return 1;
281         }
282
283         # Or, we could be a named subroutine
284         my $p1 = $tokens->[1];
285         my $p2 = $tokens->[2];
286         if (
287                 $p1->isa('PPI::Token::Word')
288                 and
289                 $p1->content eq 'sub'
290                 and (
291                         $p2->isa('PPI::Token::Structure')
292                         or (
293                                 $p2->isa('PPI::Token::Whitespace')
294                                 and
295                                 $p2->content eq ''
296                         )
297                 )
298         ) {
299                 return 1;
300         }
301
302         # We arn't an attribute
303         '';     
304 }
305
306 1;
307
308 =pod
309
310 =head1 SUPPORT
311
312 See the L<support section|PPI/SUPPORT> in the main module.
313
314 =head1 AUTHOR
315
316 Adam Kennedy E<lt>adamk@cpan.orgE<gt>
317
318 =head1 COPYRIGHT
319
320 Copyright 2001 - 2009 Adam Kennedy.
321
322 This program is free software; you can redistribute
323 it and/or modify it under the same terms as Perl itself.
324
325 The full text of the license can be found in the
326 LICENSE file included with this module.
327
328 =cut