File Coverage

blib/lib/JSON/Decode/Regexp.pm
Criterion Covered Total %
statement 19 20 95.0
branch 8 10 80.0
condition n/a
subroutine 6 6 100.0
pod 1 1 100.0
total 34 37 91.8


line stmt bran cond sub pod time code
1             package JSON::Decode::Regexp;
2              
3             our $DATE = '2018-03-25'; # DATE
4             our $VERSION = '0.101'; # VERSION
5              
6 1     1   430 use 5.010001;
  1         6  
7 1     1   4 use strict;
  1         1  
  1         14  
8 1     1   4 use warnings;
  1         1  
  1         782  
9              
10             #use Data::Dumper;
11              
12             require Exporter;
13             our @ISA = qw(Exporter);
14             our @EXPORT_OK = qw(from_json);
15              
16 5     5   31 sub _fail { die __PACKAGE__.": $_[0] at offset ".pos()."\n" }
17              
18             my %escape_codes = (
19             "\\" => "\\",
20             "\"" => "\"",
21             "b" => "\b",
22             "f" => "\f",
23             "n" => "\n",
24             "r" => "\r",
25             "t" => "\t",
26             );
27              
28             sub _decode_str {
29 22     22   55 my $str = shift;
30 22         60 $str =~ s[(\\(?:([0-7]{1,3})|x([0-9A-Fa-f]{1,2})|(.)))]
31             [defined($2) ? chr(oct $2) :
32 11 50       59 defined($3) ? chr(hex $3) :
    100          
    100          
33             $escape_codes{$4} ? $escape_codes{$4} :
34 22         105 $1]eg;
35             $str;
36             }
37              
38             our $FROM_JSON = qr{
39              
40             (?:
41             (?&VALUE) (?{ $_ = $^R->[1] })
42             |
43             \z (?{ _fail "Unexpected end of input" })
44             |
45             (?{ _fail "Invalid literal" })
46             )
47              
48             (?(DEFINE)
49              
50             (?
51             \{\s*
52             (?{ [$^R, {}] })
53             (?:
54             (?&KV) # [[$^R, {}], $k, $v]
55             (?{ [$^R->[0][0], {$^R->[1] => $^R->[2]}] })
56             \s*
57             (?:
58             (?:
59             ,\s* (?&KV) # [[$^R, {...}], $k, $v]
60             (?{ $^R->[0][1]{ $^R->[1] } = $^R->[2]; $^R->[0] })
61             )*
62             |
63             (?:[^,\}]|\z) (?{ _fail "Expected ',' or '\x7d'" })
64             )*
65             )?
66             \s*
67             (?:
68             \}
69             |
70             (?:.|\z) (?{ _fail "Expected closing of hash" })
71             )
72             )
73              
74             (?
75             (?&STRING) # [$^R, "string"]
76             \s*
77             (?:
78             :\s* (?&VALUE) # [[$^R, "string"], $value]
79             (?{ [$^R->[0][0], $^R->[0][1], $^R->[1]] })
80             |
81             (?:[^:]|\z) (?{ _fail "Expected ':'" })
82             )
83             )
84              
85             (?
86             \[\s*
87             (?{ [$^R, []] })
88             (?:
89             (?&VALUE) # [[$^R, []], $val]
90             (?{ [$^R->[0][0], [$^R->[1]]] })
91             \s*
92             (?:
93             (?:
94             ,\s* (?&VALUE)
95             (?{ push @{$^R->[0][1]}, $^R->[1]; $^R->[0] })
96             )*
97             |
98             (?: [^,\]]|\z ) (?{ _fail "Expected ',' or '\x5d'" })
99             )
100             )?
101             \s*
102             (?:
103             \]
104             |
105             (?:.|\z) (?{ _fail "Expected closing of array" })
106             )
107             )
108              
109             (?
110             \s*
111             (
112             (?&STRING)
113             |
114             (?&NUMBER)
115             |
116             (?&OBJECT)
117             |
118             (?&ARRAY)
119             |
120             true (?{ [$^R, 1] })
121             |
122             false (?{ [$^R, 0] })
123             |
124             null (?{ [$^R, undef] })
125             )
126             \s*
127             )
128              
129             (?
130             "
131             (
132             (?:
133             [^\\"]+
134             |
135             \\ [0-7]{1,3}
136             |
137             \\ x [0-9A-Fa-f]{1,2}
138             |
139             \\ ["\\/bfnrt]
140             #|
141             # \\ u [0-9a-fA-f]{4}
142             |
143             \\ (.) (?{ _fail "Invalid string escape character $^N" })
144             )*
145             )
146             (?:
147             "
148             |
149             (?:\\|\z) (?{ _fail "Expected closing of string" })
150             )
151              
152             (?{ [$^R, _decode_str($^N)] })
153             )
154              
155             (?
156             (
157             -?
158             (?: 0 | [1-9][0-9]* )
159             (?: \. [0-9]+ )?
160             (?: [eE] [-+]? [0-9]+ )?
161             )
162              
163             (?{ [$^R, 0+$^N] })
164             )
165              
166             ) }xms;
167              
168 21     21 1 1311 sub from_json {
169             state $re = qr{\A$FROM_JSON\z};
170 21         36  
171 21         25 local $_ = shift;
172 21 100       39 local $^R;
  21         179  
173 5 50       23 eval { $_ =~ $re } and return $_;
174 0           die $@ if $@;
175             die 'no match';
176             }
177              
178             1;
179             # ABSTRACT: JSON parser as a single Perl Regex
180              
181             __END__