File Coverage

blib/lib/Dotiac/DTL/Parser.pm
Criterion Covered Total %
statement 93 102 91.1
branch 28 44 63.6
condition 10 19 52.6
subroutine 5 5 100.0
pod 3 3 100.0
total 139 173 80.3


line stmt bran cond sub pod time code
1             ###############################################################################
2             #Parser.pm
3             #Last Change: 2009-01-19
4             #Copyright (c) 2009 Marc-Seabstian "Maluku" Lucksch
5             #Version 0.8
6             ####################
7             #This file is part of the Dotiac::DTL project.
8             #http://search.cpan.org/perldoc?Dotiac::DTL
9             #
10             #Parser.pm is published under the terms of the MIT license, which basically
11             #means "Do with it whatever you want". For more information, see the
12             #license.txt file that should be enclosed with libsofu distributions. A copy of
13             #the license is (at the time of writing) also available at
14             #http://www.opensource.org/licenses/mit-license.php .
15             ###############################################################################
16            
17             package Dotiac::DTL::Parser;
18             require Dotiac::DTL::Tag;
19             require Dotiac::DTL::Variable;
20             require Dotiac::DTL::Comment;
21             require Dotiac::DTL::Tag::autoescape;
22             require Dotiac::DTL::Tag::block;
23             require Dotiac::DTL::Tag::extends;
24             require Dotiac::DTL::Tag::comment;
25             require Dotiac::DTL::Tag::cycle;
26             require Dotiac::DTL::Tag::debug;
27             require Dotiac::DTL::Tag::filter;
28             require Dotiac::DTL::Tag::firstof;
29             require Dotiac::DTL::Tag::for;
30             require Dotiac::DTL::Tag::if;
31             require Dotiac::DTL::Tag::ifequal;
32             require Dotiac::DTL::Tag::ifnotequal;
33             require Dotiac::DTL::Tag::ifchanged;
34             require Dotiac::DTL::Tag::include;
35             require Dotiac::DTL::Tag::load;
36             require Dotiac::DTL::Tag::now;
37             require Dotiac::DTL::Tag::regroup;
38             require Dotiac::DTL::Tag::spaceless;
39             require Dotiac::DTL::Tag::ssi;
40             require Dotiac::DTL::Tag::templatetag;
41             require Dotiac::DTL::Tag::url;
42             require Dotiac::DTL::Tag::widthratio;
43             require Dotiac::DTL::Tag::with;
44            
45             our $VERSION = 0.8;
46            
47 11     11   64 use strict;
  11         20  
  11         409  
48 11     11   58 use warnings;
  11         15  
  11         14635  
