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 67     67   466 use strict;
  67         140  
  67         2629  
34 67     67   360 use PPI::Token::Number ();
  67         130  
  67         58766  
35              
36             our $VERSION = '1.28401'; # TRIAL
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 15 my $self = shift;
60 8         20 my $content = $self->{content};
61 8         27 $content =~ s/^v//;
62 8         32 return join '', map { chr $_ } ( split /\./, $content );
  26         127  
63             }
64              
65              
66              
67              
68              
69             #####################################################################
70             # Tokenizer Methods
71              
72             sub __TOKENIZER__on_char {
73 3100     3100   4962 my $class = shift;
74 3100         4315 my $t = shift;
75 3100         6788 my $char = substr( $t->{line}, $t->{line_cursor}, 1 );
76              
77             # Allow digits
78 3100 100       12106 return 1 if $char =~ /\d/o;
79              
80 1340 100       4465 if( $char eq '_' ) {
81 191 100       1191 return 1 if $t->{token}{content} !~ /\.$/;
82              
83 8         33 chop $t->{token}->{content};
84             $t->{class} = $t->{token}->set_class( 'Number::Float' )
85 8 50       76 if $t->{token}{content} !~ /\..+\./;
86 8         60 $t->_new_token('Operator', '.');
87 8         31 $t->_new_token('Word', '_');
88 8         24 return 0;
89             }
90              
91             # Is this a second decimal point in a row? Then the '..' operator
92 1149 100       3719 if ( $char eq '.' ) {
93 8 100       36 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         6 chop $t->{token}->{content};
98             $t->{class} = $t->{token}->set_class( 'Number::Float' )
99 2 50       24 if $t->{token}{content} !~ /\..+\./;
100 2         24 $t->_new_token('Operator', '..');
101 2         21 return 0;
102             } else {
103 6         20 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 1141         4639 $t->_finalize_token->__TOKENIZER__on_char( $t );
110             }
111              
112             sub __TOKENIZER__commit {
113 3060     3060   6459 my $t = $_[1];
114              
115             # Capture the rest of the token
116 3060         12365 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 3060 100       30942 if $t->{line} !~ m/\G(v\d[_\d]*(?:\.\d[_\d]*)+|v\d[_\d]*\b)/gc;
120              
121 2553         8732 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     14259 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         6186 $t->{line_cursor} += length $content;
130 2539         10579 $t->_new_token( 'Number::Version', $content );
131 2539         6301 $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