File Coverage

blib/lib/Spp/Tools.pm
Criterion Covered Total %
statement 148 326 45.4
branch 33 78 42.3
condition n/a
subroutine 20 35 57.1
pod 0 31 0.0
total 201 470 42.7


line stmt bran cond sub pod time code
1             package Spp::Tools;
2              
3 2     2   34 use 5.012;
  2         5  
4 2     2   16 no warnings 'experimental';
  2         4  
  2         75  
5              
6 2     2   9 use Exporter;
  2         3  
  2         127  
7             our @ISA = qw(Exporter);
8             our @EXPORT =
9             qw(is_type is_atom is_atoms to_ejson from_ejson char_to_ejson atoms flat match name value offline elen epush eappend eunshift ejoin is_atom_name is_sym is_rept is_look is_tillnot is_atom_str is_sub is_return ast_to_table get_rept_time clean_ast clean_atom see_ast is_exported);
10              
11 2     2   10 use Spp::Builtin;
  2         4  
  2         4094  
12              
13             sub is_type {
14 0     0 0 0 my $str = shift;
15 0         0 return $str ~~ [
16             'Str', 'Int', 'Bool', 'Cursor',
17             'Lint', 'Array', 'Stack'
18             ];
19             }
20              
21             sub is_atom {
22 52     52 0 73 my $atom = shift;
23 52 100       105 if (is_estr($atom)) {
24 42 50       82 if (len($atom) < 4) { return 0 }
  0         0  
25 42         63 my $atoms = atoms($atom);
26 42 50       74 if (len($atoms) > 0) {
27 42         80 my $name = $atoms->[0];
28 42         68 return is_str($name);
29             }
30             }
31 10         24 return 0;
32             }
33              
34             sub is_atoms {
35 0     0 0 0 my $atoms = shift;
36 0 0       0 if (is_estr($atoms)) {
37 0         0 for my $atom (@{ atoms($atoms) }) {
  0         0  
38 0 0       0 if (not(is_atom($atom))) { return 0 }
  0         0  
39             }
40 0         0 return 1;
41             }
42 0         0 return 1;
43             }
44              
45             sub to_ejson {
46 3     3 0 5 my $json = shift;
47 3 50       13 if (is_estr($json)) { return $json }
  0         0  
48 3         9 my $chars = [];
49 3         10 my $mode = 0;
50 3         1298 for my $ch (split '', $json) {
51 9324 100       12828 if ($mode == 0) {
    100          
    50          
52 3930         3979 given ($ch) {
53 3930         4784 when ('[') { push @{$chars}, In; }
  855         848  
  855         1538  
54 3075         3348 when (']') { push @{$chars}, Out; }
  855         882  
  855         1374  
55 2220         2452 when ('"') { push @{$chars}, Qstr; $mode = 1 }
  1110         1099  
  1110         1539  
  1110         1651  
56 1110         1151 default {
57 1110 50       1844 if (is_digit($ch)) {
58 0         0 push @{$chars}, Qint;
  0         0  
59 0         0 push @{$chars}, $ch;
  0         0  
60 0         0 $mode = 2;
61             }
62             }
63             }
64             }
65             elsif ($mode == 1) {
66 5370         5171 given ($ch) {
67 5370         6436 when ('"') { $mode = 0 }
  1110         1625  
68 4260         4427 when ("\\") { $mode = 3 }
  24         33  
69 4236         4404 default { push @{$chars}, $ch; }
  4236         4020  
  4236         7042  
70             }
71             }
72             elsif ($mode == 2) {
73 0 0       0 if ($ch eq ',') { $mode = 0 }
  0         0  
74 0 0       0 if ($ch eq ']') { push @{$chars}, Out; $mode = 0 }
  0         0  
  0         0  
  0         0  
75 0 0       0 if (is_digit($ch)) { push @{$chars}, $ch; }
  0         0  
  0         0  
76             }
77             else {
78 24         26 $mode = 1;
79 24         26 given ($ch) {
80 24         31 when ('t') { push @{$chars}, "\t"; }
  0         0  
  0         0  
81 24         31 when ('r') { push @{$chars}, "\r"; }
  0         0  
  0         0  
82 24         36 when ('n') { push @{$chars}, "\n"; }
  0         0  
  0         0  
83 24         27 default { push @{$chars}, $ch; }
  24         25  
  24         42  
84             }
85             }
86             }
87 3         669 return string($chars);
88             }
89              
90             sub from_ejson {
91 0     0 0 0 my $estr = shift;
92 0 0       0 if (is_str($estr)) { return $estr }
  0         0  
93 0         0 my $chars = [];
94 0         0 my $mode = 0;
95 0         0 for my $ch (split '', $estr) {
96 0 0       0 if ($mode == 0) {
    0          
    0          
97 0         0 given ($ch) {
98 0         0 when (In) { push @{$chars}, '['; }
  0         0  
  0         0  
99 0         0 when (Qstr) { push @{$chars}, '"'; $mode = 1 }
  0         0  
  0         0  
  0         0  
100 0         0 when (Qint) { $mode = 2 }
  0         0  
101 0         0 when (Out) { push @{$chars}, ']'; $mode = 3 }
  0         0  
  0         0  
  0         0  
102             }
103             }
104             elsif ($mode == 1) {
105 0         0 given ($ch) {
106 0         0 when (In) { push @{$chars}, '",['; $mode = 0 }
  0         0  
  0         0  
  0         0  
107 0         0 when (Qstr) { push @{$chars}, '","'; }
  0         0  
  0         0  
108 0         0 when (Qint) { push @{$chars}, '",'; $mode = 2 }
  0         0  
  0         0  
  0         0  
109 0         0 when (Out) { push @{$chars}, '"]'; $mode = 3 }
  0         0  
  0         0  
  0         0  
110 0         0 default { push @{$chars}, char_to_ejson($ch); }
  0         0  
  0         0  
111             }
112             }
113             elsif ($mode == 2) {
114 0         0 given ($ch) {
115 0         0 when (In) { push @{$chars}, ',['; $mode = 0 }
  0         0  
  0         0  
  0         0  
116 0         0 when (Qstr) { push @{$chars}, ',"'; $mode = 1 }
  0         0  
  0         0  
  0         0  
117 0         0 when (Qint) { push @{$chars}, ','; }
  0         0  
  0         0  
118 0         0 when (Out) { push @{$chars}, ']'; $mode = 3 }
  0         0  
  0         0  
  0         0  
119 0         0 default { push @{$chars}, $ch; }
  0         0  
  0         0  
120             }
121             }
122             else {
123 0         0 given ($ch) {
124 0         0 when (In) { push @{$chars}, ',['; $mode = 0 }
  0         0  
  0         0  
  0         0  
125 0         0 when (Qstr) { push @{$chars}, ',"'; $mode = 1 }
  0         0  
  0         0  
  0         0  
126 0         0 when (Qint) { push @{$chars}, ','; $mode = 2 }
  0         0  
  0         0  
  0         0  
127 0         0 when (Out) { push @{$chars}, ']'; }
  0         0  
  0         0  
128             }
129             }
130             }
131 0         0 return string($chars);
132             }
133              
134             sub char_to_ejson {
135 0     0 0 0 my $ch = shift;
136 0         0 given ($ch) {
137 0         0 when ("\t") { return '\t' }
  0         0  
138 0         0 when ("\n") { return '\n' }
  0         0  
139 0         0 when ("\r") { return '\r' }
  0         0  
140 0         0 when ("\\") { return '\\\\' }
  0         0  
141 0         0 when ('"') { return '\"' }
  0         0  
142 0         0 default { return $ch }
  0         0  
143             }
144             }
145              
146             sub atoms {
147 1296     1296 0 1590 my $estr = shift;
148 1296         1560 my $estrs = [];
149 1296         1477 my $chars = [];
150 1296         1462 my $depth = 0;
151 1296         1299 my $mode = 0;
152 1296         6820 for my $ch (split '', $estr) {
153 59352 100       81167 if ($depth == 0) {
    100          
154 1296 50       2022 if ($ch eq In) { $depth++ }
  1296         1481  
155             }
156             elsif ($depth == 1) {
157 10472         9966 given ($ch) {
158 10472         12242 when (In) {
159 1440         1440 $depth++;
160 1440 100       1991 if ($mode) {
161 1171         1229 push @{$estrs}, string($chars);
  1171         2077  
162 1171         1990 clean($chars);
163             }
164 1440         1678 $mode = 1;
165 1440         1388 push @{$chars}, $ch;
  1440         2536  
166             }
167 9032         9146 when (Qstr) {
168 1555 100       2261 if ($mode) {
169 528         555 push @{$estrs}, string($chars);
  528         936  
170 528         902 clean($chars);
171             }
172 1555         2296 $mode = 1
173             }
174 7477         7469 when (Qint) {
175 0 0       0 if ($mode) {
176 0         0 push @{$estrs}, string($chars);
  0         0  
177 0         0 clean($chars);
178             }
179 0         0 $mode = 1
180             }
181 7477         7815 when (Out) {
182 1296 50       1984 if ($mode) { push @{$estrs}, string($chars); }
  1296         1291  
  1296         2303  
183             }
184 6181         6183 default {
185 6181 50       8269 if ($mode) { push @{$chars}, $ch; }
  6181         5937  
  6181         13176  
186             }
187             }
188             }
189             else {
190 47584 100       59666 if ($ch eq In) { $depth++ }
  4137         3983  
191 47584 100       59455 if ($ch eq Out) { $depth-- }
  5577         5282  
192 47584         43763 push @{$chars}, $ch;
  47584         64303  
193             }
194             }
195 1296         5915 return $estrs;
196             }
197              
198             sub flat {
199 966     966 0 1149 my $estr = shift;
200 966 50       1464 if (is_str($estr)) {
201 0         0 croak("Str: |$estr| could not flat!");
202             }
203 966         1410 my $atoms = atoms($estr);
204 966 50       1667 if (len($atoms) < 2) {
205 0         0 say from_ejson($estr);
206 0         0 croak("flat less two atom");
207             }
208 966         2666 return $atoms->[0], $atoms->[1];
209             }
210              
211             sub match {
212 3     3 0 7 my $estr = shift;
213 3         6 my $atoms = atoms($estr);
214 3 50       10 if (len($atoms) == 0) { error("match with blank") }
  0         0  
215 3 50       8 if (len($atoms) == 1) { return $atoms->[0], Blank }
  0         0  
216 3         16 return $atoms->[0], estr(rest($atoms));
217             }
218              
219             sub name {
220 22     22 0 28 my $estr = shift;
221 22         28 my $atoms = atoms($estr);
222 22         68 return $atoms->[0];
223             }
224              
225             sub value {
226 5     5 0 8 my $estr = shift;
227 5         8 my $atoms = atoms($estr);
228 5         15 return $atoms->[1];
229             }
230              
231             sub offline {
232 0     0 0 0 my $estr = shift;
233 0         0 my $atoms = atoms($estr);
234 0         0 return $atoms->[-1];
235             }
236              
237             sub elen {
238 3     3 0 6 my $estr = shift;
239 3         9 my $atoms = atoms($estr);
240 3         10 return len($atoms);
241             }
242              
243             sub epush {
244 1     1 0 4 my ($array, $elem) = @_;
245 1         5 return add(Chop($array), $elem, Out);
246             }
247              
248             sub eappend {
249 0     0 0 0 my ($a_one, $a_two) = @_;
250 0         0 return add(Chop($a_one), rest_str($a_two));
251             }
252              
253             sub eunshift {
254 3     3 0 10 my ($elem, $array) = @_;
255 3         14 return add(In, $elem, rest_str($array));
256             }
257              
258             sub ejoin {
259 0     0 0 0 my ($estr, $sub) = @_;
260 0         0 return join $sub, @{ atoms($estr) };
  0         0  
261             }
262              
263             sub is_atom_name {
264 14     14 0 24 my ($atom, $name) = @_;
265 14 50       23 if (is_atom($atom)) { return name($atom) eq $name }
  14         26  
266 0         0 return 0;
267             }
268              
269             sub is_sym {
270 0     0 0 0 my $atom = shift;
271 0         0 return is_atom_name($atom, 'Sym');
272             }
273              
274             sub is_rept {
275 7     7 0 11 my $atom = shift;
276 7         12 return is_atom_name($atom, 'rept');
277             }
278              
279             sub is_look {
280 7     7 0 10 my $atom = shift;
281 7         19 return is_atom_name($atom, 'look');
282             }
283              
284             sub is_tillnot {
285 7     7 0 13 my $atom = shift;
286 7 50       14 if (is_atom($atom)) {
287 7         14 given (name($atom)) {
288 7         16 when ('Till') { return 1 }
  0         0  
289 7         12 when ('Not') { return 1 }
  0         0  
290             }
291             }
292 7         19 return 0;
293             }
294              
295             sub is_atom_str {
296 0     0 0 0 my $atom = shift;
297 0         0 return is_atom_name($atom, 'Str');
298             }
299              
300             sub is_sub {
301 0     0 0 0 my $atom = shift;
302 0         0 return is_atom_name($atom, 'Sub');
303             }
304              
305             sub is_return {
306 0     0 0 0 my $atom = shift;
307 0         0 return is_atom_name($atom, '->');
308             }
309              
310             sub ast_to_table {
311 3     3 0 8 my $ast = shift;
312 3         8 my $table = {};
313 3         8 for my $spec (@{ atoms($ast) }) {
  3         17  
314 96         145 my ($name, $rule) = flat($spec);
315 96 50       180 if (exists $table->{$name}) {
316 0         0 say "redefine token: <$name>";
317             }
318 96         253 $table->{$name} = $rule;
319             }
320 3         38 return $table;
321             }
322              
323             sub get_rept_time {
324 77     77 0 103 my $rept = shift;
325 77         106 given ($rept) {
326 77         116 when ('?') { return 0, 1 }
  1         3  
327 76         110 when ('*') { return 0, -1 }
  3         10  
328 73         103 default { return 1, -1 }
  73         146  
329             }
330             }
331              
332             sub clean_ast {
333 0     0 0   my $ast = shift;
334 0 0         if (is_atom($ast)) { return clean_atom($ast) }
  0            
335 0           my $clean_atoms = [];
336 0           for my $atom (@{ atoms($ast) }) {
  0            
337 0           push @{$clean_atoms}, clean_atom($atom);
  0            
338             }
339 0           return estr($clean_atoms);
340             }
341              
342             sub clean_atom {
343 0     0 0   my $atom = shift;
344 0           my ($name, $value) = flat($atom);
345 0 0         if (is_str($value)) { return cons($name, $value) }
  0            
346 0 0         if (is_blank($value)) { return cons($name, $value) }
  0            
347 0 0         if (is_atom($value)) {
348 0           return cons($name, clean_atom($value));
349             }
350 0 0         if (is_atoms($value)) {
351 0           return cons($name, clean_ast($value));
352             }
353 0           say from_ejson($atom);
354 0           croak("ast data error!");
355 0           return False;
356             }
357              
358             sub see_ast {
359 0     0 0   my $ast = shift;
360 0           return from_ejson(clean_ast($ast));
361             }
362              
363             sub is_exported {
364 0     0 0   my $name = shift;
365 0           return not(start_with($name, '_'));
366             }
367             1;