File Coverage

blib/lib/MarpaX/ESLIF/ECMA404/ValueInterface.pm
Criterion Covered Total %
statement 44 64 68.7
branch 5 18 27.7
condition 11 18 61.1
subroutine 15 19 78.9
pod 14 14 100.0
total 89 133 66.9


line stmt bran cond sub pod time code
1 1     1   7 use strict;
  1         3  
  1         34  
2 1     1   6 use warnings FATAL => 'all';
  1         2  
  1         41  
3              
4             package MarpaX::ESLIF::ECMA404::ValueInterface;
5 1     1   6 use Math::BigInt;
  1         3  
  1         7  
6 1     1   22479 use Math::BigFloat;
  1         3  
  1         7  
7 1     1   663 use Carp qw/croak/;
  1         2  
  1         787  
8              
9             our $FFFD = chr(0xFFFD);
10              
11             # ABSTRACT: MarpaX::ESLIF::ECMA404 Value Interface
12              
13             our $VERSION = '0.012'; # VERSION
14              
15             our $AUTHORITY = 'cpan:JDDPAUSE'; # AUTHORITY
16              
17              
18             # -----------
19             # Constructor
20             # -----------
21              
22              
23             sub new {
24 354     354 1 1676 my ($pkg, %options) = @_;
25              
26 354         2038 return bless { result => undef, %options }, $pkg
27             }
28              
29             # ----------------
30             # Required methods
31             # ----------------
32              
33              
34 354     354 1 961 sub isWithHighRankOnly { return 1 } # When there is the rank adverb: highest ranks only ?
35              
36              
37 354     354 1 965 sub isWithOrderByRank { return 1 } # When there is the rank adverb: order by rank ?
38              
39              
40 354     354 1 824 sub isWithAmbiguous { return 0 } # Allow ambiguous parse ?
41              
42              
43 354     354 1 862 sub isWithNull { return 0 } # Allow null parse ?
44              
45              
46 354     354 1 9634 sub maxParses { return 0 } # Maximum number of parse tree values
47              
48              
49 149     149 1 1016 sub getResult { return $_[0]->{result} }
50              
51              
52 149     149 1 1398 sub setResult { return $_[0]->{result} = $_[1] }
53              
54             # ----------------
55             # Specific actions
56             # ----------------
57              
58              
59             sub unicode {
60 42     42 1 211 my ($self, $u) = @_;
61              
62 42         81 my @hex;
63 42         329 while ($u =~ m/\\u([[:xdigit:]]{4})/g) {
64 80         370 push(@hex, hex($1))
65             }
66              
67 42         76 my $result;
68 42         98 while (@hex) {
69 72 100       187 if ($#hex > 0) {
70 36         73 my ($high, $low) = @hex;
71             #
72             # An UTF-16 surrogate pair ?
73             #
74 36 100 100     180 if (($high >= 0xD800) && ($high <= 0xDBFF) && ($low >= 0xDC00) && ($low <= 0xDFFF)) {
      100        
      66        
75             #
76             # Yes.
77             # This is evaled for one reason only: some old versions of perl may croak with special characters like
78             # "Unicode character 0x10ffff is illegal"
79             #
80 8   33     24 $result .= eval {chr((($high - 0xD800) * 0x400) + ($low - 0xDC00) + 0x10000)} // $FFFD;
  8         46  
81 8         31 splice(@hex, 0, 2)
82             } else {
83             #
84             # No. Take first \uhhhh as a code point. Fallback to replacement character 0xFFFD if invalid.
85             # Eval returns undef in scalar context if there is a failure.
86             #
87 28   33     50 $result .= eval {chr(shift @hex) } // $FFFD
  28         136  
88             }
89             } else {
90             #
91             # \uhhhh taken as a code point. Fallback to replacement character 0xFFFD if invalid.
92             # Eval returns undef in scalar context if there is a failure.
93             #
94 36   33     79 $result .= eval {chr(shift @hex) } // $FFFD
  36         174  
95             }
96             }
97              
98 42         2477 return $result
99             }
100              
101              
102             sub members {
103 354 50   354 1 1356 do { shift, return { map { $_->[0] => $_->[1] } @_ } } if !$_[0]->{disallow_dupkeys};
  354         911  
  1135         31711  
104              
105 0           my $self = shift;
106              
107             #
108             # Arguments are: ($self, $pair1, $pair2, etc..., $pairn)
109             #
110 0           my %hash;
111 0           foreach (@_) {
112 0           my ($key, $value) = @{$_};
  0            
113 0 0         if (exists $hash{$key}) {
114 0 0         if ($self->{disallow_dupkeys}) {
115             #
116             # Just make sure the key printed out contains only printable things
117             #
118 0           my $ascii = $key;
119 0           $ascii =~ s/[^[:print:]]/ /g;
120 0 0         $ascii .= " (printable characters only)" unless $ascii eq $key;
121 0 0         $self->{logger}->errorf('Duplicate key %s', $ascii) if $self->{logger};
122 0           croak "Duplicate key $ascii"
123             } else {
124             $self->{logger}->warnf('Duplicate key %s', $key) if $self->{logger}
125 0 0         }
126             }
127 0           $hash{$key} = $value
128             }
129              
130 0           return \%hash
131             }
132              
133              
134             sub number {
135 0     0 1   my ($self, $number) = @_;
136             #
137             # We are sure this is a float if there is the dot '.' or the exponent [eE]
138             #
139 0 0         return ($number =~ /[\.eE]/) ? Math::BigFloat->new($number) : Math::BigInt->new($number)
140             }
141              
142              
143             sub nan {
144 0     0 1   return Math::BigInt->bnan()
145             }
146              
147              
148             sub negative_infinity {
149 0     0 1   return Math::BigInt->binf('-')
150             }
151              
152              
153             sub positive_infinity {
154 0     0 1   return Math::BigInt->binf()
155             }
156              
157              
158             1;
159              
160             __END__