File Coverage

blib/lib/Hub/Parse/StandardParser.pm
Criterion Covered Total %
statement 6 7 85.7
branch 0 2 0.0
condition n/a
subroutine 2 3 66.6
pod 1 1 100.0
total 9 13 69.2


line stmt bran cond sub pod time code
1             package Hub::Parse::StandardParser;
2 1     1   5 use strict;
  1         2  
  1         38  
3 1     1   5 use Hub qw/:lib/;
  1         2  
  1         5  
4              
5             push our @ISA, qw(Hub::Parse::Parser);
6              
7             our %EVALUATORS;
8              
9             sub get_evaluator {
10 0 0   0 1   return defined $EVALUATORS{$_[1]}
11             ? $EVALUATORS{$_[1]}
12             : &Hub::Parse::Parser::get_evaluator(@_);
13             }
14              
15             $EVALUATORS{'into'} = sub {
16             my ($self, $params, $result) = @_;
17             my ($outer_str, $fields, $pos, $text, $parents, $valdata) = @$params;
18             my ($opts, %directive) = Hub::opts($fields);
19             $result->{'value'} = '';
20             push @$parents, \%directive;
21             };
22              
23             $EVALUATORS{'use'} = sub {
24             my ($self, $params, $result) = @_;
25             my ($outer_str, $fields, $pos, $text, $parents, $valdata) = @$params;
26             my ($opts, %directive) = Hub::hashopts($fields);
27             $result->{'value'} = '';
28             my $h = $self->get_value($directive{'use'}, $valdata, $fields);
29             unless (ref($h)) {
30             warn "Cannot use item '$h'" . $self->get_hint($$pos, $text)
31             if $$Hub{'/sys/ENV/DEBUG'};
32             }
33             $h = { $directive{'as'} => $h } if $directive{'as'};
34             unshift @$valdata, $h;
35             };
36              
37             $EVALUATORS{'define'} = sub {
38             my ($self, $params, $result) = @_;
39             my ($outer_str, $fields, $pos, $text, $parents, $valdata) = @$params;
40             my ($opts, %directive) = Hub::hashopts($fields);
41             $result->{'value'} = '';
42             my $varname = $directive{'define'};
43             my ($end_p, $block) =
44             $self->_get_block($$pos + length($outer_str), $text, 'define');
45             $$result{'width'} = $end_p - $$pos;
46             $directive{'as'} ||= 'HASH';
47             my $data = ();
48             if ($directive{'as'} =~ /^(DATA|HASH)$/i) {
49             $data = Hub::hparse($block);
50             } elsif ($directive{'as'} =~ /^(LIST|ARRAY)$/i) {
51             $data = Hub::hparse($block, -as_array => 1);
52             } elsif ($directive{'as'} =~ /^(TEXT|SCALAR)$/i) {
53             $data = $block;
54             }
55             push @$valdata, defined $varname ? {$varname, $data} : $data;
56             };
57              
58             $EVALUATORS{'if'} = sub {
59             my ($self, $params, $result) = @_;
60             my ($outer_str, $fields, $pos, $text, $parents, $valdata) = @$params;
61             $result->{'value'} = '';
62             my ($opts, @params) = Hub::opts($fields);
63             shift @params; # drop 'if' part
64             my $true = 0; # default to false
65             if (defined $params[2]) {
66             # This is a two-part evaluation
67             my $l = $self->get_value($params[0], \@$valdata);
68             my $r = $self->get_value($params[2], \@$valdata);
69             if (defined $l && defined $r) {
70             $true = Hub::compare($params[1], $l, $r);
71             } elsif (!defined $l && !defined $r) {
72             $true = 1;
73             }
74             } else {
75             # This boolean condition
76             my $v = $self->get_value($params[0], \@$valdata);
77             $true = defined $v
78             ? Hub::is_bipolar($v)
79             ? 1
80             : isa($v, 'ARRAY')
81             ? @$v
82             : isa($v, 'HASH')
83             ? scalar(keys %$v)
84             : ref($v) eq 'SCALAR'
85             ? $$v
86             : $v
87             : 0;
88             }
89             my ($end_p, $block) =
90             $self->_get_block($$pos + length($outer_str), $text, 'if');
91             $$result{'width'} = $end_p - $$pos;
92             my ($if,$else) = $self->_split_if_else($block);
93             # Logical not
94             $true = !$true if $$opts{'not'};
95             # Replace block with logical portion
96             $$result{'value'} = $true ? $if : $else;
97             };
98              
99             $EVALUATORS{'foreach'} = sub {
100             my ($self, $params, $result) = @_;
101             my ($outer_str, $fields, $pos, $text, $parents, $valdata) = @$params;
102             # Parse parameters (we delete the internally removed parameters
103             # so that the others may be passed to get_value.)
104             my ($opts, %directive) = Hub::opts($fields);
105             $result->{'value'} = '';
106             my $varname = $directive{'foreach'};
107             delete $directive{'foreach'};
108             die "Missing variable name parameter" . $self->get_hint($$pos, $text)
109             unless defined $varname;
110             my $in = $directive{'in'};
111             delete $directive{'in'};
112             die "Missing 'in' parameter" . $self->get_hint($$pos, $text)
113             unless defined $in;
114             my $sort = $$opts{'sort'} || 0;
115             my ($end_p, $block) =
116             $self->_get_block($$pos + length($outer_str), $text, 'foreach');
117             $$result{'width'} = $end_p - $$pos;
118             # Get the data for the sub-template
119             my $data = $self->get_value($in, \@$valdata, $fields);
120             if (defined $data && !ref($data)) {
121             if ($$opts{'split'}) {
122             $data = [split($$opts{'split'}, $data)];
123             } elsif ($$opts{'split_hash'}) {
124             my %hash_data = split($$opts{'split_hash'}, $data);
125             $data = \%hash_data;
126             }
127             }
128             my @items = ();
129             if (isa($data, 'HASH')) {
130             my @keys = keys %$data;
131             if ($sort) {
132             my $comparator = $sort eq '1' ? 'cmp' : $sort;
133             @keys = sort {
134             Hub::sort_compare($comparator, $self->_to_string($a), $self->_to_string($b))
135             } keys %$data;
136             }
137             @keys = grep { substr($_, 0, 1) ne '.' } @keys;
138             for (@keys) {
139             push @items, {
140             $varname => {
141             'name' => $self->_to_string($_),
142             'value' => $$data{$_},
143             }
144             }
145             }
146             } elsif (isa($data, 'ARRAY')) {
147             my $comparator = $sort eq '1' ? 'cmp' : $sort;
148             for ($sort ? sort {
149             Hub::sort_compare($comparator, $self->_to_string($a), $self->_to_string($b))
150             } @$data : @$data) {
151             push @items, { $varname => $self->_to_string($_), };
152             }
153             } elsif (defined $data) {
154             push @items, { $varname => $data, };
155             }
156             # Populate the sub-template for each datum
157             my $idx = 0;
158             my @text_results = ();
159             foreach my $item (@items) {
160             my $item_text = $self->_populate(-text => $block,
161             $item, @$valdata, {
162             '.idx' => $idx,
163             '.num' => ($idx + 1),
164             '.total' => scalar(@items),
165             '.pen' => $#items, # penultimate
166             });
167             $self->{'*depth'}--; # our call to _populate is not stepping deeper
168             push @text_results, $item_text
169             if defined $item_text && ref($item_text) eq 'SCALAR';
170             $idx++;
171             }
172             my $num_joins = 0;
173             for(my $i = 0; $i < @text_results; $i++) {
174             my $item_text = $text_results[$i];
175             if ($$item_text) {
176             if ($$opts{'joint'} && $num_joins > 0) {
177             $$result{'value'} .= $$opts{'joint'};
178             }
179             $$result{'value'} .= $$item_text;
180             $num_joins++;
181             }
182             }
183             # This worked everywhere, but with the foreach loop on
184             # dev.livesite.net/custom-fonts. The idea is to skip
185             # over the entire foreach section after it is parsed so that
186             # it doesn't get reparsed.
187             # $$result{'goto'} = $$pos + length($$result{'value'});
188             };
189              
190             $EVALUATORS{'end'} = sub {
191             my ($self, $params, $result) = @_;
192             my ($outer_str, $fields, $pos, $text, $parents, $valdata) = @$params;
193             my ($opts, %directive) = Hub::opts($fields);
194             $result->{'value'} = '';
195             shift @$valdata if $directive{'end'} eq 'use';
196             };
197              
198             1;