File Coverage

blib/lib/HTML/YaTmpl/_parse.pm
Criterion Covered Total %
statement 56 57 98.2
branch 9 10 90.0
condition n/a
subroutine 6 6 100.0
pod n/a
total 71 73 97.2


line stmt bran cond sub pod time code
1             package HTML::YaTmpl;
2 6     6   33 use strict;
  6         9  
  6         169  
3 6     6   28 use warnings;
  6         11  
  6         145  
4 6     6   26 no warnings 'uninitialized';
  6         10  
  6         215  
5 6     6   32 use Config;
  6         86  
  6         575  
6              
7             our $VERSION='1.0';
8              
9             sub _parse {
10 241     241   313 my $I=shift;
11 241         315 my $str=shift;
12 241 50       543 $str=$I->template unless( defined $str );
13              
14 6     6   32 use re 'eval';
  6         18  
  6         10875  
15              
16 241         251 my $regexp;
17 241         797 my $re_nostr=qr{
18             (?: # between <: and /> can be written perl code
19             [^\s\w/]> # but perl knows the -> operator. Originally
20             | # this (?:...) was written simply as [^"<>]
21             # and <:$p->{xxx}/> was matched as $1=':',
22             # $2='', $3='$p-' and not as $3='$p->{xxx}'
23             # as expected. Now a character other than \s,
24             # \w or / acts like an escape character for a
25             # subsequent >.
26             /(?!>)
27             |
28             \\.
29             |
30             [^"<>/] # "]# kein string
31             )*
32             }xs;
33              
34 241         608 my $re_isstr=qr{
35             " #"# string start
36             (?: #
37             \\. # escaped character
38             |
39             [^"\\] #"]# other character
40             )*
41             " #"# string ende
42             }xs;
43              
44 241         8244 my $re_tparam=qr{
45             $re_nostr
46             (?:
47             $re_isstr
48             $re_nostr
49             )*?
50             }xs;
51              
52             $regexp=qr{
53             # (?{
54             # my $pos=pos;
55             # my $prev=substr($str, $pos>=10?$pos-10:0, $pos>=10?10:$pos);
56             # my $post=substr($str, $pos, 10);
57             # print "start at position ",pos,": $prev^$post\n";
58             # })
59             <([=:\043]) # [=:#] goes to $1
60             (\w*) # TAG to $2
61 762         5363 ($re_tparam) # tag params go to $3
62             (?:
63             (?> /> )
64             |
65             (?>
66             >
67             ( # the section content goes to $4
68             (?: # we are looking for a character
69             (?> [^<]+ ) # that is not the beginning of a TAG
70             | # or
71             (?>
72             (??{$regexp}) # we are looking for something that is
73             ) # described by $regexp
74             | # or
75             <(?! # is the beginning of a TAG but not followed
76             (?> # by the rest of an opening or closing TAG
77             \1\2 $re_tparam
78             |
79             /\1\2
80             )> )
81             )*? # and that many times
82             )
83             # the closing TAG
84             ))
85             # (?{
86             # my $pos=pos;
87             # my $prev=substr($str, $pos-10, 10);
88             # my $post=substr($str, $pos, 10);
89             # print "emitted at position ",pos,": $prev^$post\n";
90             # })
91 241         104068 }xs;
92              
93 241         3054 my $sreg=qr{(?:
94             \\.
95             |
96             [^"\s] #"]# kein string oder space
97             |
98             (?:$re_isstr) # "#
99             )+
100             }xs;
101              
102 241         1843 my $kreg=qr{(?:
103             \\.
104             |
105             [^"\s=] #"]# kein string oder space
106             |
107             (?:$re_isstr)
108             )+
109             }xs;
110              
111 241         340 my $vreg=$sreg;
112              
113 241         2143 my $xreg=qr{^($kreg) = ($vreg)$}xs;
114              
115              
116             # real start of code
117              
118 241         410 my ($id, $tag, $tparam, $tbody, $chunk);
119 0         0 my @res;
120              
121             #print "\nparse($str)\n";
122 241         336 my $start=0;
123 241         3741 while( $str=~/$regexp/g ) {
124 311         1367 ($id, $tag, $tparam, $tbody)=($1,$2,$3,$4);
125 311         1610 $chunk=substr( $str, $-[0], $+[0]-$-[0] );
126 311 100       1344 if( $start!=$-[0] ) {
127 214         867 push @res, [undef, 'text', undef, undef,
128             substr( $str, $start, $-[0]-$start )];
129             }
130 311         953 $start=$+[0];
131 311 100       1104 next if( $id eq '#' ); # skip comments
132 279         490 my $p=[];
133              
134             #print "id='$id'\n";
135             #print "tag='$tag'\n";
136             #print "tparam='$tparam'\n";
137             #print "tbody='$tbody'\n";
138              
139 279         408 my $pstr=$tparam;
140 279         690 $pstr=~s/^\s+//;
141 279         612 $pstr=~s/\s+$//;
142             #$pstr=~s/\\(.)/$1/g;
143 279         1025 push @res, [$id, $tag, $p, $tbody, $chunk, $pstr];
144 279         377 local $_;
145 279         2981 push @{$p}, map {
  251         1780  
146             #warn "_=$_\n";
147 279         320 my @l=/$xreg/; @l ? [do {
  109         352  
148 142         180 local $_;
149 284         1132 map {
150 142         211 s/\\(.)|"/$1/g; #";#
151 284         1807 $_;
152             } @l;
153 251 100       560 }] : do {s/\\(.)|"/$1/g;$_}} $tparam=~/$sreg/g; #"}};#
  109         873  
154             }
155 241 100       586 if( $start!=length($str) ) {
156 171         563 push @res, [undef, 'text', undef, undef, substr( $str, $start )];
157             }
158              
159             #use Data::Dumper; warn Dumper(\@res);
160 241         2553 return @res;
161             }
162              
163             1;