File Coverage

blib/lib/PPI/Token/Number/Exp.pm
Criterion Covered Total %
statement 34 41 82.9
branch 16 20 80.0
condition 2 3 66.6
subroutine 4 4 100.0
pod 1 1 100.0
total 57 69 82.6


line stmt bran cond sub pod time code
1             package PPI::Token::Number::Exp;
2              
3             =pod
4              
5             =head1 NAME
6              
7             PPI::Token::Number::Exp - Token class for an exponential notation number
8              
9             =head1 SYNOPSIS
10              
11             $n = 1.0e-2;
12             $n = 1e+2;
13              
14             =head1 INHERITANCE
15              
16             PPI::Token::Number::Exp
17             isa PPI::Token::Number::Float
18             isa PPI::Token::Number
19             isa PPI::Token
20             isa PPI::Element
21              
22             =head1 DESCRIPTION
23              
24             The C class is used for tokens that
25             represent floating point numbers with exponential notation.
26              
27             =head1 METHODS
28              
29             =cut
30              
31 65     65   415 use strict;
  65         120  
  65         1478  
32 65     65   286 use PPI::Token::Number::Float ();
  65         102  
  65         26627  
33              
34             our $VERSION = '1.276';
35              
36             our @ISA = "PPI::Token::Number::Float";
37              
38             =pod
39              
40             =head2 literal
41              
42             Return the numeric value of this token.
43              
44             =cut
45              
46             sub literal {
47 13     13 1 183 my $self = shift;
48 13 50       30 return if $self->{_error};
49 13         33 my ($mantissa, $exponent) = split m/e/i, $self->_literal;
50 13         35 my $neg = $mantissa =~ s/^\-//;
51 13         18 $mantissa =~ s/^\./0./;
52 13         16 $exponent =~ s/^\+//;
53              
54             # Must cast exponent as numeric type, due to string type '00' exponent
55             # creating false positive condition in for() loop below, causing infinite loop
56 13         23 $exponent += 0;
57              
58             # This algorithm is reasonably close to the S_mulexp10()
59             # algorithm from the Perl source code, so it should arrive
60             # at the same answer as Perl most of the time.
61 13         28 my $negpow = 0;
62 13 100       23 if ($exponent < 0) {
63 2         4 $negpow = 1;
64 2         5 $exponent *= -1;
65             }
66              
67 13         13 my $result = 1;
68 13         18 my $power = 10;
69 13         22 for (my $bit = 1; $exponent; $bit = $bit << 1) {
70 22 100       34 if ($exponent & $bit) {
71 12         14 $exponent = $exponent ^ $bit;
72 12         14 $result *= $power;
73             }
74 22         36 $power *= $power;
75             }
76              
77 13 100       23 my $val = $neg ? 0 - $mantissa : $mantissa;
78 13 100       40 return $negpow ? $val / $result : $val * $result;
79             }
80              
81              
82              
83              
84              
85             #####################################################################
86             # Tokenizer Methods
87              
88             sub __TOKENIZER__on_char {
89 95     95   116 my $class = shift;
90 95         101 my $t = shift;
91 95         134 my $char = substr( $t->{line}, $t->{line_cursor}, 1 );
92              
93             # To get here, the token must have already encountered an 'E'
94              
95             # Allow underscores straight through
96 95 100       146 return 1 if $char eq '_';
97              
98             # Allow digits
99 86 100       231 return 1 if $char =~ /\d/o;
100              
101             # Start of exponent is special
102 41 100       110 if ( $t->{token}->{content} =~ /e$/i ) {
103             # Allow leading +/- in exponent
104 16 50 66     72 return 1 if $char eq '-' || $char eq '+';
105              
106             # Invalid character in exponent. Recover
107 0 0       0 if ( $t->{token}->{content} =~ s/\.(e)$//i ) {
108 0         0 my $word = $1;
109 0         0 $t->{class} = $t->{token}->set_class('Number');
110 0         0 $t->_new_token('Operator', '.');
111 0         0 $t->_new_token('Word', $word);
112 0         0 return $t->{class}->__TOKENIZER__on_char( $t );
113             }
114             else {
115 0         0 $t->{token}->{_error} = "Illegal character in exponent '$char'";
116             }
117             }
118              
119             # Doesn't fit a special case, or is after the end of the token
120             # End of token.
121 25         52 $t->_finalize_token->__TOKENIZER__on_char( $t );
122             }
123              
124             1;
125              
126             =pod
127              
128             =head1 SUPPORT
129              
130             See the L in the main module.
131              
132             =head1 AUTHOR
133              
134             Chris Dolan Ecdolan@cpan.orgE
135              
136             =head1 COPYRIGHT
137              
138             Copyright 2006 Chris Dolan.
139              
140             This program is free software; you can redistribute
141             it and/or modify it under the same terms as Perl itself.
142              
143             The full text of the license can be found in the
144             LICENSE file included with this module.
145              
146             =cut