File Coverage

blib/lib/DTL/Fast/Parser.pm
Criterion Covered Total %
statement 66 66 100.0
branch 18 20 90.0
condition 11 22 50.0
subroutine 11 11 100.0
pod 0 4 0.0
total 106 123 86.1


line stmt bran cond sub pod time code
1             package DTL::Fast::Parser;
2 98     98   34635 use strict;
  98         988  
  98         3351  
3 98     98   1180 use warnings FATAL => 'all';
  98         889  
  98         3661  
4 98     98   1147 use parent 'DTL::Fast::Renderer';
  98         172  
  98         1308  
5              
6 98     98   33189 use DTL::Fast::Expression;
  98         277  
  98         3165  
7 98     98   30915 use DTL::Fast::Text;
  98         258  
  98         2435  
8 98     98   647 use DTL::Fast::Template;
  98         195  
  98         1732  
9 98     98   1282 use DTL::Fast qw(count_lines);
  98         191  
  98         58534  
10              
11             sub new
12             {
13 1805     1805 0 5949 my ( $proto, %kwargs ) = @_;
14              
15             die $proto->get_parse_error('no directory arrays passed into constructor')
16             if (not $kwargs{dirs}
17 1805 50 33     9342 or ref $kwargs{dirs} ne 'ARRAY')
18             ;
19              
20             die $proto->get_parse_error('no raw chunks array passed into constructor')
21             if (not $kwargs{raw_chunks}
22 1805 50 33     7572 or ref $kwargs{raw_chunks} ne 'ARRAY')
23             ;
24              
25 1805   50     7614 $kwargs{safe} //= 0;
26              
27 1805         7015 my $self = $proto->SUPER::new(%kwargs)->parse_chunks();;
28              
29 1749         3568 delete @{$self}{raw_chunks};
  1749         3601  
30              
31 1749         5083 return $self;
32             }
33              
34             sub parse_chunks
35             {
36 1790     1790 0 3135 my ( $self ) = @_;
37 1790         2731 while( scalar @{$self->{raw_chunks}} )
  8460         18836  
38             {
39 6711         13307 $self->add_chunk( $self->parse_next_chunk());
40             }
41 1749         3373 return $self;
42             }
43              
44             sub parse_next_chunk
45             {
46 6501     6501 0 10018 my ( $self ) = @_;
47              
48 6501         8437 my $chunk = shift @{$self->{raw_chunks}};
  6501         11096  
49 6501         14161 my $chunk_lines = count_lines($chunk);
50              
51 6501 100       32265 if (
    100          
    100          
    100          
52             $chunk =~ /^
53             \{\{\s* # open sequence
54             ([^\s].*?) # variable name or value $1
55             \s*\}\} # close sequence
56             $/xs
57             )
58             {
59 638 100       2065 if ($1 eq 'block.super')
60             {
61 1         7 require DTL::Fast::Tag::BlockSuper;
62             $chunk = DTL::Fast::Tag::BlockSuper->new(
63             ''
64             , dirs => $self->{dirs}
65 1         6 , _open_tag_lines => $chunk_lines
66             );
67             }
68             else
69             {
70 637         2366 $chunk = DTL::Fast::Variable->new($1);
71 637         1113 $DTL::Fast::Template::CURRENT_TEMPLATE_LINE += $chunk_lines;
72             }
73             }
74             elsif
75             (
76             $chunk =~ /^
77             \{\%\s* # open sequence
78             ([^\s]+?) # tag keyword $1
79             (?:
80             \s+ # spaces
81             (.*?) # parameters $2
82             )?
83             \s*\%\} # close sequence
84             $/xs
85             )
86             {
87 2423         8910 $chunk = $self->parse_tag_chunk(lc $1, $2, $chunk_lines);
88             }
89             elsif
90             (
91             $chunk =~ /^\{\#.*\#\}$/s
92             )
93             {
94 2         4 $DTL::Fast::Template::CURRENT_TEMPLATE_LINE += $chunk_lines;
95 2         5 $chunk = undef;
96             }
97             elsif ($chunk ne '')
98             {
99 2364         6465 $chunk = DTL::Fast::Text->new( $chunk);
100 2364         3848 $DTL::Fast::Template::CURRENT_TEMPLATE_LINE += $chunk_lines;
101             }
102             else
103             {
104 1074         1706 $chunk = undef;
105             }
106              
107 6460         16697 return $chunk;
108             }
109              
110             sub parse_tag_chunk
111             {
112 849     849 0 2193 my ( $self, $tag_name, $tag_param, $chunk_lines ) = @_;
113              
114 849         1384 my $result = undef;
115              
116             # dynamic module loading
117 849 100 66     2479 if (
118             not exists $DTL::Fast::TAG_HANDLERS{$tag_name}
119             and exists $DTL::Fast::KNOWN_TAGS{$tag_name}
120             )
121             {
122 53         16084 require Module::Load;
123 53         27671 Module::Load::load($DTL::Fast::KNOWN_TAGS{$tag_name});
124 53         789 $DTL::Fast::LOADED_MODULES{$DTL::Fast::KNOWN_TAGS{$tag_name}} = time;
125             }
126              
127             # handling tag
128 849 100       1760 if (exists $DTL::Fast::TAG_HANDLERS{$tag_name})
129             {
130             $result = $DTL::Fast::TAG_HANDLERS{$tag_name}->new(
131             $tag_param
132             , raw_chunks => $self->{raw_chunks}
133             , dirs => $self->{dirs}
134 843         3728 , _open_tag_lines => $chunk_lines
135             );
136             }
137             else # not found
138             {
139 6         26 my $full_tag_name = join ' ', grep $_, ($tag_name, $tag_param);
140              
141 6 100 66     94 if (# block tag parsing error
142             $self->isa('DTL::Fast::Tag')
143             and not $self->isa('DTL::Fast::Tag::Simple')
144             )
145             {
146 2   50     46 warn $self->get_parse_warning(
      50        
147             sprintf( 'unknown tag {%% %s %%}', $full_tag_name )
148             , 'Possible reasons' => sprintf( <<'_EOM_'
149             typo in tag name
150             duplicated close tag {%% %1$s %%}
151             unopened close tag {%% %1$s %%}
152             undisclosed block tag %3$s
153             _EOM_
154             , $tag_name // 'undef'
155             , $DTL::Fast::Template::CURRENT_TEMPLATE_LINE // 'unknown'
156             , $self->open_tag_syntax_with_line_number()
157             )
158             );
159             }
160             else # template parsing error
161             {
162 4   50     63 warn $self->get_parse_warning(
      50        
163             sprintf( 'unknown tag {%% %s %%}', $full_tag_name )
164             , 'Possible reasons' => sprintf( <<'_EOM_'
165             typo, duplicated or unopened close tag {%% %1$s %%} at line %2$s
166             _EOM_
167             , $tag_name // 'undef'
168             , $DTL::Fast::Template::CURRENT_TEMPLATE_LINE // 'unknown'
169             )
170             );
171             }
172              
173 6         49 $DTL::Fast::Template::CURRENT_TEMPLATE_LINE += $chunk_lines;
174              
175 6         26 $result = DTL::Fast::Text->new();
176             }
177              
178 809         1818 return $result;
179             }
180              
181             1;