File Coverage

blib/lib/Spp/OptAst.pm
Criterion Covered Total %
statement 122 244 50.0
branch 22 56 39.2
condition n/a
subroutine 17 29 58.6
pod 0 24 0.0
total 161 353 45.6


line stmt bran cond sub pod time code
1             package Spp::OptAst;
2              
3 2     2   38 use 5.012;
  2         5  
4 2     2   14 no warnings 'experimental';
  2         4  
  2         69  
5              
6 2     2   9 use Exporter;
  2         4  
  2         155  
7             our @ISA = qw(Exporter);
8             our @EXPORT =
9             qw(opt_spp_ast map_opt_spp_atom opt_spp_atom opt_spp_spec opt_spp_rules opt_spp_group opt_spp_branch opt_spp_atoms opt_spp_kstr opt_spp_cclass opt_spp_char opt_spp_escape_char opt_spp_chclass opt_spp_catom opt_spp_cchar opt_spp_range opt_spp_look gather_spp_tillnot gather_spp_look gather_spp_rept opt_spp_token opt_spp_str opt_spp_expr opt_spp_array);
10              
11 2     2   11 use Spp::Builtin;
  2         7  
  2         395  
12 2     2   12 use Spp::Tools;
  2         3  
  2         3133  
13              
14             sub opt_spp_ast {
15 3     3 0 4 my $ast = shift;
16 3 50       8 if (is_atom($ast)) { return cons(opt_spp_atom($ast)) }
  3         10  
17 0         0 return map_opt_spp_atom($ast);
18             }
19              
20             sub map_opt_spp_atom {
21 3     3 0 5 my $atoms = shift;
22             return estr(
23 3         5 [map { opt_spp_atom($_) } @{ atoms($atoms) }]);
  7         15  
  3         7  
24             }
25              
26             sub opt_spp_atom {
27 10     10 0 13 my $atom = shift;
28 10         19 my ($name, $value) = flat($atom);
29 10         15 given ($name) {
30 10         18 when ('Spec') { return opt_spp_spec($value) }
  3         10  
31 7         10 when ('Group') { return opt_spp_group($value) }
  0         0  
32 7         12 when ('Branch') { return opt_spp_branch($value) }
  0         0  
33 7         8 when ('Cclass') { return opt_spp_cclass($value) }
  2         5  
34 5         6 when ('Char') { return opt_spp_char($value) }
  0         0  
35 5         8 when ('Str') { return opt_spp_str($value) }
  0         0  
36 5         6 when ('String') { return opt_spp_str($value) }
  0         0  
37 5         7 when ('Kstr') { return opt_spp_kstr($value) }
  0         0  
38 5         8 when ('Chclass') { return opt_spp_chclass($value) }
  0         0  
39 5         5 when ('Look') { return opt_spp_look($value) }
  1         5  
40 4         5 when ('Token') { return opt_spp_token($value) }
  2         8  
41 2         4 when ('Expr') { return opt_spp_expr($value) }
  0         0  
42 2         3 when ('Array') { return opt_spp_array($value) }
  0         0  
43 2         3 default { return cons($name, $value) }
  2         5  
44             }
45             }
46              
47             sub opt_spp_spec {
48 3     3 0 4 my $atoms = shift;
49 3         9 my ($token, $rules) = match($atoms);
50 3         11 my $name = value($token);
51 3         10 my $opt_rules = opt_spp_rules($rules);
52 3         8 return cons($name, $opt_rules);
53             }
54              
55             sub opt_spp_rules {
56 3     3 0 5 my $atoms = shift;
57 3         10 my $opt_atoms = opt_spp_atoms($atoms);
58 3 100       12 if (elen($opt_atoms) == 1) { return name($opt_atoms) }
  1         3  
59 2         6 return cons('Rules', $opt_atoms);
60             }
61              
62             sub opt_spp_group {
63 0     0 0 0 my $atoms = shift;
64 0         0 my $opt_atoms = opt_spp_atoms($atoms);
65 0 0       0 if (elen($opt_atoms) == 1) { return name($opt_atoms) }
  0         0  
66 0         0 return cons('Group', $opt_atoms);
67             }
68              
69             sub opt_spp_branch {
70 0     0 0 0 my $atoms = shift;
71 0         0 my $opt_atoms = opt_spp_atoms($atoms);
72 0 0       0 if (elen($opt_atoms) == 1) { return name($opt_atoms) }
  0         0  
73 0         0 return cons('Branch', $opt_atoms);
74             }
75              
76             sub opt_spp_atoms {
77 3     3 0 5 my $atoms = shift;
78 3         8 return gather_spp_rept(
79             gather_spp_look(
80             gather_spp_tillnot(map_opt_spp_atom($atoms))
81             )
82             );
83             }
84              
85             sub opt_spp_kstr {
86 0     0 0 0 my $kstr = shift;
87 0         0 my $str = rest_str($kstr);
88 0 0       0 if (len($str) == 1) { return cons('Char', $str) }
  0         0  
89 0         0 return cons('Str', $str);
90             }
91              
92             sub opt_spp_cclass {
93 2     2 0 4 my $cclass = shift;
94 2         33 return cons('Cclass', last_char($cclass));
95             }
96              
97             sub opt_spp_char {
98 0     0 0 0 my $char = shift;
99 0         0 return cons('Char', opt_spp_escape_char($char));
100             }
101              
102             sub opt_spp_escape_char {
103 0     0 0 0 my $str = shift;
104 0         0 my $char = last_char($str);
105 0         0 given ($char) {
106 0         0 when ('n') { return "\n" }
  0         0  
107 0         0 when ('r') { return "\r" }
  0         0  
108 0         0 when ('t') { return "\t" }
  0         0  
109 0         0 when ('s') { return 's' }
  0         0  
110 0         0 default { return $char }
  0         0  
111             }
112             }
113              
114             sub opt_spp_chclass {
115 0     0 0 0 my $nodes = shift;
116 0         0 my $atoms = [];
117 0         0 my $flip = 0;
118 0         0 for my $node (@{ atoms($nodes) }) {
  0         0  
119 0         0 my ($name, $value) = flat($node);
120 0 0       0 if ($name eq 'Flip') { $flip = 1 }
  0         0  
121             else {
122 0         0 my $atom = opt_spp_catom($name, $value);
123 0         0 push @{$atoms}, $atom;
  0         0  
124             }
125             }
126 0 0       0 if ($flip == 0) { return cons('Chclass', estr($atoms)) }
  0         0  
127 0         0 return cons('Nclass', estr($atoms));
128             }
129              
130             sub opt_spp_catom {
131 0     0 0 0 my ($name, $value) = @_;
132 0         0 given ($name) {
133 0         0 when ('Cclass') { return opt_spp_cclass($value) }
  0         0  
134 0         0 when ('Range') { return opt_spp_range($value) }
  0         0  
135 0         0 when ('Char') { return opt_spp_cchar($value) }
  0         0  
136 0         0 default { return cons('Cchar', $value) }
  0         0  
137             }
138             }
139              
140             sub opt_spp_cchar {
141 0     0 0 0 my $char = shift;
142 0         0 return cons('Cchar', opt_spp_escape_char($char));
143             }
144              
145             sub opt_spp_range {
146 0     0 0 0 my $atom = shift;
147 0         0 return cons('Range', estr([split '-', $atom]));
148             }
149              
150             sub opt_spp_look {
151 1     1 0 2 my $estr = shift;
152 1         4 my $atoms = atoms($estr);
153 1         2 my $rept = $atoms->[0];
154 1         3 my $char = value($rept);
155 1 50       3 if (len($atoms) == 1) { return cons('rept', $char) }
  1         4  
156 0         0 return cons('look', $char);
157             }
158              
159             sub gather_spp_tillnot {
160 3     3 0 5 my $atoms = shift;
161 3         5 my $opt_atoms = [];
162 3         6 my $flag = 0;
163 3         4 my $cache = '';
164 3         6 for my $atom (@{ atoms($atoms) }) {
  3         6  
165 7 50       12 if ($flag == 0) {
166 7 50       18 if (is_tillnot($atom)) { $flag = 1; $cache = $atom }
  0         0  
  0         0  
167 7         8 else { push @{$opt_atoms}, $atom; }
  7         13  
168             }
169             else {
170 0 0       0 if (not(is_tillnot($atom))) {
171 0         0 my $name = name($cache);
172 0         0 $cache = cons($name, $atom);
173 0         0 push @{$opt_atoms}, $cache;
  0         0  
174 0         0 $flag = 0;
175             }
176             }
177             }
178 3 50       10 if ($flag > 0) { error("Till/Not without token!") }
  0         0  
179 3         7 return estr($opt_atoms);
180             }
181              
182             sub gather_spp_look {
183 3     3 0 6 my $atoms = shift;
184 3         6 my $opt_atoms = [];
185 3         3 my $flag = 0;
186 3         5 my $cache = '';
187 3         5 my $look = '';
188 3         6 for my $atom (@{ atoms($atoms) }) {
  3         4  
189 7 100       18 if ($flag == 0) {
    50          
190 3 50       10 if (not(is_look($atom))) { $cache = $atom; $flag = 1 }
  3         5  
  3         6  
191             }
192             elsif ($flag == 1) {
193 4 50       8 if (is_look($atom)) {
194 0         0 $look = value($atom);
195 0         0 $flag = 2;
196             }
197 4         6 else { push @{$opt_atoms}, $cache; $cache = $atom }
  4         7  
  4         7  
198             }
199             else {
200 0 0       0 if (not(is_look($atom))) {
201 0         0 $cache = cons($look, cons($cache, $atom));
202 0         0 $cache = cons('Look', $cache);
203 0         0 push @{$opt_atoms}, $cache;
  0         0  
204 0         0 $flag = 0;
205             }
206             }
207             }
208 3 50       8 if ($flag == 1) { push @{$opt_atoms}, $cache; }
  3         4  
  3         8  
209 3         7 return estr($opt_atoms);
210             }
211              
212             sub gather_spp_rept {
213 3     3 0 6 my $atoms = shift;
214 3         5 my $opt_atoms = [];
215 3         6 my $flag = 0;
216 3         5 my $cache = '';
217 3         5 for my $atom (@{ atoms($atoms) }) {
  3         7  
218 7 100       14 if ($flag == 0) {
219 3 50       11 if (not(is_rept($atom))) { $cache = $atom; $flag = 1 }
  3         8  
  3         5  
220             }
221             else {
222 4 100       7 if (is_rept($atom)) {
223 1         3 my $rept = value($atom);
224 1         3 $cache = cons('Rept', cons($rept, $cache));
225 1         2 push @{$opt_atoms}, $cache;
  1         2  
226 1         2 $flag = 0;
227             }
228 3         4 else { push @{$opt_atoms}, $cache; $cache = $atom }
  3         6  
  3         6  
229             }
230             }
231 3 100       7 if ($flag == 1) { push @{$opt_atoms}, $cache; }
  2         2  
  2         6  
232 3         8 return estr($opt_atoms);
233             }
234              
235             sub opt_spp_token {
236 2     2 0 3 my $name = shift;
237 2         8 my $char = first_char($name);
238 2 50       7 if (is_upper($char)) { return cons('Ntoken', $name) }
  0         0  
239 2 50       9 if (is_lower($char)) { return cons('Ctoken', $name) }
  2         5  
240 0           return cons('Rtoken', $name);
241             }
242              
243             sub opt_spp_str {
244 0     0 0   my $atoms = shift;
245 0           my $opt_atoms = [];
246 0           for my $atom (@{ atoms($atoms) }) {
  0            
247 0           my ($name, $value) = flat($atom);
248 0           given ($name) {
249 0           when ('Char') {
250 0           my $char = opt_spp_escape_char($value);
251 0           push @{$opt_atoms}, $char;
  0            
252             }
253 0           default { push @{$opt_atoms}, $value; }
  0            
  0            
254             }
255             }
256 0           my $str = join '', @{$opt_atoms};
  0            
257 0 0         if (len($str) == 1) { return cons('Char', $str) }
  0            
258 0           return cons('Str', $str);
259             }
260              
261             sub opt_spp_expr {
262 0     0 0   my $atoms = shift;
263 0           my ($action, $args) = match($atoms);
264 0 0         if (is_sub($action)) {
265 0           my $call = value($action);
266 0 0         if ($call ~~ ['push', 'my']) {
267 0           my $opt_args = map_opt_spp_atom($args);
268 0           my $expr = cons($call, $opt_args);
269 0           return cons('Call', $expr);
270             }
271 0           else { error("not implement action: |$call|") }
272             }
273 0           my $action_str = from_ejson($action);
274 0           error("Expr not action: $action_str");
275             }
276              
277             sub opt_spp_array {
278 0     0 0   my $atoms = shift;
279 0 0         if (is_str($atoms)) { return cons('Array', Blank) }
  0            
280 0           my $opt_atoms = map_opt_spp_atom($atoms);
281 0           return cons('Array', $opt_atoms);
282             }
283             1;