File Coverage

blib/lib/PPI/Token/Number/Version.pm
Criterion Covered Total %
statement 38 38 100.0
branch 16 18 88.8
condition 3 3 100.0
subroutine 5 5 100.0
pod 1 1 100.0
total 63 65 96.9


line stmt bran cond sub pod time code
1             package PPI::Token::Number::Version;
2              
3             =pod
4              
5             =head1 NAME
6              
7             PPI::Token::Number::Version - Token class for a byte-packed number
8              
9             =head1 SYNOPSIS
10              
11             $n = 1.1.0;
12             $n = 127.0.0.1;
13             $n = 10_000.10_000.10_000;
14             $n = v1.2.3.4
15              
16             =head1 INHERITANCE
17              
18             PPI::Token::Number::Version
19             isa PPI::Token::Number
20             isa PPI::Token
21             isa PPI::Element
22              
23             =head1 DESCRIPTION
24              
25             The C class is used for tokens that have
26             multiple decimal points. In truth, these aren't treated like numbers
27             at all by Perl, but they look like numbers to a parser.
28              
29             =head1 METHODS
30              
31             =cut
32              
33 65     65   466 use strict;
  65         121  
  65         1926  
34 65     65   411 use PPI::Token::Number ();
  65         159  
  65         42806  
35              
36             our $VERSION = '1.277';
37              
38             our @ISA = "PPI::Token::Number";
39              
40             =pod
41              
42             =head2 base
43              
44             Returns the base for the number: 256.
45              
46             =cut
47              
48             sub base() { 256 }
49              
50             =pod
51              
52             =head2 literal
53              
54             Return the numeric value of this token.
55              
56             =cut
57              
58             sub literal {
59 8     8 1 16 my $self = shift;
60 8         17 my $content = $self->{content};
61 8         28 $content =~ s/^v//;
62 8         27 return join '', map { chr $_ } ( split /\./, $content );
  26         114  
63             }
64              
65              
66              
67              
68              
69             #####################################################################
70             # Tokenizer Methods
71              
72             sub __TOKENIZER__on_char {
73 3099     3099   4935 my $class = shift;
74 3099         4559 my $t = shift;
75 3099         6069 my $char = substr( $t->{line}, $t->{line_cursor}, 1 );
76              
77             # Allow digits
78 3099 100       10365 return 1 if $char =~ /\d/o;
79              
80 1339 100       3650 if( $char eq '_' ) {
81 191 100       780 return 1 if $t->{token}{content} !~ /\.$/;
82              
83 8         46 chop $t->{token}->{content};
84             $t->{class} = $t->{token}->set_class( 'Number::Float' )
85 8 50       119 if $t->{token}{content} !~ /\..+\./;
86 8         57 $t->_new_token('Operator', '.');
87 8         53 $t->_new_token('Word', '_');
88 8         26 return 0;
89             }
90              
91             # Is this a second decimal point in a row? Then the '..' operator
92 1148 100       2536 if ( $char eq '.' ) {
93 8 100       28 if ( $t->{token}->{content} =~ /\.$/ ) {
94             # We have a .., which is an operator.
95             # Take the . off the end of the token..
96             # and finish it, then make the .. operator.
97 2         7 chop $t->{token}->{content};
98             $t->{class} = $t->{token}->set_class( 'Number::Float' )
99 2 50       22 if $t->{token}{content} !~ /\..+\./;
100 2         16 $t->_new_token('Operator', '..');
101 2         6 return 0;
102             } else {
103 6         16 return 1;
104             }
105             }
106              
107             # Doesn't fit a special case, or is after the end of the token
108             # End of token.
109 1140         2685 $t->_finalize_token->__TOKENIZER__on_char( $t );
110             }
111              
112             sub __TOKENIZER__commit {
113 3051     3051   5121 my $t = $_[1];
114              
115             # Capture the rest of the token
116 3051         8375 pos $t->{line} = $t->{line_cursor};
117             # This was not a v-string after all (it's a word);
118             return PPI::Token::Word->__TOKENIZER__commit($t)
119 3051 100       20944 if $t->{line} !~ m/\G(v\d[_\d]*(?:\.\d[_\d]*)+|v\d[_\d]*\b)/gc;
120              
121 2553         7268 my $content = $1;
122              
123             # If there are no periods this could be a word starting with v\d
124             # Forced to be a word. Done.
125 2553 100 100     9850 return PPI::Token::Word->__TOKENIZER__commit($t)
126             if $content !~ /\./ and $t->__current_token_is_forced_word($content);
127              
128             # This is a v-string
129 2539         4685 $t->{line_cursor} += length $content;
130 2539         7446 $t->_new_token( 'Number::Version', $content );
131 2539         5485 $t->_finalize_token->__TOKENIZER__on_char($t);
132             }
133              
134             1;
135              
136             =pod
137              
138             =head1 BUGS
139              
140             - Does not handle leading minus sign correctly. Should translate to a DashedWord.
141             See L
142              
143             -95.0.1.0 --> "-_\000\cA\000"
144             -96.0.1.0 --> Argument "`\0^A\0" isn't numeric in negation (-)
145              
146             =head1 SUPPORT
147              
148             See the L in the main module.
149              
150             =head1 AUTHOR
151              
152             Chris Dolan Ecdolan@cpan.orgE
153              
154             =head1 COPYRIGHT
155              
156             Copyright 2006 Chris Dolan.
157              
158             This program is free software; you can redistribute
159             it and/or modify it under the same terms as Perl itself.
160              
161             The full text of the license can be found in the
162             LICENSE file included with this module.
163              
164             =cut