File Coverage

blib/lib/Plosurin/SoyTree.pm
Criterion Covered Total %
statement 121 204 59.3
branch 0 22 0.0
condition 0 13 0.0
subroutine 42 58 72.4
pod n/a
total 163 297 54.8


line stmt bran cond sub pod time code
1             #===============================================================================
2             #
3             # DESCRIPTION: util for tree
4             #
5             # AUTHOR: Aliaksandr P. Zahatski, <zahatski@gmail.com>
6             #===============================================================================
7             =head1 NAME
8              
9             Plosurin::SoyTree - syntax tree
10              
11             =head1 SYNOPSIS
12              
13             my $plo = new Plosurin::SoyTree( src => $self->body );
14              
15             =head1 DESCRIPTION
16              
17             Plosurin::SoyTree - syntax tree
18              
19             =cut
20              
21             package Soy::Actions;
22 2     2   59917 use strict;
  2         5  
  2         58  
23 2     2   11 use warnings;
  2         5  
  2         52  
24 2     2   25 use v5.10;
  2         8  
25 2     2   9 use Data::Dumper;
  2         4  
  2         228  
26              
27             sub new {
28 0     0     my $class = shift;
29 0 0 0       bless( ( $#_ == 0 ) ? shift : {@_}, ref($class) || $class );
30             }
31              
32             sub content_ {
33 0     0     my $self = shift;
34 0           my ($a) = @_;
35              
36             # say Dumper( $a );
37             # say Dumper(\@_);
38             # @_
39 0           $a;
40             }
41             1;
42              
43             package Soy::base;
44 2     2   12 use Data::Dumper;
  2         3  
  2         886  
45              
46             sub new {
47 0     0     my $class = shift;
48 0 0 0       bless( ( $#_ == 0 ) ? shift : {@_}, ref($class) || $class );
49             }
50              
51              
52             sub attrs {
53 0     0     my $self = shift;
54 0   0       my $attr = $self->{attribute} || [];
55 0           my %attr = ();
56 0           foreach my $rec (@$attr) {
57 0           $attr{ $rec->{name} } = $rec->{value};
58             }
59 0           return \%attr;
60             }
61              
62             sub childs {
63 0     0     my $self = shift;
64 0 0         if (@_) {
65 0           $self->{content} = shift;
66             }
67 0 0         return [] unless exists $self->{content};
68 0           [ @{ $self->{content} } ];
  0            
69             }
70              
71 0     0     sub as_perl5 { die "$_[0]\-\>as_perl5 unimplemented " }
72              
73             sub dump {
74 0     0     my $self = shift;
75 0           my $childs = $self->childs;
76 0           my $res = {};
77 0 0         if ( scalar(@$childs) ) {
78             $res->{childs} = [
79             map {
80 0           { ref( $_->{obj} ) => $_->{obj}->dump }
81 0           } @$childs
82             ]
83             };
84 0 0         if (scalar( keys %{$self->attrs})) {
  0            
85 0           $res->{attrs} = $self->attrs;
86             }
87              
88 0           $res;
89              
90             }
91             1;
92              
93             package Soy::command_print;
94 2     2   17 use base 'Soy::base';
  2         4  
  2         823  
95             1;
96              
97             package Soy::expression;
98 2     2   16 use base 'Soy::base';
  2         5  
  2         442  
99             1;
100              
101             package Soy::raw_text;
102 2     2   14 use base 'Soy::base';
  2         4  
  2         570  
103              
104             sub as_perl5 {
105 0     0     my $self = shift;
106 0           my $str = $self->{''};
107 0           $str =~ s/\!/\\\!/g;
108 0           "\$res .=q!$str!;\n";
109             }
110             1;
111              
112             package Soy::command_elseif;
113 2     2   17 use base 'Soy::base';
  2         3  
  2         488  
114 2     2   20 use Data::Dumper;
  2         4  
  2         67  
115 2     2   9 use strict;
  2         3  
  2         38  
116 2     2   8 use warnings;
  2         5  
  2         143  
117              
118             sub dump {
119 0     0     my $self = shift;
120 0           return { %{ $self->SUPER::dump() },
121 0           expression => $self->{expression}->dump };
122             }
123             1;
124              
125             package Soy::command_call_self;
126 2     2   11 use base 'Soy::base';
  2         3  
  2         397  
127 2     2   13 use strict;
  2         2  
  2         44  
128 2     2   8 use warnings;
  2         4  
  2         36  
129 2     2   8 use Data::Dumper;
  2         4  
  2         464  
130              
131             sub as_perl5 {
132 0     0     my ( $self, $ctx ) = @_;
133 0           my $template = $self->{tmpl_name};
134 0           my $attr = $self->attrs;
135 0           my $tmpl = $ctx->get_template_by_name($template);
136 0   0       my $sub = $ctx->get_perl5_name($tmpl) || die "Not found template $template";
137 0 0         if ( scalar( @{ $self->childs } ) ) {
  0            
138 0           my $code = '';
139 0           my @ch = @{ $self->childs };
  0            
140 0           foreach my $p ( @{ $self->childs } ) {
  0            
141              
142             #check if childs id param
143 0 0 0       die "{call ... }{/call} can contain only {param}"
144             unless $p->isa('Soy::command_param') || $p->isa('Soy::Node');
145              
146             #now export
147 0           $code .= $p->as_perl5($ctx);
148             }
149             return
150 0           '$res .= &'
151             . $sub . '('
152             . $code
153             . '); # calling '
154             . $template . "\n";
155             }
156 0           return '$res .= &' . $sub . '(@_); # calling ' . $template . "\n";
157             }
158              
159             sub dump {
160 0     0     my $self = shift;
161 0           my $res = $self->SUPER::dump;
162 0           $res->{template} = $self->{tmpl_name};
163 0           $res;
164             }
165             1;
166              
167             package Soy::command_call;
168 2     2   17 use Plosurin::SoyTree;
  2         3  
  2         41  
169 2     2   8 use base 'Soy::command_call_self';
  2         4  
  2         481  
170 2     2   16 use strict;
  2         4  
  2         39  
171 2     2   8 use warnings;
  2         4  
  2         61  
172              
173             package Soy::command_else;
174 2     2   10 use base 'Soy::base';
  2         3  
  2         425  
175 2     2   12 use strict;
  2         3  
  2         34  
176 2     2   7 use warnings;
  2         4  
  2         75  
177             1;
178              
179             package Soy::command_if;
180 2     2   10 use base 'Soy::base';
  2         4  
  2         364  
181 2     2   12 use strict;
  2         4  
  2         35  
182 2     2   8 use warnings;
  2         3  
  2         35  
183 2     2   20 use v5.10;
  2         6  
184 2     2   8 use Data::Dumper;
  2         4  
  2         312  
185              
186             sub dump {
187 0     0     my $self = shift;
188 0           my %ifs = ();
189             $ifs{'if'} =
190 0           { %{ $self->SUPER::dump }, expression => $self->{expression}->dump, };
  0            
191 0 0         if ( exists $self->{commands_elseif} ) {
192 0           my $elseifs = $self->{commands_elseif};
193             $ifs{elseif} = [
194             map {
195 0           { ref($_) => $_->dump }
  0            
196             } @$elseifs
197             ];
198              
199             }
200 0 0         if ( my $elseif = $self->{command_else} ) {
201              
202 0           $ifs{else} = { ref($elseif) => $elseif->dump() };
203             }
204              
205 0           \%ifs;
206             }
207             1;
208              
209             package Soy::command_param;
210 2     2   12 use base 'Soy::base';
  2         4  
  2         514  
211 2     2   14 use warnings;
  2         4  
  2         44  
212 2     2   8 use strict;
  2         15  
  2         28  
213 2     2   12 use Data::Dumper;
  2         3  
  2         289  
214              
215             sub as_perl5 {
216 0     0     my $self = shift;
217              
218             # my $ctx = shift;
219             #die Dumper($self);
220             #die $self->childs
221 0           my $str = join ' . ', map { $_->as_perl5(@_) } @{ $self->childs };
  0            
  0            
222 0           return qq!'$self->{name}' => $str!;
223             }
224              
225             sub dump {
226 0     0     my $self = shift;
227 0           my %res = ( %{ $self->SUPER::dump() }, name => $self->{name}, );
  0            
228 0 0         $res{value} = $self->{value} if exists $self->{value};
229 0           \%res;
230             }
231              
232             package Soy::command_param_self;
233 2     2   11 use base 'Soy::command_param';
  2         4  
  2         476  
234              
235             package Soy::Node;
236 2     2   16 use base 'Soy::base';
  2         4  
  2         512  
237              
238             sub childs {
239 0     0     [ $_[0]->{obj} ];
240             }
241              
242             sub as_perl5 {
243 0     0     my $self = shift;
244 0           return $self->{obj}->as_perl5(@_);
245             }
246              
247             package Soy::command_import;
248 2     2   27 use strict;
  2         4  
  2         50  
249 2     2   9 use warnings;
  2         4  
  2         50  
250 2     2   12 use base 'Soy::base';
  2         4  
  2         417  
251             1;
252             package Plosurin::SoyTree;
253 2     2   11 use strict;
  2         4  
  2         37  
254 2     2   6 use warnings;
  2         4  
  2         38  
255 2     2   21 use v5.10;
  2         6  
256 2     2   8 use Data::Dumper;
  2         4  
  2         72  
257 2     2   1145 use Plosurin::Grammar;
  0            
  0            
258             use Regexp::Grammars;
259              
260             =head2 new
261              
262             my $st = new Plosurin::SoyTree( src => "txt");
263             my $tree = $stree->parse( "text")
264              
265             =cut
266              
267             sub new {
268             my $class = shift;
269             my $self = bless( ( $#_ == 0 ) ? shift : {@_}, ref($class) || $class );
270             if ( my $src = $self->{src} ) {
271             unless ( $self->{_tree} = $self->parse($src) ) { return $self->{_tree} }
272             }
273             $self;
274             }
275              
276             =head2 parse
277              
278             return [node1, node2]
279              
280             =cut
281              
282             sub parse {
283             my $self = shift;
284             my $str = shift || return [];
285             my $q = shift || qr{
286             <extends: Plosurin::Grammar>
287             # <debug:step>
288             \A <[content]>* \Z
289             }xms;
290             if ( $str =~ $q->with_actions( new Soy::Actions:: ) ) {
291             return {%/};
292             }
293             else {
294             "bad template";
295             }
296             }
297              
298             =head2 raw
299              
300             return syntax tree
301              
302             =cut
303              
304             sub raw_tree {
305             $_[0]->{_tree} || {};
306             }
307              
308             =head2 reduce_tree
309              
310             Union raw_text nodes
311              
312             =cut
313              
314             sub reduced_tree {
315             my $self = shift;
316             my $tree = shift || $self->raw_tree->{content} || return [];
317             my @res = ();
318             my @tmp = @$tree; #copy for protect from modify orig tree
319             while ( my $node = shift @tmp ) {
320              
321             #skip first node
322             #skip all non text nodes
323             if ( ref( $node->{obj} ) ne 'Soy::raw_text' || scalar(@res) == 0 ) {
324             ## if ( my $sub_tree = $node->{obj}->childs ) {
325             ## $node->{obj}->childs( $self->reduced_tree($sub_tree) );
326             ###### $self->reduced_tree($sub_tree);
327             # }
328             push @res, $node;
329             next;
330             }
331             my $prev = pop @res;
332             unless ( ref( $prev->{obj} ) eq 'Soy::raw_text' ) {
333             push @res, $prev;
334             }
335             else {
336              
337             #now union !
338             $node->{obj} = Soy::raw_text->new(
339             { '' => $prev->{obj}->{''} . $node->{obj}->{''} } );
340             $node->{matchline} = $prev->{matchline};
341             $node->{matchpos} = $node->{matchpos};
342             }
343             push @res, $node;
344             }
345             \@res;
346             }
347              
348             =head2 dump_tree($obj1 [, $objn])
349              
350             Minimalistic tree
351             return [ "clasname", {key1=>key2} ]
352              
353             =cut
354              
355             sub dump_tree {
356             my $self = shift;
357             my @res = ();
358             foreach my $rec ( @{ shift || [] } ) {
359             my $obj = $rec->{obj};
360             push @res, { ref($obj) => $obj->dump() };
361             }
362             \@res;
363             }
364             1;
365             __END__
366              
367             =head1 SEE ALSO
368              
369             Closure Templates Documentation L<http://code.google.com/closure/templates/docs/overview.html>
370              
371             Perl 6 implementation L<https://github.com/zag/plosurin>
372              
373              
374             =head1 AUTHOR
375              
376             Zahatski Aliaksandr, <zag@cpan.org>
377              
378             =head1 COPYRIGHT AND LICENSE
379              
380             Copyright (C) 2011 by Zahatski Aliaksandr
381              
382             This library is free software; you can redistribute it and/or modify
383             it under the same terms as Perl itself.
384              
385             =cut
386