49            
50             sub new {
51 123     123 1 317 my $class=shift;
52 123         292 my $self={};
53 123         380 bless $self,$class;
54 123         394 return $self;
55             }
56            
57             sub unparsed {
58 6     6 1 45 my $self=shift;
59 6         9 my $template=shift;
60 6         9 my $pos=shift;
61 6         9 my $start=$$pos;
62 6         29 my @end = @_;
63 6         12 my $found;
64             my $starttag;
65 6 50       18 $found=shift @end if @end;
66 6 50       17 $starttag=shift @end if @end;
67 6         6 my @starttag;
68 6 50 33     42 @starttag = ($starttag) if $starttag and not ref $starttag;
69 6 50 33     32 @starttag = @{$starttag} if $starttag and ref $starttag eq "ARRAY";
  0         0  
70 6         6 my $text;
71 6         7 local $_;
72 6         10 while (1) {
73 20         29 my $p = index($$template,"{",$$pos);
74 20 50       98 if ($p >=0) {
75 20         24 $$pos=$p+1;
76 20         31 my $n = substr $$template,$$pos,1;
77 20 100       45 if ($n eq "%") {
78 8         17 my $text .= substr $$template,$start,$$pos-$start-1;
79 8         16 my $npos = index($$template,"%}",++$$pos);
80 8 50       18 die "Missing closing %} at char $$pos" if $npos < 0;
81 8         14 my $cont=substr $$template,$$pos,$npos-$$pos;
82 8         12 $$pos=$npos+2;
83 8         10 my $c=$cont;
84 8         29 $cont=~s/^\s+//;
85 8         26 $cont=~s/\s+$//;
86 8         20 my ($tagname,$param) = split /\s+/,$cont,2;
87 8         13 $tagname=lc $tagname;
88 8 100 50     25 $$found = $c and return $text if $found and grep {$_ eq $tagname} @end;
  8   66     1232  
89 2         6 $text .= "{\%$c\%}";
90 2 50 33     9 $text .= $self->unparsed($template,$pos,@_) if $found and grep {$_ eq $tagname} @starttag;
  2         24  
91 2         7 $text .="{\%$$found\%}";
92 2         5 $$found="";
93             }
94             }
95             else {
96 0         0 $$pos=length $$template;
97 0         0 return $text
98             }
99             }
100             }
101            
102            
103             sub parse {
104 699     699 1 939 my $self=shift;
105 699         1045 my $template=shift;
106 699         858 my $pos=shift;
107 699         989 my $start=$$pos;
108 699         1177 my @end = @_;
109 699         823 my $found;
110 699 100       1637 $found=shift @end if @end;
111 699         931 local $_;
112 699         1809 while ($Dotiac::DTL::PARSER eq __PACKAGE__) {
113 699         1263 my $p = index($$template,"{",$$pos);
114 699 100       1351 if ($p >=0) {
115 576         767 $$pos=$p+1;
116 576         1164 my $n = substr $$template,$$pos,1;
117 576 100       1300 if ($n eq "%") {
    100          
    50          
118 303         640 my $pre = substr $$template,$start,$$pos-$start-1;
119 303         549 my $npos = index($$template,"%}",++$$pos);
120 303 50       583 die "Missing closing %} at char $$pos" if $npos < 0;
121 303         968 my $cont=substr $$template,$$pos,$npos-$$pos;
122 303         450 $$pos=$npos+2;
123 303         1239 $cont=~s/^\s+//;
124 303         1171 $cont=~s/\s+$//;
125 303         845 my ($tagname,$param) = split /\s+/,$cont,2;
126 303         614 $tagname=lc $tagname;
127 303 100 50     961 $$found = $tagname and return Dotiac::DTL::Tag->new($pre) if $found and grep {$_ eq $tagname} @end;
  270   100     1595  
128 163         316 my $r;
129 163         209 eval {$r="Dotiac::DTL::Tag::$tagname"->new($pre,$param,$self,$template,$pos);};
  163         1406  
130 163 50       476 if ($@) {
131 0         0 die "Error while loading Tag '$tagname' from Dotiac::DTL::Tag::$tagname. If this is an endtag (like endif) then your template is unbalanced\n$@";
132             }
133             #print "\n\nold: $npos, new $$pos, lenght=".length $$template and die if $tagname eq "extends";
134             #warn $$pos," ",length $$template,"\n";
135 163 100       411 if ($$pos >= length $$template) {
136 2         9 $r->next(Dotiac::DTL::Tag->new(""));
137             }
138             else {
139 161         570 $r->next($self->parse($template,$pos,@_));
140             }
141 163         1267 return $r;
142            
143             }
144             elsif ($n eq "{") {
145 267         607 my $pre = substr $$template,$start,$$pos-$start-1;
146 267         475 my $npos = index($$template,"}}",++$$pos);
147 267 50       492 die "Missing closing }} at char $$pos" if $npos < 0;
148 267         596 my $cont=substr $$template,$$pos,$npos-$$pos;
149 267         332 $$pos=$npos+2;
150 267         941 return Dotiac::DTL::Variable->new($pre,$cont,$self->parse($template,$pos,@_));
151             }
152             elsif ($n eq "#") {
153 6         14 my $pre = substr $$template,$start,$$pos-$start-1;
154 6         13 my $npos = index($$template,"#}",++$$pos);
155 6 50       15 die "Missing closing #} at char $$pos" if $npos < 0;
156 6         16 my $cont=substr $$template,$$pos,$npos-$$pos;
157 6         9 $$pos=$npos+2;
158 6         52 return Dotiac::DTL::Comment->new($pre,$cont,$self->parse($template,$pos,@_));
159             }
160             }
161             else {
162 123         309 $$pos=length $$template;
163 123         637 return Dotiac::DTL::Tag->new(substr $$template,$start);
164             }
165             }
166 0           my $parser=$Dotiac::DTL::PARSER->new();
167 0           my @args=($template,$pos);
168 0 0         push @args,$found if $found;
169 0 0         push @args,@end if @end;
170 0           return $parser->parse(@args);
171             }
172            
173             1;
174             __END__