line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#!perl --
|
2
|
|
|
|
|
|
|
package Text::Template::Compact;
|
3
|
4
|
|
|
4
|
|
47014
|
use utf8;
|
|
4
|
|
|
|
|
22
|
|
|
4
|
|
|
|
|
84
|
|
4
|
4
|
|
|
4
|
|
92
|
use strict;
|
|
4
|
|
|
|
|
12
|
|
|
4
|
|
|
|
|
106
|
|
5
|
4
|
|
|
4
|
|
34
|
use warnings;
|
|
4
|
|
|
|
|
14
|
|
|
4
|
|
|
|
|
141
|
|
6
|
4
|
|
|
4
|
|
1453
|
use Encode;
|
|
4
|
|
|
|
|
26136
|
|
|
4
|
|
|
|
|
255
|
|
7
|
4
|
|
|
4
|
|
32
|
use Carp;
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
2331
|
|
8
|
|
|
|
|
|
|
our $VERSION = "0.1.12";
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
sub getDataType($){
|
11
|
|
|
|
|
|
|
# return empty string if not reference type.
|
12
|
1446
|
100
|
|
1446
|
0
|
3841
|
return '' if not ref $_[0];
|
13
|
|
|
|
|
|
|
# use scalar to avoid bless.
|
14
|
1444
|
|
|
|
|
5385
|
$_[0]=~/(\w+)\(/;
|
15
|
1444
|
|
|
|
|
4263
|
return $1;
|
16
|
|
|
|
|
|
|
}
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
# decode "quoted" string to plain.
|
19
|
|
|
|
|
|
|
sub decodeQuote{
|
20
|
686
|
50
|
33
|
686
|
0
|
3044
|
return if not @_ or not defined $_[0];
|
21
|
686
|
100
|
|
|
|
2803
|
return $_[0] if not $_[0] =~ /^"/;
|
22
|
226
|
|
|
|
|
655
|
my $r = substr($_[0],1,length($_[0])-2);
|
23
|
226
|
|
|
|
|
519
|
$r =~ s/""/"/g;
|
24
|
226
|
|
|
|
|
940
|
return $r;
|
25
|
|
|
|
|
|
|
}
|
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
# defined or ...
|
28
|
|
|
|
|
|
|
sub dor{
|
29
|
866
|
100
|
|
866
|
0
|
1774
|
for(@_){ defined($_) and return $_;}
|
|
1260
|
|
|
|
|
3755
|
|
30
|
1
|
|
|
|
|
4
|
return;
|
31
|
|
|
|
|
|
|
}
|
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# filter for variable expansion
|
34
|
|
|
|
|
|
|
our %filter_map =(
|
35
|
|
|
|
|
|
|
raw => sub{
|
36
|
|
|
|
|
|
|
return $_[0];
|
37
|
|
|
|
|
|
|
},
|
38
|
|
|
|
|
|
|
html => sub{
|
39
|
|
|
|
|
|
|
my $a = $_[0];
|
40
|
|
|
|
|
|
|
$a =~ s/&/&/g;
|
41
|
|
|
|
|
|
|
$a =~ s/</g;
|
42
|
|
|
|
|
|
|
$a =~ s/>/>/g;
|
43
|
|
|
|
|
|
|
$a =~ s/"/"/g;
|
44
|
|
|
|
|
|
|
$a =~ s/'/'/g;
|
45
|
|
|
|
|
|
|
$a =~ s/\n/ \n/g;
|
46
|
|
|
|
|
|
|
return $a;
|
47
|
|
|
|
|
|
|
},
|
48
|
|
|
|
|
|
|
nobr => sub{
|
49
|
|
|
|
|
|
|
my $a = $_[0];
|
50
|
|
|
|
|
|
|
$a =~ s/&/&/g;
|
51
|
|
|
|
|
|
|
$a =~ s/</g;
|
52
|
|
|
|
|
|
|
$a =~ s/>/>/g;
|
53
|
|
|
|
|
|
|
$a =~ s/"/"/g;
|
54
|
|
|
|
|
|
|
$a =~ s/'/'/g;
|
55
|
|
|
|
|
|
|
return $a;
|
56
|
|
|
|
|
|
|
},
|
57
|
|
|
|
|
|
|
uri => sub{
|
58
|
|
|
|
|
|
|
my $a = Encode::encode('utf8',$_[0]);
|
59
|
|
|
|
|
|
|
$a =~ s/([^a-zA-Z0-9_.!~*'()-])/'%' . unpack('H2', $1)/eg;
|
60
|
|
|
|
|
|
|
return $a;
|
61
|
|
|
|
|
|
|
},
|
62
|
|
|
|
|
|
|
);
|
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
{
|
65
|
|
|
|
|
|
|
package Text::Template::Compact::ExprParser;
|
66
|
4
|
|
|
4
|
|
29
|
use Carp;
|
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
838
|
|
67
|
|
|
|
|
|
|
our @ExprOperator;
|
68
|
|
|
|
|
|
|
our %ExprOperator;
|
69
|
|
|
|
|
|
|
our $token_re;
|
70
|
|
|
|
|
|
|
our $dataset;
|
71
|
|
|
|
|
|
|
our $list_op_prio;
|
72
|
|
|
|
|
|
|
{
|
73
|
|
|
|
|
|
|
my $prio=0;
|
74
|
|
|
|
|
|
|
for(
|
75
|
|
|
|
|
|
|
# 優先順序が同じ場合の結合順序: L=左結合((a+b)+c) R=右結合(a=(b=c)) _=非結合
|
76
|
|
|
|
|
|
|
# 演算子の見た目:
|
77
|
|
|
|
|
|
|
# b (braket) (a) のような外見,
|
78
|
|
|
|
|
|
|
# l (left) 左側の単項演算子。 +num
|
79
|
|
|
|
|
|
|
# a (array) a[b] のような外見,
|
80
|
|
|
|
|
|
|
# r (right) 右側の単項演算子。 num++
|
81
|
|
|
|
|
|
|
# m (middle) 二項演算子 a ** b
|
82
|
|
|
|
|
|
|
# t (tri) 三項演算子 a?b:c
|
83
|
|
|
|
|
|
|
# k (keyword) 二項演算子 a.keyword 演算子の右側に式ではなくキーワードが入る
|
84
|
|
|
|
|
|
|
# c (const) 定数
|
85
|
|
|
|
|
|
|
# K (const) キーワード
|
86
|
|
|
|
|
|
|
# 優先順序の区切り: []
|
87
|
|
|
|
|
|
|
['Lb','(',1,sub{ return $_[0];},')'],
|
88
|
|
|
|
|
|
|
['La','(',1,sub{
|
89
|
|
|
|
|
|
|
# find list operator
|
90
|
|
|
|
|
|
|
my $key = $dataset->getV($_[0]);
|
91
|
|
|
|
|
|
|
my $op = findOp($key,qr/l/);
|
92
|
|
|
|
|
|
|
$op or return $dataset->encode("[Error: $op() is not found]");
|
93
|
|
|
|
|
|
|
return $op->{_eval}->($_[1]);
|
94
|
|
|
|
|
|
|
},')'],
|
95
|
|
|
|
|
|
|
[],
|
96
|
|
|
|
|
|
|
['Lk','.',2,sub{ return $dataset->child($_[0],$_[1] ) } ],
|
97
|
|
|
|
|
|
|
['La','[',2,sub{ return $dataset->child($_[0],$dataset->encode($dataset->getV($_[1]))) },']' ],
|
98
|
|
|
|
|
|
|
[],
|
99
|
4
|
|
|
4
|
|
27
|
['_l','++',1,sub{ no warnings; my $v= $dataset->getV($_[0]); $dataset->setV($_[0],++$v); return $dataset->encode( $v);} ],
|
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
366
|
|
100
|
4
|
|
|
4
|
|
30
|
['_l','--',1,sub{ no warnings; my $v= $dataset->getV($_[0]); $dataset->setV($_[0],--$v); return $dataset->encode( $v);} ],
|
|
4
|
|
|
|
|
14
|
|
|
4
|
|
|
|
|
242
|
|
101
|
4
|
|
|
4
|
|
22
|
['_r','++',1,sub{ no warnings; my $v= $dataset->getV($_[0]); $dataset->setV($_[0],++$v); return $dataset->encode(--$v);} ],
|
|
4
|
|
|
|
|
14
|
|
|
4
|
|
|
|
|
228
|
|
102
|
4
|
|
|
4
|
|
36
|
['_r','--',1,sub{ no warnings; my $v= $dataset->getV($_[0]); $dataset->setV($_[0],--$v); return $dataset->encode(++$v);} ],
|
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
270
|
|
103
|
|
|
|
|
|
|
[],
|
104
|
4
|
|
|
4
|
|
31
|
['Rm','**',2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0])**$dataset->getV($_[1])); } ],
|
|
4
|
|
|
|
|
16
|
|
|
4
|
|
|
|
|
221
|
|
105
|
|
|
|
|
|
|
[],
|
106
|
4
|
|
|
4
|
|
25
|
['Rl','!',1,sub{ no warnings; return $dataset->encode(!$dataset->getV($_[0]))} ],
|
|
4
|
|
|
|
|
12
|
|
|
4
|
|
|
|
|
189
|
|
107
|
4
|
|
|
4
|
|
24
|
['Rl','~',1,sub{ no warnings; return $dataset->encode(~(0+$dataset->getV($_[0])))} ],
|
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
185
|
|
108
|
4
|
|
|
4
|
|
29
|
['Rl','+',1,sub{ no warnings; return $dataset->encode(+$dataset->getV($_[0]))} ],
|
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
171
|
|
109
|
4
|
|
|
4
|
|
21
|
['Rl','-',1,sub{ no warnings; return $dataset->encode(-$dataset->getV($_[0]))} ],
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
182
|
|
110
|
|
|
|
|
|
|
[],
|
111
|
4
|
|
|
4
|
|
24
|
['Lm','*',2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0]) * $dataset->getV($_[1])) }],
|
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
208
|
|
112
|
4
|
|
|
4
|
|
21
|
['Lm','/',2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0]) / $dataset->getV($_[1])) }],
|
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
227
|
|
113
|
4
|
|
|
4
|
|
22
|
['Lm','%',2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0]) % $dataset->getV($_[1])) }],
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
198
|
|
114
|
4
|
|
|
4
|
|
22
|
['Lm','repeat',2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0]) x $dataset->getV($_[1])) }],
|
|
4
|
|
|
|
|
11
|
|
|
4
|
|
|
|
|
214
|
|
115
|
|
|
|
|
|
|
[],
|
116
|
4
|
|
|
4
|
|
22
|
['Lm','+',2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0]) + $dataset->getV($_[1])) } ],
|
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
220
|
|
117
|
4
|
|
|
4
|
|
21
|
['Lm','-',2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0]) - $dataset->getV($_[1])) } ],
|
|
4
|
|
|
|
|
16
|
|
|
4
|
|
|
|
|
234
|
|
118
|
4
|
|
|
4
|
|
27
|
['Lm','cat',2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0]) . $dataset->getV($_[1])) } ],
|
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
1144
|
|
119
|
|
|
|
|
|
|
[],
|
120
|
4
|
|
|
4
|
|
27
|
['Lm','<<',2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0]) << $dataset->getV($_[1])) } ],
|
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
259
|
|
121
|
4
|
|
|
4
|
|
24
|
['Lm','>>',2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0]) >> $dataset->getV($_[1])) } ],
|
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
401
|
|
122
|
|
|
|
|
|
|
[],
|
123
|
|
|
|
|
|
|
['_l','defined' ,1,sub{ return $dataset->encode( defined($dataset->getV($_[0])) ?1:0); }],
|
124
|
|
|
|
|
|
|
['_l','bool' ,1,sub{ return $dataset->encode($dataset->getV($_[0]) ?1:0); }],
|
125
|
4
|
|
|
4
|
|
21
|
['_l','nz' ,1,sub{ no warnings; return $dataset->encode($dataset->getV($_[0])!=0 ?1:0); }],
|
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
203
|
|
126
|
4
|
|
|
4
|
|
22
|
['_l','int' ,1,sub{ no warnings; return $dataset->encode(int $dataset->getV($_[0]) ); }],
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
954
|
|
127
|
|
|
|
|
|
|
['_l','length' ,1,sub{
|
128
|
|
|
|
|
|
|
my $v =$dataset->getV($_[0]);
|
129
|
|
|
|
|
|
|
defined($v) or return $dataset->encode(undef);
|
130
|
|
|
|
|
|
|
ref($v) or return $dataset->encode(length $v);
|
131
|
|
|
|
|
|
|
my $type = Text::Template::Compact::getDataType($v);
|
132
|
|
|
|
|
|
|
$type =~ /ARRAY/ and return $dataset->encode(scalar @$v);
|
133
|
|
|
|
|
|
|
$type =~ /HASH/ and return $dataset->encode(scalar keys %$v);
|
134
|
|
|
|
|
|
|
return $dataset->encode(length $v);
|
135
|
|
|
|
|
|
|
}],
|
136
|
|
|
|
|
|
|
['l','pop',1,sub{
|
137
|
|
|
|
|
|
|
my $ra = $dataset->getV($_[0]);
|
138
|
|
|
|
|
|
|
if(Text::Template::Compact::getDataType($ra) =~ /ARRAY/ ){
|
139
|
|
|
|
|
|
|
return $dataset->encode( pop @$ra );
|
140
|
|
|
|
|
|
|
}
|
141
|
|
|
|
|
|
|
return $dataset->encode( undef );
|
142
|
|
|
|
|
|
|
}],
|
143
|
|
|
|
|
|
|
['l','shift',1,sub{
|
144
|
|
|
|
|
|
|
my $ra = $dataset->getV($_[0]);
|
145
|
|
|
|
|
|
|
if(Text::Template::Compact::getDataType($ra) =~ /ARRAY/ ){
|
146
|
|
|
|
|
|
|
return $dataset->encode( shift @$ra );
|
147
|
|
|
|
|
|
|
}
|
148
|
|
|
|
|
|
|
return $dataset->encode( undef );
|
149
|
|
|
|
|
|
|
}],
|
150
|
|
|
|
|
|
|
[],
|
151
|
4
|
|
|
4
|
|
26
|
['_m','<' ,2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0]) < $dataset->getV($_[1])) }],
|
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
231
|
|
152
|
4
|
|
|
4
|
|
23
|
['_m','>' ,2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0]) > $dataset->getV($_[1])) }],
|
|
4
|
|
|
|
|
14
|
|
|
4
|
|
|
|
|
231
|
|
153
|
4
|
|
|
4
|
|
20
|
['_m','<=' ,2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0]) <= $dataset->getV($_[1])) }],
|
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
208
|
|
154
|
4
|
|
|
4
|
|
20
|
['_m','>=' ,2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0]) >= $dataset->getV($_[1])) }],
|
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
192
|
|
155
|
4
|
|
|
4
|
|
21
|
['_m','lt' ,2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0]) lt $dataset->getV($_[1])) }],
|
|
4
|
|
|
|
|
27
|
|
|
4
|
|
|
|
|
202
|
|
156
|
4
|
|
|
4
|
|
21
|
['_m','gt' ,2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0]) gt $dataset->getV($_[1])) }],
|
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
225
|
|
157
|
4
|
|
|
4
|
|
24
|
['_m','le' ,2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0]) le $dataset->getV($_[1])) }],
|
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
218
|
|
158
|
4
|
|
|
4
|
|
21
|
['_m','ge' ,2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0]) ge $dataset->getV($_[1])) }],
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
217
|
|
159
|
|
|
|
|
|
|
[],
|
160
|
4
|
|
|
4
|
|
24
|
['_m','==' ,2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0]) == $dataset->getV($_[1])) }],
|
|
4
|
|
|
|
|
21
|
|
|
4
|
|
|
|
|
229
|
|
161
|
4
|
|
|
4
|
|
22
|
['_m','!=' ,2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0]) != $dataset->getV($_[1])) }],
|
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
211
|
|
162
|
4
|
|
|
4
|
|
20
|
['_m','<=>' ,2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0]) <=> $dataset->getV($_[1])) }],
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
199
|
|
163
|
4
|
|
|
4
|
|
20
|
['_m','eq' ,2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0]) eq $dataset->getV($_[1])) }],
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
243
|
|
164
|
4
|
|
|
4
|
|
22
|
['_m','ne' ,2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0]) ne $dataset->getV($_[1])) }],
|
|
4
|
|
|
|
|
11
|
|
|
4
|
|
|
|
|
189
|
|
165
|
4
|
|
|
4
|
|
21
|
['_m','cmp' ,2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0]) cmp $dataset->getV($_[1])) }],
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
247
|
|
166
|
|
|
|
|
|
|
[],
|
167
|
4
|
|
|
4
|
|
26
|
['Lm','&' ,2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0])+0 & 0+$dataset->getV($_[1])) }],
|
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
237
|
|
168
|
|
|
|
|
|
|
[],
|
169
|
4
|
|
|
4
|
|
22
|
['Lm','|' ,2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0])+0 | 0+$dataset->getV($_[1])) }],
|
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
232
|
|
170
|
4
|
|
|
4
|
|
21
|
['Lm','^' ,2,sub{ no warnings; return $dataset->encode($dataset->getV($_[0])+0 ^ 0+$dataset->getV($_[1])) }],
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
801
|
|
171
|
|
|
|
|
|
|
[],
|
172
|
|
|
|
|
|
|
['Lm','&&',2,sub{ return $dataset->getV($_[0]) ?$_[1]:$_[0]; }],
|
173
|
|
|
|
|
|
|
[],
|
174
|
|
|
|
|
|
|
['Lm','||',2,sub{ return $dataset->getV($_[0]) ?$_[0]:$_[1]; }],
|
175
|
|
|
|
|
|
|
['Lm','//',2,sub{ return defined($dataset->getV($_[0])) ?$_[0]:$_[1]; }],
|
176
|
|
|
|
|
|
|
[],
|
177
|
|
|
|
|
|
|
['Rt','?' ,3,sub{ return $dataset->getV($_[0])? $_[1]:$_[2]; },':'],
|
178
|
|
|
|
|
|
|
[],
|
179
|
|
|
|
|
|
|
[ 'Rm', '=',2,sub{ $dataset->setV($_[0],$dataset->getV($_[1]) ); return $_[0]; }],
|
180
|
4
|
|
|
4
|
|
25
|
[ 'Rm','**=',2,sub{ no warnings; $dataset->setV($_[0],$dataset->getV($_[0]) ** $dataset->getV($_[1]) ); return $_[0]; }],
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
237
|
|
181
|
4
|
|
|
4
|
|
28
|
[ 'Rm', '*=',2,sub{ no warnings; $dataset->setV($_[0],$dataset->getV($_[0]) * $dataset->getV($_[1]) ); return $_[0]; }],
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
224
|
|
182
|
4
|
|
|
4
|
|
26
|
[ 'Rm', '/=',2,sub{ no warnings; $dataset->setV($_[0],$dataset->getV($_[0]) / $dataset->getV($_[1]) ); return $_[0]; }],
|
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
240
|
|
183
|
4
|
|
|
4
|
|
22
|
[ 'Rm', '%=',2,sub{ no warnings; $dataset->setV($_[0],$dataset->getV($_[0]) % $dataset->getV($_[1]) ); return $_[0]; }],
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
209
|
|
184
|
4
|
|
|
4
|
|
21
|
[ 'Rm', '+=',2,sub{ no warnings; $dataset->setV($_[0],$dataset->getV($_[0]) + $dataset->getV($_[1]) ); return $_[0]; }],
|
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
216
|
|
185
|
4
|
|
|
4
|
|
21
|
[ 'Rm', '-=',2,sub{ no warnings; $dataset->setV($_[0],$dataset->getV($_[0]) - $dataset->getV($_[1]) ); return $_[0]; }],
|
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
222
|
|
186
|
4
|
|
|
4
|
|
20
|
[ 'Rm','<<=',2,sub{ no warnings; $dataset->setV($_[0],$dataset->getV($_[0]) << $dataset->getV($_[1]) ); return $_[0]; }],
|
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
213
|
|
187
|
4
|
|
|
4
|
|
19
|
[ 'Rm','>>=',2,sub{ no warnings; $dataset->setV($_[0],$dataset->getV($_[0]) >> $dataset->getV($_[1]) ); return $_[0]; }],
|
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
213
|
|
188
|
4
|
|
|
4
|
|
21
|
[ 'Rm','&=' ,2,sub{ no warnings; $dataset->setV($_[0],$dataset->getV($_[0])+0&0+$dataset->getV($_[1]) ); return $_[0]; }],
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
228
|
|
189
|
4
|
|
|
4
|
|
22
|
[ 'Rm','|=' ,2,sub{ no warnings; $dataset->setV($_[0],$dataset->getV($_[0])+0|0+$dataset->getV($_[1]) ); return $_[0]; }],
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
282
|
|
190
|
4
|
|
|
4
|
|
23
|
[ 'Rm','^=' ,2,sub{ no warnings; $dataset->setV($_[0],$dataset->getV($_[0])+0^0+$dataset->getV($_[1]) ); return $_[0]; }],
|
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
10760
|
|
191
|
|
|
|
|
|
|
[ 'Rm','&&=',2,sub{ $dataset->getV($_[0]) and $dataset->setV($_[0],$dataset->getV($_[1])); return $_[0]; }],
|
192
|
|
|
|
|
|
|
[ 'Rm','||=',2,sub{ $dataset->getV($_[0]) or $dataset->setV($_[0],$dataset->getV($_[1])); return $_[0]; }],
|
193
|
|
|
|
|
|
|
[ 'Rm','//=',2,sub{ defined($dataset->getV($_[0])) or $dataset->setV($_[0],$dataset->getV($_[1])); return $_[0]; }],
|
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
[],
|
196
|
|
|
|
|
|
|
['Lm',',',2,sub{ return $dataset->makepathlist($_[0],$_[1]);}],
|
197
|
|
|
|
|
|
|
[],
|
198
|
|
|
|
|
|
|
['l','print',1,sub{
|
199
|
|
|
|
|
|
|
my @list;
|
200
|
|
|
|
|
|
|
$dataset->getVlist(\@list,$_[0]);
|
201
|
|
|
|
|
|
|
$dataset->print( @list);
|
202
|
|
|
|
|
|
|
return $dataset->encode('');
|
203
|
|
|
|
|
|
|
}],
|
204
|
|
|
|
|
|
|
['l','join',1,sub{
|
205
|
|
|
|
|
|
|
my @list;
|
206
|
|
|
|
|
|
|
$dataset->getVlist(\@list,$_[0]);
|
207
|
|
|
|
|
|
|
@list or return $dataset->encode('');
|
208
|
|
|
|
|
|
|
my $delm = shift @list;
|
209
|
|
|
|
|
|
|
my $a = join $delm,@list;
|
210
|
|
|
|
|
|
|
return $dataset->encode( $a );
|
211
|
|
|
|
|
|
|
}],
|
212
|
|
|
|
|
|
|
['l','scalar',1,sub{
|
213
|
|
|
|
|
|
|
my @list;
|
214
|
|
|
|
|
|
|
$dataset->getVlist(\@list,$_[0]);
|
215
|
|
|
|
|
|
|
return $dataset->encode( scalar @list );
|
216
|
|
|
|
|
|
|
}],
|
217
|
|
|
|
|
|
|
['l','push',1,sub{
|
218
|
|
|
|
|
|
|
my @list;
|
219
|
|
|
|
|
|
|
$dataset->getVlist(\@list,$_[0]);
|
220
|
|
|
|
|
|
|
if( @list and Text::Template::Compact::getDataType($list[0]) =~ /ARRAY/ ){
|
221
|
|
|
|
|
|
|
my $ra = shift @list;
|
222
|
|
|
|
|
|
|
push @$ra,@list;
|
223
|
|
|
|
|
|
|
}
|
224
|
|
|
|
|
|
|
return $dataset->encode( undef );
|
225
|
|
|
|
|
|
|
}],
|
226
|
|
|
|
|
|
|
['l','unshift',1,sub{
|
227
|
|
|
|
|
|
|
my @list;
|
228
|
|
|
|
|
|
|
$dataset->getVlist(\@list,$_[0]);
|
229
|
|
|
|
|
|
|
if(@list and Text::Template::Compact::getDataType($list[0]) =~ /ARRAY/ ){
|
230
|
|
|
|
|
|
|
my $ra = shift @list;
|
231
|
|
|
|
|
|
|
unshift @$ra,@list;
|
232
|
|
|
|
|
|
|
}
|
233
|
|
|
|
|
|
|
return $dataset->encode( undef );
|
234
|
|
|
|
|
|
|
}],
|
235
|
|
|
|
|
|
|
['l','call',1,sub{
|
236
|
|
|
|
|
|
|
my @list;
|
237
|
|
|
|
|
|
|
$dataset->getVlist(\@list,$_[0]);
|
238
|
|
|
|
|
|
|
local $_ = $dataset->{tmpl}{param};
|
239
|
|
|
|
|
|
|
if(@list and Text::Template::Compact::getDataType($list[0]) =~ /CODE/ ){
|
240
|
|
|
|
|
|
|
my $coderef = shift @list;
|
241
|
|
|
|
|
|
|
my $rv = eval{ $coderef->(@list); };
|
242
|
|
|
|
|
|
|
$@ and $rv = "[Error: $@]";
|
243
|
|
|
|
|
|
|
return $dataset->encode( $rv );
|
244
|
|
|
|
|
|
|
}elsif( @list >= 2 ){
|
245
|
|
|
|
|
|
|
my $obj = shift @list;
|
246
|
|
|
|
|
|
|
my $method = shift @list;
|
247
|
|
|
|
|
|
|
my $rv = eval{ $obj->$method(@list); };
|
248
|
|
|
|
|
|
|
$@ and $rv = "[Error: $@]";
|
249
|
|
|
|
|
|
|
return $dataset->encode( $rv );
|
250
|
|
|
|
|
|
|
}
|
251
|
|
|
|
|
|
|
return $dataset->encode( undef );
|
252
|
|
|
|
|
|
|
}],
|
253
|
|
|
|
|
|
|
['l','makearray',1,sub{
|
254
|
|
|
|
|
|
|
my @list;
|
255
|
|
|
|
|
|
|
$dataset->getVlist(\@list,$_[0]);
|
256
|
|
|
|
|
|
|
return $dataset->encode( \@list );
|
257
|
|
|
|
|
|
|
}],
|
258
|
|
|
|
|
|
|
['l','makehash',1,sub{
|
259
|
|
|
|
|
|
|
my @list;
|
260
|
|
|
|
|
|
|
$dataset->getVlist(\@list,$_[0]);
|
261
|
|
|
|
|
|
|
return $dataset->encode( {@list} );
|
262
|
|
|
|
|
|
|
}],
|
263
|
|
|
|
|
|
|
[],
|
264
|
|
|
|
|
|
|
# not and or xor
|
265
|
|
|
|
|
|
|
['Rl','not',1,sub{ return $dataset->encode(not $dataset->getV($_[0]));} ],
|
266
|
|
|
|
|
|
|
[],
|
267
|
|
|
|
|
|
|
['Lm','and',2,sub{ return $dataset->encode( $dataset->getV($_[0]) and $dataset->getV($_[1])); }],
|
268
|
|
|
|
|
|
|
[],
|
269
|
|
|
|
|
|
|
['Lm','or' ,2,sub{ return $dataset->encode( $dataset->getV($_[0]) or $dataset->getV($_[1])); }],
|
270
|
|
|
|
|
|
|
['Lm','xor',2,sub{ return $dataset->encode( $dataset->getV($_[0]) xor $dataset->getV($_[1])); }],
|
271
|
|
|
|
|
|
|
){
|
272
|
|
|
|
|
|
|
if(not @$_){ ++$prio; next; }
|
273
|
|
|
|
|
|
|
my $item = {
|
274
|
|
|
|
|
|
|
prio => $prio,
|
275
|
|
|
|
|
|
|
assoc => $_->[0],
|
276
|
|
|
|
|
|
|
key1 => $_->[1],
|
277
|
|
|
|
|
|
|
count => $_->[2],
|
278
|
|
|
|
|
|
|
_eval => $_->[3],
|
279
|
|
|
|
|
|
|
key2 => $_->[4],
|
280
|
|
|
|
|
|
|
};
|
281
|
|
|
|
|
|
|
( $item->{key1} eq 'print') and $list_op_prio=$prio;
|
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
push @ExprOperator,$item;
|
284
|
|
|
|
|
|
|
# defined($ExprOperator{ $item->{key1} }) or $ExprOperator{ $item->{key1} }=[];
|
285
|
|
|
|
|
|
|
push @{$ExprOperator{ $item->{key1} }},$item;
|
286
|
|
|
|
|
|
|
}
|
287
|
|
|
|
|
|
|
# make re
|
288
|
|
|
|
|
|
|
my %c;
|
289
|
|
|
|
|
|
|
for( '#',',',';','-|','$','$$',map {$_->{key1},$_->{key2}} @ExprOperator){
|
290
|
|
|
|
|
|
|
next if not defined or not length;
|
291
|
|
|
|
|
|
|
next if /^\w+$/;
|
292
|
|
|
|
|
|
|
my $text = $_;
|
293
|
|
|
|
|
|
|
my $map = \%c;
|
294
|
|
|
|
|
|
|
for(my $i=0;$i
|
295
|
|
|
|
|
|
|
my $c = substr($text,$i,1);
|
296
|
|
|
|
|
|
|
$map->{$c} or $map->{$c}={};
|
297
|
|
|
|
|
|
|
$map = $map->{$c};
|
298
|
|
|
|
|
|
|
}
|
299
|
|
|
|
|
|
|
}
|
300
|
|
|
|
|
|
|
sub toRe{
|
301
|
163
|
|
|
163
|
|
318
|
my($map)=@_;
|
302
|
163
|
|
|
|
|
266
|
my @list;
|
303
|
163
|
|
|
|
|
456
|
while(my($k,$v)=each %$map){
|
304
|
160
|
|
|
|
|
373
|
my $sub = toRe($v);
|
305
|
160
|
100
|
|
|
|
305
|
if($sub){
|
306
|
61
|
|
|
|
|
213
|
push @list,quotemeta($k).$sub."?";
|
307
|
|
|
|
|
|
|
}else{
|
308
|
100
|
|
|
|
|
357
|
push @list,quotemeta($k);
|
309
|
|
|
|
|
|
|
}
|
310
|
|
|
|
|
|
|
}
|
311
|
163
|
100
|
|
|
|
446
|
@list > 1 and return "(?:".join('|',@list).")";
|
312
|
136
|
100
|
|
|
|
311
|
@list and return $list[0];
|
313
|
100
|
|
|
|
|
226
|
return;
|
314
|
|
|
|
|
|
|
}
|
315
|
|
|
|
|
|
|
my $a = toRe(\%c);
|
316
|
|
|
|
|
|
|
$token_re = qr/$a/;
|
317
|
|
|
|
|
|
|
}
|
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
sub findOp{
|
320
|
1522
|
|
|
1522
|
|
3009
|
my($token,$re)=@_;
|
321
|
1522
|
100
|
|
|
|
5301
|
my $list = $ExprOperator{ $token } or return;
|
322
|
467
|
100
|
|
|
|
960
|
for(@$list){ return $_ if $_->{assoc} =~ $re; }
|
|
520
|
|
|
|
|
2928
|
|
323
|
43
|
|
|
|
|
190
|
return;
|
324
|
|
|
|
|
|
|
}
|
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
{
|
327
|
|
|
|
|
|
|
package Text::Template::Compact::ExprNode;
|
328
|
|
|
|
|
|
|
sub new{
|
329
|
523
|
|
|
523
|
|
1083
|
my($class,$op,$text)=@_;
|
330
|
523
|
100
|
|
|
|
1390
|
if(not ref $op){
|
331
|
|
|
|
|
|
|
# keyword?
|
332
|
286
|
50
|
|
|
|
696
|
return $text if $op eq 'k';
|
333
|
|
|
|
|
|
|
# root operator?
|
334
|
|
|
|
|
|
|
$op = {
|
335
|
|
|
|
|
|
|
assoc => '_',
|
336
|
|
|
|
|
|
|
key1 => 'root',
|
337
|
1283
|
|
|
1283
|
|
2445
|
_eval => sub{ return $_[0]; },
|
338
|
286
|
|
|
|
|
1703
|
count => 1,
|
339
|
|
|
|
|
|
|
prio => 999,
|
340
|
|
|
|
|
|
|
};
|
341
|
|
|
|
|
|
|
}
|
342
|
523
|
|
|
|
|
2605
|
return bless{ op=>$op, args=>[],},$class;
|
343
|
|
|
|
|
|
|
};
|
344
|
|
|
|
|
|
|
sub addArg{
|
345
|
844
|
|
|
844
|
|
1332
|
my $self=shift;
|
346
|
844
|
|
|
|
|
1200
|
push @{$self->{args}},@_;
|
|
844
|
|
|
|
|
1965
|
|
347
|
|
|
|
|
|
|
}
|
348
|
|
|
|
|
|
|
sub toString{
|
349
|
1
|
|
|
1
|
|
35
|
my($self,$mark)=@_;
|
350
|
1
|
0
|
|
|
|
7
|
defined($mark) or $mark = '';
|
351
|
1
|
0
|
|
|
|
2
|
if($self->{op}{key1} eq 'root'){
|
352
|
1
|
0
|
|
|
|
31
|
return join(',',map{ ref($_)?$_->toString($mark):$_} @{$self->{args}});
|
|
1
|
|
|
|
|
7
|
|
|
1
|
|
|
|
|
2
|
|
353
|
|
|
|
|
|
|
}
|
354
|
|
|
|
|
|
|
return
|
355
|
|
|
|
|
|
|
$self->{op}{key1}
|
356
|
|
|
|
|
|
|
.($self->{closed}?$self->{op}{key2}:'')
|
357
|
|
|
|
|
|
|
.($mark eq $self ?"<=HERE=>":'')
|
358
|
|
|
|
|
|
|
.'{'
|
359
|
1
|
0
|
|
|
|
32
|
.join(',',map{ ref($_)?$_->toString($mark):$_ } @{$self->{args}} )
|
|
1
|
0
|
|
|
|
6
|
|
|
1
|
0
|
|
|
|
3
|
|
360
|
|
|
|
|
|
|
.'}';
|
361
|
|
|
|
|
|
|
}
|
362
|
|
|
|
|
|
|
sub _eval{
|
363
|
2036
|
|
|
2036
|
|
3577
|
my($self)=@_;
|
364
|
2036
|
100
|
|
|
|
3098
|
my @args = map{ ref($_) ? $_->_eval() : $Text::Template::Compact::ExprParser::dataset->token2path($_) } @{$self->{args}};
|
|
2524
|
|
|
|
|
6888
|
|
|
2036
|
|
|
|
|
4501
|
|
365
|
2036
|
|
66
|
|
|
10189
|
my $r = ($self->{realop} || $self->{op})->{_eval}(@args);
|
366
|
2036
|
|
|
|
|
6870
|
return $r;
|
367
|
|
|
|
|
|
|
}
|
368
|
|
|
|
|
|
|
sub eval{
|
369
|
1283
|
|
|
1283
|
|
2453
|
my($self,$dataset)=@_;
|
370
|
1283
|
|
|
|
|
2197
|
local $Text::Template::Compact::ExprParser::dataset = $dataset;
|
371
|
1283
|
|
|
|
|
2076
|
my $r = CORE::eval{ $self->_eval();};
|
|
1283
|
|
|
|
|
2701
|
|
372
|
1283
|
50
|
|
|
|
3043
|
$@ and return ['i',"[Error: $@ in ".$self->toString." in Text::Template::Compact::ExprNode::eval]"];
|
373
|
1283
|
|
|
|
|
3264
|
return $r;
|
374
|
|
|
|
|
|
|
}
|
375
|
|
|
|
|
|
|
}
|
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
our $verbose = 0;
|
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
sub peekToken{
|
380
|
2394
|
|
|
2394
|
|
3720
|
my $self = shift;
|
381
|
2394
|
100
|
|
|
|
3457
|
@{$self->{token}} and return $self->{token}[0];
|
|
2394
|
|
|
|
|
6562
|
|
382
|
1172
|
|
|
|
|
2241
|
return;
|
383
|
|
|
|
|
|
|
}
|
384
|
|
|
|
|
|
|
sub reduce{
|
385
|
1000
|
|
|
1000
|
|
1953
|
my($self,$where)=@_;
|
386
|
|
|
|
|
|
|
|
387
|
1000
|
100
|
|
|
|
2721
|
return if $self->{allow_child};
|
388
|
|
|
|
|
|
|
|
389
|
514
|
|
|
|
|
1030
|
my $a = $self->peekToken;
|
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
# スタックが空ならreduceできない
|
392
|
514
|
100
|
|
|
|
862
|
return if @{$self->{stack}}==1;
|
|
514
|
|
|
|
|
1428
|
|
393
|
|
|
|
|
|
|
|
394
|
229
|
|
|
|
|
461
|
my $target = $self->{stack}[0];
|
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
# 注目ノードの種別が () []だった
|
397
|
229
|
100
|
|
|
|
670
|
if( $target->{op}{assoc} =~ /[ba]/ ){
|
398
|
26
|
50
|
33
|
|
|
138
|
if( defined($a) and $a eq $target->{op}{key2}
|
|
|
|
33
|
|
|
|
|
399
|
26
|
|
|
|
|
124
|
and @{$target->{args}} == $target->{op}->{count}
|
400
|
|
|
|
|
|
|
){
|
401
|
26
|
50
|
|
|
|
71
|
$verbose>0 and warn "remove end of braket $target->{op}{key2}. reduce in $where\n";
|
402
|
26
|
|
|
|
|
63
|
$target->{closed} = 1;
|
403
|
26
|
|
|
|
|
79
|
shift @{$self->{token}};
|
|
26
|
|
|
|
|
59
|
|
404
|
26
|
|
|
|
|
45
|
shift @{$self->{stack}};
|
|
26
|
|
|
|
|
104
|
|
405
|
26
|
|
|
|
|
45
|
$self->{allow_child} = 0;
|
406
|
26
|
|
|
|
|
82
|
return 1;
|
407
|
|
|
|
|
|
|
}
|
408
|
|
|
|
|
|
|
}else{
|
409
|
204
|
100
|
|
|
|
351
|
if( @{$target->{args}} == $target->{op}->{count} ){
|
|
204
|
|
|
|
|
544
|
|
410
|
200
|
50
|
|
|
|
432
|
$verbose>0 and warn "end of operator $target->{op}{key1} . reduce in $where\n";
|
411
|
200
|
|
|
|
|
343
|
shift @{$self->{stack}};
|
|
200
|
|
|
|
|
360
|
|
412
|
200
|
|
|
|
|
347
|
$self->{allow_child} = 0;
|
413
|
200
|
|
|
|
|
648
|
return 1;
|
414
|
|
|
|
|
|
|
}
|
415
|
|
|
|
|
|
|
# ?:
|
416
|
5
|
50
|
33
|
|
|
63
|
if( $target->{op}{assoc} =~ /t/ and $a and $a eq $target->{op}->{key2} ){
|
|
|
|
33
|
|
|
|
|
417
|
5
|
50
|
|
|
|
20
|
$verbose>0 and warn "eating ':' operator . reduce in $where\n";
|
418
|
5
|
|
|
|
|
41
|
shift @{$self->{token}};
|
|
5
|
|
|
|
|
20
|
|
419
|
5
|
|
|
|
|
12
|
$self->{allow_child} = 1;
|
420
|
5
|
|
|
|
|
48
|
return 1;
|
421
|
|
|
|
|
|
|
}
|
422
|
|
|
|
|
|
|
}
|
423
|
1
|
|
|
|
|
9
|
return;
|
424
|
|
|
|
|
|
|
}
|
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
sub parse{
|
427
|
286
|
|
|
286
|
|
511
|
my($list)=@_;
|
428
|
|
|
|
|
|
|
|
429
|
286
|
|
|
|
|
844
|
my $self = bless{
|
430
|
|
|
|
|
|
|
allow_child => 1,
|
431
|
|
|
|
|
|
|
stack=>[new Text::Template::Compact::ExprNode('')],
|
432
|
|
|
|
|
|
|
token=>$list,
|
433
|
|
|
|
|
|
|
};
|
434
|
|
|
|
|
|
|
|
435
|
286
|
|
|
|
|
581
|
my($op,$node);
|
436
|
|
|
|
|
|
|
|
437
|
286
|
|
|
|
|
440
|
Loop: for(;;){
|
438
|
1152
|
|
|
|
|
2049
|
my $target = $self->{stack}[0];
|
439
|
1152
|
|
|
|
|
2312
|
my $token = $self->peekToken;
|
440
|
1152
|
50
|
0
|
|
|
2701
|
$verbose>0 and warn "mode=$self->{allow_child} token:",($token||'')," stack:",join(',',map{$_->{op}{key1}} @{$self->{stack}}),"\n";
|
|
1
|
|
|
|
|
51
|
|
|
1
|
|
|
|
|
7
|
|
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
# reduce if possible
|
444
|
1152
|
100
|
100
|
|
|
4114
|
if( not defined($token)
|
445
|
|
|
|
|
|
|
or not findOp( $token,qr/[armtk]/ )
|
446
|
|
|
|
|
|
|
){
|
447
|
970
|
100
|
|
|
|
2080
|
next if $self->reduce('loop');
|
448
|
|
|
|
|
|
|
}
|
449
|
|
|
|
|
|
|
|
450
|
954
|
100
|
|
|
|
2728
|
last if not defined($token);
|
451
|
|
|
|
|
|
|
|
452
|
719
|
100
|
|
|
|
1584
|
if( $self->{allow_child} ){
|
453
|
507
|
|
|
|
|
1544
|
my $op = findOp($token,qr/[bl]/);
|
454
|
507
|
100
|
|
|
|
1376
|
if($op){
|
455
|
|
|
|
|
|
|
# listop(b) ??
|
456
|
63
|
100
|
66
|
|
|
117
|
if( @{$self->{token}} >= 2
|
|
63
|
|
100
|
|
|
508
|
|
457
|
|
|
|
|
|
|
and $op->{key1} =~/^\w/
|
458
|
|
|
|
|
|
|
and $self->{token}[1] eq '('
|
459
|
|
|
|
|
|
|
){
|
460
|
6
|
50
|
|
|
|
22
|
$verbose>0 and warn "start of term $token(?) \n";
|
461
|
6
|
|
|
|
|
13
|
shift @{$self->{token}};
|
|
6
|
|
|
|
|
55
|
|
462
|
6
|
|
|
|
|
17
|
shift @{$self->{token}};
|
|
6
|
|
|
|
|
16
|
|
463
|
6
|
|
|
|
|
51
|
$node = new Text::Template::Compact::ExprNode(findOp('(',qr/a/));
|
464
|
6
|
|
|
|
|
25
|
$target->addArg($node);
|
465
|
6
|
|
|
|
|
13
|
unshift @{$self->{stack}},$node;
|
|
6
|
|
|
|
|
46
|
|
466
|
6
|
|
|
|
|
18
|
$self->{allow_child} = 1;
|
467
|
6
|
|
|
|
|
16
|
$node->{realop} = $op;
|
468
|
6
|
|
|
|
|
40
|
next;
|
469
|
|
|
|
|
|
|
}
|
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
# unary left or '('
|
472
|
58
|
50
|
|
|
|
162
|
$verbose>0 and warn "operator $token start\n";
|
473
|
58
|
|
|
|
|
104
|
shift @{$self->{token}};
|
|
58
|
|
|
|
|
137
|
|
474
|
58
|
|
|
|
|
170
|
$node = new Text::Template::Compact::ExprNode($op);
|
475
|
58
|
|
|
|
|
166
|
$target->addArg($node);
|
476
|
58
|
|
|
|
|
138
|
unshift @{$self->{stack}},$node;
|
|
58
|
|
|
|
|
145
|
|
477
|
58
|
|
|
|
|
114
|
$self->{allow_child} = 1;
|
478
|
58
|
|
|
|
|
161
|
next;
|
479
|
|
|
|
|
|
|
}
|
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
# keyword or constant or $,$$
|
482
|
445
|
50
|
|
|
|
1731
|
if( $token =~/^["\w\d_\$]/ ){
|
483
|
445
|
50
|
|
|
|
1015
|
$verbose>0 and warn "constant or keyword $token\n";
|
484
|
445
|
|
|
|
|
754
|
$target->addArg(shift @{$self->{token}});
|
|
445
|
|
|
|
|
1359
|
|
485
|
445
|
|
|
|
|
904
|
$self->{allow_child} = 0;
|
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
# $keyword
|
488
|
445
|
|
|
|
|
854
|
my $old_arg = $target->{args}[-1];
|
489
|
445
|
|
|
|
|
902
|
$token = $self->peekToken;
|
490
|
445
|
100
|
100
|
|
|
2043
|
if( defined($token) and $token =~/^["\w\d_]/ and $old_arg =~/^\$/ ){
|
|
|
|
100
|
|
|
|
|
491
|
14
|
50
|
|
|
|
79
|
$verbose>0 and warn "merge '$old_arg' and '$token'\n";
|
492
|
14
|
|
|
|
|
60
|
$node = new Text::Template::Compact::ExprNode(findOp('.',qr/[armtk]/));
|
493
|
14
|
|
|
|
|
39
|
$target->{args}[-1] = $node;
|
494
|
14
|
|
|
|
|
96
|
$node->addArg($old_arg,$token);
|
495
|
14
|
|
|
|
|
33
|
shift @{$self->{token}};
|
|
14
|
|
|
|
|
30
|
|
496
|
|
|
|
|
|
|
}
|
497
|
445
|
|
|
|
|
935
|
next;
|
498
|
|
|
|
|
|
|
}
|
499
|
|
|
|
|
|
|
}else{
|
500
|
|
|
|
|
|
|
|
501
|
213
|
|
|
|
|
671
|
$op = findOp($token,qr/[armtk]/);
|
502
|
213
|
100
|
|
|
|
619
|
if($op){
|
503
|
163
|
|
|
|
|
415
|
$node = new Text::Template::Compact::ExprNode($op);
|
504
|
163
|
|
|
|
|
299
|
my $a;
|
505
|
163
|
|
|
|
|
279
|
while(@{$self->{stack}}){
|
|
193
|
|
|
|
|
487
|
|
506
|
193
|
|
|
|
|
411
|
my($left,$right) =($target->{op},$op);
|
507
|
193
|
|
|
|
|
379
|
my($left_prio,$right_prio) =($left->{prio},$right->{prio});
|
508
|
193
|
|
|
|
|
399
|
my($left_assoc,$right_assoc) =($left->{assoc},$right->{assoc});
|
509
|
|
|
|
|
|
|
|
510
|
193
|
100
|
66
|
|
|
684
|
if( $left_assoc =~ /[ba]/ and not $target->{closed} ){
|
511
|
|
|
|
|
|
|
# if inside of non closed braket, always right combination
|
512
|
22
|
|
|
|
|
71
|
$a=1;
|
513
|
|
|
|
|
|
|
}else{
|
514
|
|
|
|
|
|
|
# List Operators (Leftward) has very high priority
|
515
|
172
|
50
|
|
|
|
387
|
if( $right_prio == $list_op_prio ){
|
516
|
1
|
|
|
|
|
25
|
$right_prio = 0;
|
517
|
|
|
|
|
|
|
}
|
518
|
|
|
|
|
|
|
# compare operator precedence
|
519
|
172
|
|
|
|
|
277
|
$a = $left_prio - $right_prio;
|
520
|
172
|
100
|
|
|
|
406
|
if(!$a){
|
521
|
|
|
|
|
|
|
# if same, check left or right associativity
|
522
|
25
|
50
|
|
|
|
97
|
if( $left_assoc =~/L/ ){ $a=-1;}
|
|
25
|
0
|
|
|
|
57
|
|
523
|
1
|
|
|
|
|
4
|
elsif( $left_assoc =~/R/ ){ $a= 1;}
|
524
|
|
|
|
|
|
|
else{
|
525
|
1
|
|
|
|
|
50
|
die "repeating non-assoc operator. $left->{key1} $right->{key1}\n";
|
526
|
|
|
|
|
|
|
}
|
527
|
|
|
|
|
|
|
}
|
528
|
|
|
|
|
|
|
}
|
529
|
193
|
50
|
|
|
|
469
|
$verbose>0 and warn "lr=$a $left->{key1} $right->{key1}\n";
|
530
|
|
|
|
|
|
|
|
531
|
193
|
100
|
|
|
|
504
|
if($a>0){ #right a+(b*c)
|
532
|
163
|
50
|
|
|
|
384
|
$verbose>0 and warn "appending right combination\n";
|
533
|
163
|
|
|
|
|
295
|
shift @{$self->{token}};
|
|
163
|
|
|
|
|
310
|
|
534
|
163
|
|
|
|
|
374
|
my $b = pop @{$target->{args}};
|
|
163
|
|
|
|
|
354
|
|
535
|
163
|
|
|
|
|
441
|
$target->addArg($node);
|
536
|
163
|
|
|
|
|
288
|
unshift @{$self->{stack}},$node;
|
|
163
|
|
|
|
|
399
|
|
537
|
163
|
|
|
|
|
396
|
$node->addArg($b);
|
538
|
163
|
|
|
|
|
343
|
$target=$self->{stack}[0];
|
539
|
163
|
100
|
|
|
|
245
|
if( @{$target->{args}} < $target->{op}{count} ){
|
|
163
|
|
|
|
|
462
|
|
540
|
156
|
|
|
|
|
295
|
$self->{allow_child} =1;
|
541
|
|
|
|
|
|
|
}
|
542
|
163
|
|
|
|
|
412
|
next Loop;
|
543
|
|
|
|
|
|
|
}
|
544
|
|
|
|
|
|
|
|
545
|
31
|
50
|
|
|
|
120
|
if( not $self->reduce("left combination $target->{op}->{key1} $op->{key1}") ){
|
546
|
|
|
|
|
|
|
# warn "reduce failed: ",Data::Dumper::Dumper($target),"\n";
|
547
|
1
|
|
|
|
|
20
|
die "cannot resolve operator precedence between '$target->{op}->{key1}' and '$op->{key1}'\n";
|
548
|
|
|
|
|
|
|
}
|
549
|
31
|
|
|
|
|
77
|
$target=$self->{stack}[0];
|
550
|
|
|
|
|
|
|
}
|
551
|
|
|
|
|
|
|
}
|
552
|
|
|
|
|
|
|
}
|
553
|
51
|
|
|
|
|
122
|
last;
|
554
|
|
|
|
|
|
|
}
|
555
|
286
|
50
|
|
|
|
644
|
$verbose>0 and warn "end. stack=",join(',',map{$_->{op}->{key1}} @{$self->{stack}}),"\n";
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
19
|
|
556
|
285
|
|
|
|
|
577
|
my $token = $self->peekToken;
|
557
|
285
|
0
|
|
|
|
462
|
@{$self->{stack}}==1 or die "expression is not completed at '",(defined($token)?"'$token'":"end of statement"),"'\n";
|
|
285
|
50
|
|
|
|
695
|
|
558
|
285
|
50
|
|
|
|
462
|
@{$self->{stack}[0]{args}} or die "expression not found\n";
|
|
285
|
|
|
|
|
686
|
|
559
|
285
|
|
|
|
|
978
|
return $self->{stack}[0];
|
560
|
|
|
|
|
|
|
}
|
561
|
|
|
|
|
|
|
}
|
562
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
{
|
564
|
|
|
|
|
|
|
package Text::Template::Compact::Dataset;
|
565
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
*getDataType = \&Text::Template::Compact::getDataType;
|
567
|
|
|
|
|
|
|
*decodeQuote = \&Text::Template::Compact::decodeQuote;
|
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
sub new{
|
570
|
1282
|
|
|
1283
|
|
2536
|
my($class,$tmpl,$tag)=@_;
|
571
|
|
|
|
|
|
|
return bless {
|
572
|
|
|
|
|
|
|
tmpl=>$tmpl,
|
573
|
|
|
|
|
|
|
tag=>$tag,
|
574
|
|
|
|
|
|
|
enc => $tmpl->{paramEncoding},
|
575
|
1282
|
|
|
|
|
5408
|
},$class;
|
576
|
|
|
|
|
|
|
}
|
577
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
sub print{
|
579
|
10
|
|
|
11
|
|
22
|
my($self)=shift;
|
580
|
10
|
|
|
|
|
25
|
my $printer = $self->{tmpl}{printer};
|
581
|
10
|
|
33
|
|
|
49
|
my $filter = ( $self->{tag}{filter} || $self->{tmpl}{filter_default} );
|
582
|
10
|
|
|
|
|
31
|
for(@_){ $printer->( $filter->( Text::Template::Compact::dor($_,$self->{tmpl}{undef_supply}))); }
|
|
19
|
|
|
|
|
45
|
|
583
|
|
|
|
|
|
|
}
|
584
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
# make path from token
|
586
|
|
|
|
|
|
|
sub token2path{
|
587
|
1770
|
|
|
1771
|
|
3531
|
my($self,$token)=@_;
|
588
|
1770
|
100
|
100
|
|
|
9581
|
if( $token =~ /^"/
|
589
|
|
|
|
|
|
|
or $token =~ /^\d/
|
590
|
|
|
|
|
|
|
){
|
591
|
439
|
|
|
|
|
1095
|
return ['i',decodeQuote($token)];
|
592
|
|
|
|
|
|
|
}
|
593
|
1331
|
|
|
|
|
5078
|
return ['k',$token];
|
594
|
|
|
|
|
|
|
}
|
595
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
sub makepathlist{
|
597
|
92
|
|
|
93
|
|
159
|
my($self) = shift;
|
598
|
92
|
|
|
|
|
215
|
return [ 'l',@_];
|
599
|
|
|
|
|
|
|
}
|
600
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
sub endoflist{
|
602
|
1945
|
|
|
1946
|
|
3439
|
my($self,$path)=@_;
|
603
|
1945
|
100
|
|
|
|
4684
|
( $path->[0] eq 'l' ) and return $self->endoflist($path->[-1]);
|
604
|
1942
|
|
|
|
|
3529
|
return $path;
|
605
|
|
|
|
|
|
|
}
|
606
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
sub getVlist{
|
608
|
582
|
|
|
583
|
|
1184
|
my($self,$result,$path)=@_;
|
609
|
582
|
100
|
|
|
|
1348
|
if( $path->[0] eq 'l' ){
|
610
|
88
|
|
|
|
|
246
|
for(my $i=1;$i<@$path;++$i){
|
611
|
176
|
|
|
|
|
405
|
$self->getVlist($result,$path->[$i]);
|
612
|
|
|
|
|
|
|
}
|
613
|
|
|
|
|
|
|
}else{
|
614
|
494
|
|
|
|
|
1226
|
my $val = $self->getV($path);
|
615
|
494
|
|
|
|
|
8216
|
push @$result,$val;
|
616
|
|
|
|
|
|
|
}
|
617
|
|
|
|
|
|
|
}
|
618
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
# make data path from immediate value
|
620
|
|
|
|
|
|
|
sub encode{
|
621
|
518
|
|
|
519
|
|
4161
|
my($self,$value)=@_;
|
622
|
518
|
|
|
|
|
1510
|
return ['i',$value];
|
623
|
|
|
|
|
|
|
}
|
624
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
# make relative data path
|
626
|
|
|
|
|
|
|
sub child{
|
627
|
55
|
|
|
56
|
|
105
|
my($self,$path,$rel)=@_;
|
628
|
55
|
|
|
|
|
139
|
my $r = ['p',[]];
|
629
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
# get right item if arg is list
|
631
|
55
|
|
|
|
|
135
|
$path = $self->endoflist($path);
|
632
|
55
|
|
|
|
|
109
|
$rel = $self->endoflist($rel);
|
633
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
# copy parent
|
635
|
55
|
100
|
|
|
|
118
|
if($path->[0] eq 'p'){
|
636
|
6
|
|
|
|
|
11
|
push @{$r->[1]} , @{$path->[1]};
|
|
6
|
|
|
|
|
13
|
|
|
6
|
|
|
|
|
17
|
|
637
|
|
|
|
|
|
|
}else{
|
638
|
49
|
|
|
|
|
81
|
push @{$r->[1]} , $path->[1];
|
|
49
|
|
|
|
|
128
|
|
639
|
|
|
|
|
|
|
}
|
640
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
# copy child
|
642
|
55
|
100
|
|
|
|
125
|
if($rel->[0] eq 'p'){
|
643
|
2
|
|
|
|
|
5
|
push @{$r->[1]} , @{$rel->[1]};
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
5
|
|
644
|
|
|
|
|
|
|
}else{
|
645
|
53
|
|
|
|
|
75
|
push @{$r->[1]} , $rel->[1];
|
|
53
|
|
|
|
|
105
|
|
646
|
|
|
|
|
|
|
}
|
647
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
# make
|
649
|
55
|
|
|
|
|
113
|
return $r;
|
650
|
|
|
|
|
|
|
}
|
651
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
# get value in data path
|
653
|
|
|
|
|
|
|
sub getV{
|
654
|
1830
|
|
|
1831
|
|
7460
|
my($self,$path)=@_;
|
655
|
1830
|
50
|
|
|
|
4467
|
ref($path) or die "incorrect path\n";
|
656
|
|
|
|
|
|
|
|
657
|
|
|
|
|
|
|
# get right item if arg is list
|
658
|
1830
|
|
|
|
|
3799
|
$path = $self->endoflist($path);
|
659
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
# immidiate value
|
661
|
1830
|
100
|
|
|
|
5281
|
return $path->[1] if $path->[0] eq 'i';
|
662
|
|
|
|
|
|
|
|
663
|
987
|
|
|
|
|
1675
|
my @path;
|
664
|
987
|
100
|
|
|
|
2803
|
if( $path->[0] eq 'p' ){
|
665
|
42
|
|
|
|
|
68
|
push @path,@{$path->[1]};
|
|
42
|
|
|
|
|
90
|
|
666
|
|
|
|
|
|
|
}else{
|
667
|
945
|
|
|
|
|
2051
|
push @path,$path->[1];
|
668
|
|
|
|
|
|
|
}
|
669
|
|
|
|
|
|
|
|
670
|
987
|
|
|
|
|
1923
|
my $param = $self->{tmpl}{param};
|
671
|
987
|
|
|
|
|
1707
|
my $path_str = '$';
|
672
|
987
|
100
|
|
|
|
2733
|
if( $path[0] eq '$' ){
|
|
|
100
|
|
|
|
|
|
673
|
10
|
|
|
|
|
18
|
shift @path;
|
674
|
|
|
|
|
|
|
}elsif( $path[0] eq '$$' ){
|
675
|
2
|
|
|
|
|
5
|
shift @path;
|
676
|
2
|
|
|
|
|
5
|
$param = $self->{tmpl};
|
677
|
|
|
|
|
|
|
}
|
678
|
|
|
|
|
|
|
|
679
|
987
|
|
|
|
|
2363
|
while(@path){
|
680
|
1025
|
|
|
|
|
2168
|
my $key = shift @path;
|
681
|
1025
|
|
|
|
|
2392
|
my $type = getDataType($param);
|
682
|
1025
|
100
|
|
|
|
2857
|
if( $type eq 'ARRAY' ){
|
|
|
50
|
|
|
|
|
|
683
|
4
|
|
|
4
|
|
45
|
no warnings;
|
|
4
|
|
|
|
|
11
|
|
|
4
|
|
|
|
|
208
|
|
684
|
27
|
|
|
|
|
71
|
$param = $param->[$key];
|
685
|
|
|
|
|
|
|
}elsif($type eq 'HASH' ){
|
686
|
4
|
|
|
4
|
|
28
|
no warnings;
|
|
4
|
|
|
|
|
14
|
|
|
4
|
|
|
|
|
13132
|
|
687
|
998
|
|
|
|
|
2035
|
$param = $param->{$key};
|
688
|
|
|
|
|
|
|
}else{
|
689
|
0
|
|
|
|
|
0
|
die "incorrect data path $path_str\n";
|
690
|
|
|
|
|
|
|
}
|
691
|
1025
|
50
|
|
|
|
2851
|
$path_str .= (length($path_str)?'.':'').$key;
|
692
|
1025
|
50
|
66
|
|
|
3945
|
(@path and not ref $param) and die "incorrect data path $path_str\n";
|
693
|
|
|
|
|
|
|
}
|
694
|
987
|
100
|
100
|
|
|
7528
|
if( defined $param
|
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
695
|
|
|
|
|
|
|
and not ref($param)
|
696
|
|
|
|
|
|
|
and not utf8::is_utf8($param)
|
697
|
|
|
|
|
|
|
and defined $self->{enc}
|
698
|
|
|
|
|
|
|
){
|
699
|
701
|
|
|
|
|
2157
|
return Encode::decode($self->{enc},$param);
|
700
|
|
|
|
|
|
|
}
|
701
|
286
|
|
|
|
|
904
|
return $param;
|
702
|
|
|
|
|
|
|
}
|
703
|
|
|
|
|
|
|
# set value to data path
|
704
|
|
|
|
|
|
|
sub setV{
|
705
|
405
|
|
|
406
|
|
859
|
my($self,$path,$newval)=@_;
|
706
|
|
|
|
|
|
|
|
707
|
|
|
|
|
|
|
# get right item if arg is list
|
708
|
405
|
50
|
|
|
|
1111
|
($path->[0] eq 'l') and $path = $self->endoflist($path);
|
709
|
|
|
|
|
|
|
|
710
|
405
|
50
|
|
|
|
969
|
if( $path->[0] eq 'i' ){
|
711
|
0
|
|
|
|
|
0
|
die "L-Value required\n";
|
712
|
|
|
|
|
|
|
}
|
713
|
|
|
|
|
|
|
|
714
|
405
|
|
|
|
|
667
|
my @path;
|
715
|
405
|
100
|
|
|
|
864
|
if( $path->[0] eq 'p' ){
|
716
|
5
|
|
|
|
|
13
|
push @path,@{$path->[1]};
|
|
5
|
|
|
|
|
20
|
|
717
|
|
|
|
|
|
|
}else{
|
718
|
400
|
|
|
|
|
864
|
push @path,$path->[1];
|
719
|
|
|
|
|
|
|
}
|
720
|
|
|
|
|
|
|
|
721
|
405
|
|
|
|
|
785
|
my $param = $self->{tmpl}{param};
|
722
|
405
|
|
|
|
|
692
|
my $path_str = '$';
|
723
|
405
|
100
|
|
|
|
1202
|
if( $path[0] eq '$' ){
|
|
|
50
|
|
|
|
|
|
724
|
5
|
|
|
|
|
12
|
shift @path;
|
725
|
|
|
|
|
|
|
}elsif( $path[0] eq '$$' ){
|
726
|
0
|
|
|
|
|
0
|
shift @path;
|
727
|
0
|
|
|
|
|
0
|
$param = $self->{tmpl};
|
728
|
|
|
|
|
|
|
}
|
729
|
|
|
|
|
|
|
|
730
|
405
|
|
|
|
|
1173
|
while(@path){
|
731
|
405
|
|
|
|
|
841
|
my $key = shift @path;
|
732
|
405
|
|
|
|
|
975
|
my $type = getDataType($param);
|
733
|
405
|
50
|
|
|
|
1259
|
if( $type eq 'ARRAY' ){
|
|
|
50
|
|
|
|
|
|
734
|
0
|
0
|
|
|
|
0
|
if(not @path){
|
735
|
0
|
|
|
|
|
0
|
my $old = $param->[$key];
|
736
|
0
|
|
|
|
|
0
|
$param->[$key] = $newval;
|
737
|
0
|
|
|
|
|
0
|
return \$old;
|
738
|
|
|
|
|
|
|
}else{
|
739
|
0
|
|
|
|
|
0
|
$param = $param->[$key];
|
740
|
|
|
|
|
|
|
}
|
741
|
|
|
|
|
|
|
}elsif($type eq 'HASH' ){
|
742
|
405
|
50
|
|
|
|
895
|
if(not @path){
|
743
|
405
|
|
|
|
|
848
|
my $old = $param->{$key};
|
744
|
405
|
|
|
|
|
786
|
$param->{$key} = $newval;
|
745
|
405
|
|
|
|
|
1138
|
return \$old;
|
746
|
|
|
|
|
|
|
}else{
|
747
|
0
|
|
|
|
|
0
|
$param = $param->{$key};
|
748
|
|
|
|
|
|
|
}
|
749
|
|
|
|
|
|
|
}else{
|
750
|
0
|
|
|
|
|
0
|
die "incorrect data path $path_str\n";
|
751
|
|
|
|
|
|
|
}
|
752
|
0
|
|
|
|
|
0
|
$path_str .= '.'.$key;
|
753
|
0
|
0
|
0
|
|
|
0
|
(@path and not ref $param) and die "incorrect data path $path_str\n";
|
754
|
|
|
|
|
|
|
}
|
755
|
|
|
|
|
|
|
}
|
756
|
|
|
|
|
|
|
}
|
757
|
|
|
|
|
|
|
|
758
|
|
|
|
|
|
|
# record parse error and die (should be catch in parser)
|
759
|
|
|
|
|
|
|
sub parseError{
|
760
|
0
|
|
|
1
|
0
|
0
|
my($self)=shift;
|
761
|
0
|
|
|
|
|
0
|
my $msg = join('',"$self->{source_name} $self->{lno}: ",@_);
|
762
|
0
|
|
|
|
|
0
|
$msg =~ s/[\x0d\x0a]+//g;
|
763
|
0
|
|
|
|
|
0
|
push @{$self->{error}},$msg;
|
|
0
|
|
|
|
|
0
|
|
764
|
0
|
|
|
|
|
0
|
croak $msg,"\n";
|
765
|
|
|
|
|
|
|
}
|
766
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
sub parseExpr{
|
768
|
285
|
|
|
286
|
0
|
587
|
my($self,$list)=@_;
|
769
|
285
|
|
|
|
|
528
|
my $r = eval{ Text::Template::Compact::ExprParser::parse($list);};
|
|
285
|
|
|
|
|
673
|
|
770
|
285
|
50
|
|
|
|
675
|
$@ and $self->parseError($@);
|
771
|
285
|
|
|
|
|
750
|
return $r;
|
772
|
|
|
|
|
|
|
}
|
773
|
|
|
|
|
|
|
|
774
|
|
|
|
|
|
|
sub evalExpr{
|
775
|
535
|
|
|
536
|
0
|
1050
|
my($tmpl,$tag,$expr)=@_;
|
776
|
535
|
|
|
|
|
1361
|
my $dataset = new Text::Template::Compact::Dataset($tmpl,$tag);
|
777
|
535
|
|
|
|
|
1006
|
my $r = eval{ $dataset->getV( $expr->eval($dataset) );};
|
|
535
|
|
|
|
|
1220
|
|
778
|
535
|
50
|
|
|
|
5473
|
if($@){
|
779
|
0
|
|
|
|
|
0
|
$r = "[Error: $@ in evalExpr]";
|
780
|
0
|
|
|
|
|
0
|
$r =~s/[\x0d\x0a]+//g;
|
781
|
|
|
|
|
|
|
}
|
782
|
535
|
|
|
|
|
1882
|
return $r;
|
783
|
|
|
|
|
|
|
}
|
784
|
|
|
|
|
|
|
sub evalExprList{
|
785
|
389
|
|
|
390
|
0
|
854
|
my($tmpl,$tag,$expr)=@_;
|
786
|
389
|
|
|
|
|
1023
|
my $dataset = new Text::Template::Compact::Dataset($tmpl,$tag);
|
787
|
389
|
|
|
|
|
725
|
my @list;
|
788
|
389
|
|
|
|
|
712
|
eval{ $dataset->getVlist( \@list,$expr->eval($dataset) ); };
|
|
389
|
|
|
|
|
1010
|
|
789
|
389
|
50
|
|
|
|
1156
|
if($@){
|
790
|
0
|
|
|
|
|
0
|
my $r = "[Error: $@ in evalExprList]";
|
791
|
0
|
|
|
|
|
0
|
$r =~s/[\x0d\x0a]+//g;
|
792
|
0
|
|
|
|
|
0
|
return $r;
|
793
|
|
|
|
|
|
|
}
|
794
|
389
|
|
|
|
|
1575
|
return @list;
|
795
|
|
|
|
|
|
|
}
|
796
|
|
|
|
|
|
|
sub evalExprKw{
|
797
|
2
|
|
|
3
|
0
|
6
|
my($tmpl,$tag,$expr)=@_;
|
798
|
2
|
|
|
|
|
6
|
my $dataset = new Text::Template::Compact::Dataset($tmpl,$tag);
|
799
|
2
|
|
|
|
|
4
|
my $path = eval{ $expr->eval($dataset); };
|
|
2
|
|
|
|
|
156
|
|
800
|
2
|
50
|
|
|
|
8
|
if($@){
|
801
|
0
|
|
|
|
|
0
|
my $r = "[Error: $@ in evalExprKw]";
|
802
|
0
|
|
|
|
|
0
|
$r =~s/[\x0d\x0a]+//g;
|
803
|
0
|
|
|
|
|
0
|
return $r;
|
804
|
|
|
|
|
|
|
}
|
805
|
2
|
|
|
|
|
7
|
$path = $dataset->endoflist($path);
|
806
|
2
|
50
|
|
|
|
18
|
return $path->[1] if $path->[0] =~/[ki]/;
|
807
|
|
|
|
|
|
|
|
808
|
0
|
|
|
|
|
0
|
my $v = eval{ $dataset->getV( $path );};
|
|
0
|
|
|
|
|
0
|
|
809
|
0
|
0
|
|
|
|
0
|
if($@){
|
810
|
0
|
|
|
|
|
0
|
my $r = "[Error: $@ in evalExprKw]";
|
811
|
0
|
|
|
|
|
0
|
$r =~s/[\x0d\x0a]+//g;
|
812
|
0
|
|
|
|
|
0
|
return $r;
|
813
|
|
|
|
|
|
|
}
|
814
|
0
|
|
|
|
|
0
|
return $v;
|
815
|
|
|
|
|
|
|
}
|
816
|
|
|
|
|
|
|
|
817
|
|
|
|
|
|
|
|
818
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
sub setExprValue{
|
820
|
356
|
|
|
357
|
0
|
804
|
my($tmpl,$tag,$expr,$newval)=@_;
|
821
|
356
|
|
|
|
|
966
|
my $dataset = new Text::Template::Compact::Dataset($tmpl,$tag);
|
822
|
356
|
|
|
|
|
954
|
my $path = $expr->eval($dataset);
|
823
|
356
|
|
|
|
|
632
|
my $r = eval{ $dataset->setV($path,$newval);};
|
|
356
|
|
|
|
|
896
|
|
824
|
356
|
50
|
|
|
|
936
|
if($@){
|
825
|
0
|
|
|
|
|
0
|
$r = "[Error: $@ in setExprValue]";
|
826
|
0
|
|
|
|
|
0
|
$r =~s/[\x0d\x0a]+//g;
|
827
|
|
|
|
|
|
|
}
|
828
|
356
|
|
|
|
|
1076
|
return $r;
|
829
|
|
|
|
|
|
|
}
|
830
|
|
|
|
|
|
|
|
831
|
|
|
|
|
|
|
# eat specified token at head of the list. otherwise return undef.
|
832
|
|
|
|
|
|
|
sub eatType{
|
833
|
20
|
|
|
21
|
0
|
48
|
my($list,$type)=@_;
|
834
|
20
|
50
|
33
|
|
|
164
|
if( @$list and ref($list->[0]) and $list->[0]->{$type} ){
|
|
|
|
33
|
|
|
|
|
835
|
20
|
|
|
|
|
115
|
return shift @$list;
|
836
|
|
|
|
|
|
|
}
|
837
|
0
|
|
|
|
|
0
|
return;
|
838
|
|
|
|
|
|
|
}
|
839
|
|
|
|
|
|
|
|
840
|
|
|
|
|
|
|
######################################
|
841
|
|
|
|
|
|
|
|
842
|
|
|
|
|
|
|
|
843
|
|
|
|
|
|
|
# print %eval tag
|
844
|
|
|
|
|
|
|
sub print_eval{
|
845
|
6
|
|
|
7
|
0
|
18
|
my($tmpl,$tag)=@_;
|
846
|
6
|
|
|
|
|
26
|
$tmpl->evalExpr($tag,$tag->{expr});
|
847
|
6
|
|
|
|
|
12
|
return;
|
848
|
|
|
|
|
|
|
}
|
849
|
|
|
|
|
|
|
|
850
|
|
|
|
|
|
|
# print %var tag
|
851
|
|
|
|
|
|
|
sub print_var{
|
852
|
389
|
|
|
390
|
0
|
820
|
my($tmpl,$tag)=@_;
|
853
|
389
|
|
|
|
|
710
|
my $printer = $tmpl->{printer};
|
854
|
389
|
|
|
|
|
1339
|
my $filter = dor( $tag->{filter} ,$tmpl->{filter_default} );
|
855
|
389
|
|
|
|
|
1377
|
for my $value ( $tmpl->evalExprList($tag,$tag->{expr}) ){
|
856
|
449
|
|
|
|
|
1174
|
$value = dor($value,$tmpl->{undef_supply});
|
857
|
449
|
|
|
|
|
1066
|
$printer->( $filter->($value));
|
858
|
|
|
|
|
|
|
}
|
859
|
389
|
|
|
|
|
7137
|
return;
|
860
|
|
|
|
|
|
|
}
|
861
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
sub evalLabel($$$){
|
863
|
8
|
|
|
9
|
0
|
23
|
my($tmpl,$tag,$label)=@_;
|
864
|
8
|
100
|
|
|
|
33
|
return '' if not defined $label;
|
865
|
2
|
|
|
|
|
9
|
return $tmpl->evalExprKw($tag,$label);
|
866
|
|
|
|
|
|
|
}
|
867
|
|
|
|
|
|
|
|
868
|
|
|
|
|
|
|
# print %for tag
|
869
|
|
|
|
|
|
|
sub print_for{
|
870
|
20
|
|
|
21
|
0
|
57
|
my($tmpl,$tag)=@_;
|
871
|
20
|
|
|
|
|
84
|
my $list = $tmpl->evalExpr($tag,$tag->{listname});
|
872
|
20
|
|
|
|
|
48
|
my $index = 0;
|
873
|
20
|
100
|
|
|
|
80
|
$tag->{indexstart} and $index = $tmpl->evalExpr($tag,$tag->{indexstart});
|
874
|
20
|
|
|
|
|
53
|
for my $v (@$list){
|
875
|
139
|
|
|
|
|
258
|
my $oldr;
|
876
|
|
|
|
|
|
|
my $oldi;
|
877
|
139
|
50
|
|
|
|
409
|
if($tag->{itemname}){
|
878
|
139
|
|
|
|
|
402
|
$oldr = $tmpl->setExprValue($tag,$tag->{itemname},$v);
|
879
|
139
|
50
|
|
|
|
421
|
ref($oldr) or $tmpl->{printer}->($oldr);
|
880
|
|
|
|
|
|
|
}
|
881
|
139
|
100
|
|
|
|
421
|
if($tag->{indexname}){
|
882
|
4
|
|
|
|
|
18
|
$oldi = $tmpl->setExprValue($tag,$tag->{indexname},$index++);
|
883
|
4
|
50
|
|
|
|
15
|
ref($oldi) or $tmpl->{printer}->($oldi);
|
884
|
|
|
|
|
|
|
}
|
885
|
139
|
|
|
|
|
415
|
my $exit_tag = $tmpl->printBlock( $tag->{block} );
|
886
|
139
|
50
|
|
|
|
697
|
ref($oldr) and $tmpl->setExprValue($tag,$tag->{itemname} ,$$oldr);
|
887
|
139
|
100
|
|
|
|
419
|
ref($oldi) and $tmpl->setExprValue($tag,$tag->{indexname} ,$$oldi);
|
888
|
|
|
|
|
|
|
|
889
|
139
|
100
|
|
|
|
518
|
if($exit_tag){
|
890
|
|
|
|
|
|
|
# not for this block?
|
891
|
7
|
100
|
|
|
|
22
|
return $exit_tag if dor($tag->{label},'') ne evalLabel($tmpl,$tag,$exit_tag->{label});
|
892
|
|
|
|
|
|
|
# for this block.
|
893
|
6
|
50
|
|
|
|
21
|
next if $exit_tag->{continue};
|
894
|
6
|
50
|
|
|
|
20
|
last if $exit_tag->{break};
|
895
|
|
|
|
|
|
|
}
|
896
|
|
|
|
|
|
|
}
|
897
|
19
|
|
|
|
|
78
|
return;
|
898
|
|
|
|
|
|
|
}
|
899
|
|
|
|
|
|
|
|
900
|
|
|
|
|
|
|
sub print_while{
|
901
|
3
|
|
|
4
|
0
|
9
|
my($tmpl,$tag)=@_;
|
902
|
3
|
50
|
|
|
|
17
|
$tag->{ex_init} and $tmpl->evalExpr($tag,$tag->{ex_init});
|
903
|
3
|
|
|
|
|
6
|
my $exit_tag;
|
904
|
3
|
|
|
|
|
43
|
for(;;){
|
905
|
30
|
100
|
100
|
|
|
100
|
last if $tag->{ex_precheck} and not $tmpl->evalExpr($tag,$tag->{ex_precheck});
|
906
|
29
|
|
|
|
|
78
|
$exit_tag = $tmpl->printBlock( $tag->{block} );
|
907
|
29
|
100
|
|
|
|
73
|
if($exit_tag){
|
908
|
|
|
|
|
|
|
# not for this block?
|
909
|
1
|
50
|
|
|
|
6
|
last if dor($tag->{label},'') ne evalLabel($tmpl,$tag,$exit_tag->{label});
|
910
|
|
|
|
|
|
|
# for this block.
|
911
|
1
|
50
|
|
|
|
6
|
if($exit_tag->{break}){
|
912
|
1
|
|
|
|
|
4
|
undef $exit_tag;
|
913
|
1
|
|
|
|
|
3
|
last;
|
914
|
|
|
|
|
|
|
}
|
915
|
|
|
|
|
|
|
}
|
916
|
28
|
100
|
100
|
|
|
106
|
last if $tag->{ex_postcheck} and not $tmpl->evalExpr($tag,$tag->{ex_postcheck});
|
917
|
27
|
50
|
|
|
|
116
|
$tag->{ex_step} and $tmpl->evalExpr($tag,$tag->{ex_step});
|
918
|
|
|
|
|
|
|
}
|
919
|
3
|
100
|
|
|
|
18
|
$tag->{ex_final} and $tmpl->evalExpr($tag,$tag->{ex_final});
|
920
|
3
|
|
|
|
|
11
|
return $exit_tag;
|
921
|
|
|
|
|
|
|
}
|
922
|
|
|
|
|
|
|
|
923
|
|
|
|
|
|
|
# print %blockpaste tag
|
924
|
|
|
|
|
|
|
sub print_block{
|
925
|
6
|
|
|
7
|
0
|
20
|
my($tmpl,$tag)=@_;
|
926
|
6
|
|
|
|
|
20
|
my $block = $tmpl->{block}{$tag->{name}};
|
927
|
6
|
50
|
|
|
|
22
|
if(not defined($block) ){
|
928
|
0
|
|
|
|
|
0
|
$tmpl->{printer}->( "[Error: block '$tag->{name}' is not defined]" );
|
929
|
0
|
|
|
|
|
0
|
return;
|
930
|
|
|
|
|
|
|
}
|
931
|
6
|
|
|
|
|
26
|
my $exit_tag = $tmpl->printBlock( $block );
|
932
|
6
|
50
|
|
|
|
25
|
return if not $exit_tag;
|
933
|
|
|
|
|
|
|
# not for this block?
|
934
|
0
|
0
|
|
|
|
0
|
return $exit_tag if dor($tag->{label},'') ne evalLabel($tmpl,$tag,$exit_tag->{label});
|
935
|
|
|
|
|
|
|
# for this block.
|
936
|
|
|
|
|
|
|
# no difference between break or continue, just exit this block.
|
937
|
0
|
|
|
|
|
0
|
return;
|
938
|
|
|
|
|
|
|
}
|
939
|
|
|
|
|
|
|
|
940
|
|
|
|
|
|
|
# print %eval tag
|
941
|
|
|
|
|
|
|
sub print_evalperl{
|
942
|
74
|
|
|
75
|
0
|
168
|
my($tmpl,$tag)=@_;
|
943
|
74
|
|
|
|
|
163
|
local $_ = $tmpl->{param};
|
944
|
74
|
|
|
|
|
167
|
my $code = $tag->{code};
|
945
|
74
|
|
|
|
|
136
|
my @data = map{ $tmpl->evalExpr($tag,$_) } @{$tag->{args}};
|
|
34
|
|
|
|
|
97
|
|
|
74
|
|
|
|
|
231
|
|
946
|
74
|
|
|
|
|
152
|
my $a_code =ord('a');
|
947
|
74
|
100
|
|
|
|
249
|
@data and $code = "my(".join(',',map{my $c=chr($_+$a_code);"\$$c"}(0..$#data)).")=\@data;$code";
|
|
34
|
|
|
|
|
114
|
|
|
34
|
|
|
|
|
174
|
|
948
|
74
|
|
|
3
|
|
5954
|
my $r = eval "{no warnings; $code;}";
|
|
2
|
|
|
3
|
|
17
|
|
|
2
|
|
|
3
|
|
5
|
|
|
2
|
|
|
3
|
|
83
|
|
|
2
|
|
|
2
|
|
16
|
|
|
2
|
|
|
2
|
|
6
|
|
|
2
|
|
|
2
|
|
67
|
|
|
2
|
|
|
2
|
|
12
|
|
|
2
|
|
|
2
|
|
6
|
|
|
2
|
|
|
2
|
|
74
|
|
|
2
|
|
|
2
|
|
12
|
|
|
2
|
|
|
2
|
|
6
|
|
|
2
|
|
|
2
|
|
61
|
|
|
2
|
|
|
2
|
|
16
|
|
|
2
|
|
|
2
|
|
4
|
|
|
2
|
|
|
2
|
|
59
|
|
|
2
|
|
|
2
|
|
17
|
|
|
2
|
|
|
2
|
|
5
|
|
|
2
|
|
|
2
|
|
94
|
|
|
2
|
|
|
2
|
|
16
|
|
|
2
|
|
|
2
|
|
6
|
|
|
2
|
|
|
2
|
|
90
|
|
|
2
|
|
|
2
|
|
17
|
|
|
2
|
|
|
2
|
|
5
|
|
|
2
|
|
|
2
|
|
84
|
|
|
2
|
|
|
2
|
|
16
|
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
87
|
|
|
2
|
|
|
|
|
16
|
|
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
83
|
|
|
2
|
|
|
|
|
17
|
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
87
|
|
|
2
|
|
|
|
|
17
|
|
|
2
|
|
|
|
|
7
|
|
|
2
|
|
|
|
|
85
|
|
|
2
|
|
|
|
|
19
|
|
|
2
|
|
|
|
|
7
|
|
|
2
|
|
|
|
|
91
|
|
|
2
|
|
|
|
|
17
|
|
|
2
|
|
|
|
|
7
|
|
|
2
|
|
|
|
|
125
|
|
|
2
|
|
|
|
|
16
|
|
|
2
|
|
|
|
|
7
|
|
|
2
|
|
|
|
|
58
|
|
|
2
|
|
|
|
|
17
|
|
|
2
|
|
|
|
|
7
|
|
|
2
|
|
|
|
|
61
|
|
|
2
|
|
|
|
|
16
|
|
|
2
|
|
|
|
|
7
|
|
|
2
|
|
|
|
|
93
|
|
|
2
|
|
|
|
|
29
|
|
|
2
|
|
|
|
|
8
|
|
|
2
|
|
|
|
|
110
|
|
|
2
|
|
|
|
|
26
|
|
|
2
|
|
|
|
|
8
|
|
|
2
|
|
|
|
|
148
|
|
|
2
|
|
|
|
|
17
|
|
|
2
|
|
|
|
|
31
|
|
|
2
|
|
|
|
|
88
|
|
|
2
|
|
|
|
|
15
|
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
63
|
|
|
2
|
|
|
|
|
13
|
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
59
|
|
|
2
|
|
|
|
|
16
|
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
87
|
|
|
2
|
|
|
|
|
16
|
|
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
77
|
|
|
2
|
|
|
|
|
18
|
|
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
109
|
|
|
2
|
|
|
|
|
18
|
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
75
|
|
949
|
74
|
100
|
|
|
|
331
|
$@ and $tmpl->{printer}->( "[eval failed: $@]");
|
950
|
74
|
100
|
|
|
|
476
|
$tag->{result} and $tmpl->setExprValue($tag,$tag->{result},$r);
|
951
|
74
|
|
|
|
|
226
|
return;
|
952
|
|
|
|
|
|
|
}
|
953
|
|
|
|
|
|
|
|
954
|
|
|
|
|
|
|
|
955
|
|
|
|
|
|
|
# print %else tag
|
956
|
|
|
|
|
|
|
sub print_else{
|
957
|
175
|
|
|
176
|
0
|
334
|
my($tmpl,$tag)=@_;
|
958
|
|
|
|
|
|
|
|
959
|
175
|
|
|
|
|
503
|
my $exit_tag = $tmpl->printBlock( $tag->{block} );
|
960
|
|
|
|
|
|
|
|
961
|
|
|
|
|
|
|
# normally 'if' is not match for break,continue
|
962
|
|
|
|
|
|
|
# match only label is explicitly specified in both of block and break.
|
963
|
175
|
50
|
100
|
|
|
506
|
if( $exit_tag
|
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
964
|
|
|
|
|
|
|
and defined($exit_tag->{label})
|
965
|
|
|
|
|
|
|
and defined($tag->{label})
|
966
|
|
|
|
|
|
|
and $exit_tag->{label} eq $tag->{label}
|
967
|
|
|
|
|
|
|
){
|
968
|
|
|
|
|
|
|
# exit_tag is solved in this scope.
|
969
|
0
|
|
|
|
|
0
|
return;
|
970
|
|
|
|
|
|
|
}
|
971
|
175
|
|
|
|
|
393
|
return $exit_tag;
|
972
|
|
|
|
|
|
|
}
|
973
|
|
|
|
|
|
|
|
974
|
|
|
|
|
|
|
# print %if tag
|
975
|
|
|
|
|
|
|
sub print_if_simple{
|
976
|
275
|
|
|
276
|
0
|
541
|
my($tmpl,$tag)=@_;
|
977
|
275
|
|
|
|
|
670
|
my $value = $tmpl->evalExpr($tag,$tag->{expr});
|
978
|
275
|
100
|
|
|
|
725
|
$value and return print_else($tmpl,$tag);
|
979
|
166
|
|
|
|
|
317
|
$tag=$tag->{next};
|
980
|
166
|
100
|
|
|
|
428
|
$tag->{printer} and return $tag->{printer}($tmpl,$tag);
|
981
|
142
|
|
|
|
|
263
|
return;
|
982
|
|
|
|
|
|
|
}
|
983
|
|
|
|
|
|
|
|
984
|
|
|
|
|
|
|
# print %if tag
|
985
|
|
|
|
|
|
|
sub print_if_code{
|
986
|
126
|
|
|
127
|
0
|
320
|
my($tmpl,$tag)=@_;
|
987
|
126
|
|
|
|
|
211
|
my @data = map{ $tmpl->evalExpr($tag,$_) } @{$tag->{args}};
|
|
138
|
|
|
|
|
360
|
|
|
126
|
|
|
|
|
327
|
|
988
|
126
|
|
|
|
|
309
|
my $code = $tag->{code};
|
989
|
126
|
|
|
|
|
228
|
my $a_code =ord('a');
|
990
|
126
|
50
|
|
|
|
528
|
@data and $code = "my(".join(',',map{my $c=chr($_+$a_code);"\$$c"}(0..$#data)).")=\@data;$code";
|
|
138
|
|
|
|
|
323
|
|
|
138
|
|
|
|
|
543
|
|
991
|
126
|
|
|
|
|
270
|
local $_ = $tmpl->{param};
|
992
|
126
|
|
|
2
|
|
8624
|
my $value = eval "no warnings; $code";
|
|
2
|
|
|
2
|
|
16
|
|
|
2
|
|
|
2
|
|
5
|
|
|
2
|
|
|
2
|
|
115
|
|
|
2
|
|
|
2
|
|
14
|
|
|
2
|
|
|
2
|
|
4
|
|
|
2
|
|
|
2
|
|
69
|
|
|
2
|
|
|
2
|
|
13
|
|
|
2
|
|
|
2
|
|
6
|
|
|
2
|
|
|
2
|
|
64
|
|
|
2
|
|
|
2
|
|
15
|
|
|
2
|
|
|
2
|
|
5
|
|
|
2
|
|
|
2
|
|
69
|
|
|
2
|
|
|
2
|
|
14
|
|
|
2
|
|
|
2
|
|
5
|
|
|
2
|
|
|
|
|
61
|
|
|
2
|
|
|
|
|
13
|
|
|
2
|
|
|
|
|
7
|
|
|
2
|
|
|
|
|
62
|
|
|
2
|
|
|
|
|
12
|
|
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
63
|
|
|
2
|
|
|
|
|
13
|
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
66
|
|
|
2
|
|
|
|
|
15
|
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
66
|
|
|
2
|
|
|
|
|
16
|
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
71
|
|
|
2
|
|
|
|
|
18
|
|
|
2
|
|
|
|
|
7
|
|
|
2
|
|
|
|
|
82
|
|
|
2
|
|
|
|
|
14
|
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
70
|
|
|
2
|
|
|
|
|
13
|
|
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
60
|
|
|
2
|
|
|
|
|
16
|
|
|
2
|
|
|
|
|
7
|
|
|
2
|
|
|
|
|
76
|
|
|
2
|
|
|
|
|
18
|
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
79
|
|
993
|
126
|
50
|
|
|
|
453
|
$@ and $tmpl->{printer}->( "[eval failed: $@]");
|
994
|
|
|
|
|
|
|
|
995
|
126
|
100
|
|
|
|
376
|
$value and return print_else($tmpl,$tag);
|
996
|
72
|
|
|
|
|
171
|
$tag=$tag->{next};
|
997
|
72
|
100
|
|
|
|
258
|
$tag->{printer} and return $tag->{printer}($tmpl,$tag);
|
998
|
48
|
|
|
|
|
132
|
return;
|
999
|
|
|
|
|
|
|
}
|
1000
|
|
|
|
|
|
|
|
1001
|
|
|
|
|
|
|
#####################################################
|
1002
|
|
|
|
|
|
|
|
1003
|
|
|
|
|
|
|
# parse template tag
|
1004
|
|
|
|
|
|
|
sub parseTemplateTag{
|
1005
|
300
|
|
|
301
|
0
|
633
|
my($self,$text)=@_;
|
1006
|
|
|
|
|
|
|
|
1007
|
|
|
|
|
|
|
# split to token list
|
1008
|
300
|
|
|
3
|
|
3434
|
my @list = $text =~ /$Text::Template::Compact::ExprParser::token_re|"(?:[^"]|"")*"|[\w_]+|\p{IsWord}+/g;
|
|
2
|
|
|
|
|
17
|
|
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
28
|
|
1009
|
300
|
50
|
|
|
|
35748
|
@list or die $self->parseError("empty template tag");
|
1010
|
|
|
|
|
|
|
|
1011
|
|
|
|
|
|
|
# parse filter
|
1012
|
300
|
|
|
|
|
500
|
my $filter;
|
1013
|
300
|
100
|
100
|
|
|
1536
|
if( @list >= 2 and $filter_map{ $list[-1] } and $list[-2] eq '#' ){
|
|
|
|
66
|
|
|
|
|
1014
|
8
|
|
|
|
|
21
|
$filter = $filter_map{ $list[@list-1] };
|
1015
|
8
|
|
|
|
|
21
|
splice @list,@list-2;
|
1016
|
|
|
|
|
|
|
}
|
1017
|
|
|
|
|
|
|
|
1018
|
300
|
|
|
|
|
647
|
my @taglist;
|
1019
|
|
|
|
|
|
|
my $type;
|
1020
|
300
|
|
|
|
|
758
|
while(@list){
|
1021
|
352
|
100
|
|
|
|
928
|
if($list[0] eq ';'){
|
1022
|
29
|
|
|
|
|
47
|
shift @list;
|
1023
|
29
|
|
|
|
|
82
|
next;
|
1024
|
|
|
|
|
|
|
}
|
1025
|
|
|
|
|
|
|
|
1026
|
323
|
|
|
|
|
958
|
my $item = {lno=>$self->{lno}};
|
1027
|
323
|
100
|
|
|
|
793
|
$filter and $item->{filter} = $filter;
|
1028
|
|
|
|
|
|
|
|
1029
|
|
|
|
|
|
|
# read label:
|
1030
|
323
|
100
|
100
|
|
|
1423
|
if( @list >= 2
|
|
|
|
66
|
|
|
|
|
1031
|
|
|
|
|
|
|
and $list[1] eq ':'
|
1032
|
|
|
|
|
|
|
and $list[0] =~/^\w/
|
1033
|
|
|
|
|
|
|
){
|
1034
|
1
|
|
|
|
|
5
|
$item->{label} = $list[0];
|
1035
|
1
|
|
|
|
|
3
|
splice @list,0,2;
|
1036
|
1
|
50
|
|
|
|
4
|
last if not @list;
|
1037
|
|
|
|
|
|
|
}
|
1038
|
|
|
|
|
|
|
|
1039
|
|
|
|
|
|
|
# % type
|
1040
|
323
|
100
|
|
|
|
786
|
if( $list[0] eq '%' ){
|
1041
|
|
|
|
|
|
|
# skip '%'
|
1042
|
180
|
|
|
|
|
307
|
shift @list;
|
1043
|
|
|
|
|
|
|
# read type of tag
|
1044
|
180
|
50
|
|
|
|
432
|
@list or $self->parseError("no tag type after '%'");
|
1045
|
180
|
|
|
|
|
449
|
$type = lc decodeQuote(shift @list);
|
1046
|
|
|
|
|
|
|
}else{
|
1047
|
143
|
|
|
|
|
252
|
$type = 'print';
|
1048
|
|
|
|
|
|
|
}
|
1049
|
|
|
|
|
|
|
|
1050
|
323
|
|
|
|
|
1192
|
$item->{$item->{type}=$type}=1;
|
1051
|
|
|
|
|
|
|
|
1052
|
323
|
100
|
100
|
|
|
2173
|
if( $type eq 'print' ){
|
|
|
100
|
100
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
1053
|
|
|
|
|
|
|
# %print expr,expr...
|
1054
|
150
|
|
|
|
|
364
|
$item->{printer}=\&print_var;
|
1055
|
150
|
|
|
|
|
436
|
$item->{expr} = $self->parseExpr(\@list);
|
1056
|
|
|
|
|
|
|
|
1057
|
|
|
|
|
|
|
}elsif( $type eq 'eval' ){
|
1058
|
|
|
|
|
|
|
# %print expr,expr...
|
1059
|
6
|
|
|
|
|
19
|
$item->{printer}=\&print_eval;
|
1060
|
6
|
|
|
|
|
24
|
$item->{expr} = $self->parseExpr(\@list);
|
1061
|
|
|
|
|
|
|
|
1062
|
|
|
|
|
|
|
}elsif( $type eq 'if' or $type eq 'elsif' ){
|
1063
|
|
|
|
|
|
|
# %if expr
|
1064
|
|
|
|
|
|
|
# %elsif expr
|
1065
|
25
|
|
|
|
|
73
|
$item->{printer}=\&print_if_simple;
|
1066
|
25
|
|
|
|
|
95
|
$item->{expr} = $self->parseExpr(\@list);
|
1067
|
|
|
|
|
|
|
|
1068
|
|
|
|
|
|
|
}elsif( $type eq 'ifc' or $type eq 'elsifc' ){
|
1069
|
|
|
|
|
|
|
# %ifc "code" dataspec dataspec ...
|
1070
|
|
|
|
|
|
|
# %elsifc "code" dataspec dataspec ...
|
1071
|
14
|
|
|
|
|
32
|
$item->{printer}=\&print_if_code;
|
1072
|
14
|
|
|
|
|
32
|
$item->{code} =decodeQuote(shift @list);
|
1073
|
14
|
|
|
|
|
48
|
$item->{args}=[];
|
1074
|
14
|
|
66
|
|
|
69
|
while(@list and $list[0] ne ';' ){
|
1075
|
15
|
|
|
|
|
29
|
push @{$item->{args}},$self->parseExpr(\@list);
|
|
15
|
|
|
|
|
106
|
|
1076
|
|
|
|
|
|
|
}
|
1077
|
|
|
|
|
|
|
|
1078
|
|
|
|
|
|
|
}elsif( $type eq 'else'){
|
1079
|
|
|
|
|
|
|
# %else
|
1080
|
4
|
|
|
|
|
16
|
$item->{printer}=\&print_else;
|
1081
|
|
|
|
|
|
|
|
1082
|
|
|
|
|
|
|
}elsif( $type eq 'end'){
|
1083
|
|
|
|
|
|
|
# %end
|
1084
|
|
|
|
|
|
|
|
1085
|
|
|
|
|
|
|
}elsif( $type eq 'break' or $type eq 'continue' ){
|
1086
|
|
|
|
|
|
|
# %break [label]
|
1087
|
|
|
|
|
|
|
# %continue [label]
|
1088
|
3
|
100
|
66
|
|
|
22
|
if( @list and $list[0] ne ';'){
|
1089
|
1
|
|
|
|
|
5
|
$item->{label} = $self->parseExpr(\@list);
|
1090
|
|
|
|
|
|
|
}
|
1091
|
|
|
|
|
|
|
|
1092
|
|
|
|
|
|
|
}elsif( $type eq 'end'){
|
1093
|
|
|
|
|
|
|
# %end
|
1094
|
|
|
|
|
|
|
|
1095
|
|
|
|
|
|
|
}elsif( $type eq 'for' ){
|
1096
|
|
|
|
|
|
|
# %for item in list indexname indexstart
|
1097
|
15
|
|
|
|
|
70
|
$item->{printer}=\&print_for;
|
1098
|
15
|
|
|
|
|
63
|
$item->{itemname} = $self->parseExpr(\@list);
|
1099
|
|
|
|
|
|
|
|
1100
|
15
|
50
|
33
|
|
|
101
|
(not @list or not $list[0] eq 'in' ) and $self->parseError("expected 'in' keyword is not found.");
|
1101
|
15
|
|
|
|
|
32
|
shift @list;
|
1102
|
|
|
|
|
|
|
|
1103
|
15
|
|
|
|
|
59
|
$item->{listname} = $self->parseExpr(\@list);
|
1104
|
|
|
|
|
|
|
|
1105
|
15
|
100
|
100
|
|
|
91
|
(@list and $list[0] ne ';') and $item->{indexname} = $self->parseExpr(\@list);
|
1106
|
15
|
100
|
100
|
|
|
76
|
(@list and $list[0] ne ';') and $item->{indexstart} = $self->parseExpr(\@list);
|
1107
|
|
|
|
|
|
|
|
1108
|
|
|
|
|
|
|
}elsif( $type eq 'while' ){
|
1109
|
|
|
|
|
|
|
# %for item in list indexname indexstart
|
1110
|
3
|
|
|
|
|
13
|
$item->{printer}=\&print_while;
|
1111
|
3
|
|
66
|
|
|
20
|
Loop: while( @list and $list[0] ne ';' ){
|
1112
|
10
|
|
|
|
|
25
|
for (qw( init precheck postcheck step final )){
|
1113
|
28
|
100
|
|
|
|
60
|
if( $list[0] eq $_ ){
|
1114
|
10
|
|
|
|
|
15
|
shift @list;
|
1115
|
10
|
|
|
|
|
32
|
$item->{"ex_$_"} = $self->parseExpr(\@list);
|
1116
|
10
|
|
|
|
|
50
|
next Loop;
|
1117
|
|
|
|
|
|
|
}
|
1118
|
|
|
|
|
|
|
}
|
1119
|
0
|
|
|
|
|
0
|
$self->parseError("expected 'init/precheck/postcheck/step/final' not found.");
|
1120
|
|
|
|
|
|
|
}
|
1121
|
|
|
|
|
|
|
|
1122
|
|
|
|
|
|
|
}elsif( $type eq 'blockdefine' or $type eq 'blockpaste' ){
|
1123
|
|
|
|
|
|
|
# %blockdefine blockname
|
1124
|
|
|
|
|
|
|
# %blockpaste blockname
|
1125
|
8
|
|
|
|
|
22
|
$item->{printer}=\&print_block;
|
1126
|
8
|
50
|
|
|
|
22
|
@list or $self->parseError("no block name after $type");
|
1127
|
8
|
|
|
|
|
21
|
$item->{name} = decodeQuote(shift @list);
|
1128
|
8
|
100
|
|
|
|
26
|
if( $type eq 'blockdefine' ){
|
1129
|
2
|
50
|
|
|
|
10
|
defined( $self->{block}{$item->{name}} ) and $self->parseError("redefined block '$item->{name}'");
|
1130
|
2
|
|
|
|
|
9
|
$self->{block}{$item->{name}} = [];
|
1131
|
|
|
|
|
|
|
}
|
1132
|
|
|
|
|
|
|
}elsif( $type eq 'evalperl' ){
|
1133
|
|
|
|
|
|
|
# %evalperl "code" [result] [arg]...
|
1134
|
44
|
|
|
|
|
117
|
$item->{printer}=\&print_evalperl;
|
1135
|
44
|
50
|
|
|
|
108
|
@list or $self->parseError("no text after 'evalperl'");
|
1136
|
44
|
50
|
|
|
|
167
|
$list[0] =~ /^"/ or $self->parseError("you must quote code with \"...\"");
|
1137
|
44
|
|
|
|
|
99
|
$item->{code} = decodeQuote(shift @list);
|
1138
|
44
|
100
|
|
|
|
161
|
@list and $item->{result} = $self->parseExpr(\@list);
|
1139
|
44
|
|
|
|
|
112
|
$item->{args} = [];
|
1140
|
44
|
|
66
|
|
|
162
|
while(@list and $list[0] ne ';' ){
|
1141
|
4
|
|
|
|
|
13
|
push @{$item->{args}},$self->parseExpr(\@list);
|
|
4
|
|
|
|
|
19
|
|
1142
|
|
|
|
|
|
|
}
|
1143
|
|
|
|
|
|
|
}else{
|
1144
|
|
|
|
|
|
|
# unsupported tag type
|
1145
|
0
|
|
|
|
|
0
|
$self->parseError("unsupported tag type '$type'");
|
1146
|
|
|
|
|
|
|
}
|
1147
|
323
|
50
|
66
|
|
|
1012
|
@list and $list[0] ne ';' and $self->parseError("unexpected token '$list[0]' in template tag");
|
1148
|
323
|
|
|
|
|
968
|
push @taglist,$item;
|
1149
|
|
|
|
|
|
|
}
|
1150
|
300
|
|
|
|
|
952
|
return @taglist;
|
1151
|
|
|
|
|
|
|
}
|
1152
|
|
|
|
|
|
|
|
1153
|
|
|
|
|
|
|
# compose tree of tag and text.
|
1154
|
|
|
|
|
|
|
sub parseBlock{
|
1155
|
125
|
|
|
126
|
0
|
253
|
my($self,$rList,$block)=@_;
|
1156
|
|
|
|
|
|
|
|
1157
|
125
|
|
|
|
|
308
|
while(@$rList){
|
1158
|
569
|
|
|
|
|
1043
|
my $item = $rList->[0];
|
1159
|
|
|
|
|
|
|
# normal text
|
1160
|
569
|
100
|
|
|
|
1193
|
if( not ref($item) ){
|
1161
|
246
|
|
|
|
|
449
|
push @$block, shift @$rList;
|
1162
|
246
|
|
|
|
|
596
|
next;
|
1163
|
|
|
|
|
|
|
}
|
1164
|
|
|
|
|
|
|
# exit before end of block
|
1165
|
323
|
100
|
|
|
|
597
|
last if grep {$item->{type} eq $_} qw( end else elsif elsifc );
|
|
1292
|
|
|
|
|
2823
|
|
1166
|
|
|
|
|
|
|
|
1167
|
|
|
|
|
|
|
# %blockdefine
|
1168
|
260
|
100
|
|
|
|
578
|
if( $item->{blockdefine} ){
|
1169
|
2
|
|
|
|
|
6
|
shift @$rList;
|
1170
|
2
|
|
|
|
|
11
|
$self->parseBlock( $rList,$self->{block}{$item->{name}});
|
1171
|
2
|
50
|
|
|
|
8
|
eatType($rList,'end') or $self->parseError("missing end of blockdefine (start at $item->{lno})");
|
1172
|
2
|
|
|
|
|
15
|
next;
|
1173
|
|
|
|
|
|
|
}
|
1174
|
|
|
|
|
|
|
|
1175
|
|
|
|
|
|
|
# append to current block
|
1176
|
258
|
|
|
|
|
479
|
push @$block, shift @$rList;
|
1177
|
|
|
|
|
|
|
|
1178
|
|
|
|
|
|
|
# %for
|
1179
|
258
|
100
|
100
|
|
|
1067
|
if( $item->{for} or $item->{while} ){
|
1180
|
18
|
|
|
|
|
49
|
$item->{block} = [];
|
1181
|
18
|
|
|
|
|
77
|
$self->parseBlock( $rList ,$item->{block});
|
1182
|
18
|
50
|
|
|
|
58
|
eatType($rList,'end') or $self->parseError("missing end of $item->{type} loop (start at $item->{lno})");
|
1183
|
18
|
|
|
|
|
66
|
next;
|
1184
|
|
|
|
|
|
|
}
|
1185
|
|
|
|
|
|
|
|
1186
|
|
|
|
|
|
|
# %if ,%elsif,%else
|
1187
|
240
|
100
|
100
|
|
|
1044
|
if( $item->{if} or $item->{ifc}){
|
1188
|
31
|
|
|
|
|
49
|
for(;;$item = $item->{next}){
|
1189
|
43
|
|
|
|
|
88
|
$item->{block} = [];
|
1190
|
43
|
|
|
|
|
130
|
$self->parseBlock( $rList ,$item->{block});
|
1191
|
43
|
50
|
|
|
|
99
|
@$rList or $self->parseError("missing end of if/elsif/else/elsifc block (start at $item->{lno})");
|
1192
|
43
|
|
|
|
|
98
|
$item->{next} = shift @$rList;
|
1193
|
43
|
100
|
|
|
|
105
|
last if $item->{next}{end};
|
1194
|
12
|
50
|
33
|
|
|
44
|
$item->{label} and not defined($item->{next}->{label}) and $item->{next}->{label}=$item->{label};
|
1195
|
|
|
|
|
|
|
}
|
1196
|
31
|
|
|
|
|
71
|
next;
|
1197
|
|
|
|
|
|
|
}
|
1198
|
|
|
|
|
|
|
}
|
1199
|
|
|
|
|
|
|
}
|
1200
|
|
|
|
|
|
|
|
1201
|
|
|
|
|
|
|
sub closeLine{
|
1202
|
399
|
|
|
400
|
0
|
778
|
my($rAll,$rLine)=@_;
|
1203
|
|
|
|
|
|
|
my $a = grep{
|
1204
|
399
|
100
|
|
|
|
724
|
if( ref($_) ){
|
|
693
|
|
|
|
|
1363
|
|
1205
|
323
|
|
|
|
|
781
|
$_->{print};
|
1206
|
|
|
|
|
|
|
}else{
|
1207
|
370
|
100
|
|
|
|
1255
|
$_ =~ /[^\s ]/ ?1:0;
|
1208
|
|
|
|
|
|
|
}
|
1209
|
|
|
|
|
|
|
} @$rLine;
|
1210
|
399
|
100
|
|
|
|
882
|
if($a){
|
1211
|
275
|
|
|
|
|
572
|
for (@$rLine,"\x0a"){
|
1212
|
875
|
100
|
100
|
|
|
4069
|
if(not ref($_)
|
|
|
|
100
|
|
|
|
|
1213
|
|
|
|
|
|
|
and @$rAll
|
1214
|
|
|
|
|
|
|
and not ref($rAll->[-1])
|
1215
|
|
|
|
|
|
|
){
|
1216
|
386
|
|
|
|
|
1015
|
$rAll->[-1].= $_;
|
1217
|
|
|
|
|
|
|
}else{
|
1218
|
489
|
|
|
|
|
930
|
push @$rAll,$_;
|
1219
|
|
|
|
|
|
|
}
|
1220
|
|
|
|
|
|
|
}
|
1221
|
|
|
|
|
|
|
}else{
|
1222
|
124
|
|
|
|
|
249
|
for (@$rLine){
|
1223
|
93
|
100
|
|
|
|
295
|
ref($_) and push @$rAll,$_;
|
1224
|
|
|
|
|
|
|
}
|
1225
|
|
|
|
|
|
|
}
|
1226
|
399
|
|
|
|
|
979
|
@$rLine = ();
|
1227
|
|
|
|
|
|
|
}
|
1228
|
|
|
|
|
|
|
|
1229
|
|
|
|
|
|
|
# convert from source text to template structure.
|
1230
|
|
|
|
|
|
|
# $ok = $tmpl->loadText($filename,\$text [,$blockname]);
|
1231
|
|
|
|
|
|
|
sub loadText{
|
1232
|
62
|
|
|
63
|
0
|
25125
|
my $self = shift;
|
1233
|
62
|
|
|
|
|
163
|
$self->{error}=[];
|
1234
|
62
|
|
|
|
|
152
|
$self->{lno}=1;
|
1235
|
62
|
|
|
|
|
137
|
$self->{source_name} = $_[0];
|
1236
|
62
|
50
|
|
|
|
189
|
my $rText = ref($_[1])?$_[1]:\$_[1];
|
1237
|
62
|
|
50
|
|
|
323
|
my $blockname = ($_[2] || "");
|
1238
|
|
|
|
|
|
|
|
1239
|
|
|
|
|
|
|
# split source to tag and text
|
1240
|
62
|
|
|
|
|
125
|
my @list;
|
1241
|
|
|
|
|
|
|
my @line;
|
1242
|
62
|
|
|
|
|
109
|
my $lastend = 0;
|
1243
|
62
|
|
|
|
|
477
|
while( $$rText =~ /(\x0D\x0A|\x0D|\x0A)|(?
|
1244
|
699
|
|
|
|
|
18336
|
my $pre = substr($$rText,$lastend,$-[0] - $lastend); $lastend = $+[0];
|
|
699
|
|
|
|
|
17426
|
|
1245
|
699
|
100
|
|
|
|
1941
|
if( defined($1) ){
|
1246
|
399
|
|
|
|
|
864
|
$pre =~ s/\$\$\{/\$\{/g;
|
1247
|
399
|
100
|
|
|
|
1076
|
length($pre) and push @line,$pre;
|
1248
|
399
|
|
|
|
|
1124
|
closeLine(\@list,\@line);
|
1249
|
399
|
|
|
|
|
2599
|
++$self->{lno};
|
1250
|
|
|
|
|
|
|
}else{
|
1251
|
300
|
|
|
|
|
805
|
my $inside = substr($2,2);
|
1252
|
300
|
|
|
|
|
696
|
$pre =~ s/\$\$\{/\$\{/g;
|
1253
|
300
|
100
|
|
|
|
866
|
length($pre) and push @line,$pre;
|
1254
|
300
|
|
|
|
|
598
|
push @line,eval{ $self->parseTemplateTag($inside);};
|
|
300
|
|
|
|
|
775
|
|
1255
|
300
|
|
|
|
|
2171
|
$self->{lno} += $inside =~ tr/\x0a/\x0a/;
|
1256
|
|
|
|
|
|
|
}
|
1257
|
|
|
|
|
|
|
}
|
1258
|
62
|
50
|
|
|
|
172
|
if( $lastend < length($$rText) ){
|
1259
|
0
|
|
|
|
|
0
|
my $text =substr($$rText,$lastend);
|
1260
|
0
|
|
|
|
|
0
|
$text =~ s/\$\$\{/\$\{/g;
|
1261
|
0
|
|
|
|
|
0
|
warn "left=[$text]\n";
|
1262
|
0
|
|
|
|
|
0
|
push @line,$text;
|
1263
|
0
|
|
|
|
|
0
|
closeLine(\@list,\@line);
|
1264
|
|
|
|
|
|
|
}
|
1265
|
|
|
|
|
|
|
|
1266
|
|
|
|
|
|
|
# parse control block
|
1267
|
62
|
|
|
|
|
158
|
$self->{block}{$blockname} = [];
|
1268
|
62
|
|
|
|
|
590
|
eval{ $self->parseBlock( \@list,$self->{block}{$blockname} ); };
|
|
62
|
|
|
|
|
218
|
|
1269
|
|
|
|
|
|
|
|
1270
|
62
|
|
|
|
|
109
|
return !@{$self->{error}};
|
|
62
|
|
|
|
|
267
|
|
1271
|
|
|
|
|
|
|
}
|
1272
|
|
|
|
|
|
|
|
1273
|
|
|
|
|
|
|
|
1274
|
|
|
|
|
|
|
# $ok = $tml->loadFile("filename","utf8" [,$blockname]);
|
1275
|
|
|
|
|
|
|
sub loadFile{
|
1276
|
1
|
|
|
2
|
0
|
35
|
my $self = shift;
|
1277
|
|
|
|
|
|
|
|
1278
|
1
|
|
|
|
|
5
|
$self->{lno} = 0;
|
1279
|
1
|
|
|
|
|
3
|
$self->{source_name} = $_[0];
|
1280
|
1
|
|
|
|
|
3
|
my $enc = $_[1];
|
1281
|
1
|
|
|
|
|
3
|
my $blockname = $_[2];
|
1282
|
|
|
|
|
|
|
|
1283
|
|
|
|
|
|
|
# find encoding object for source
|
1284
|
1
|
50
|
|
|
|
4
|
if(defined $enc){
|
1285
|
1
|
50
|
|
|
|
5
|
ref($enc) or $enc = Encode::find_encoding($enc);
|
1286
|
1
|
50
|
|
|
|
16
|
if(not ref($enc) =~/Encode/){
|
1287
|
0
|
|
|
|
|
0
|
push @{$self->{error}},"$self->{source_name} $self->{lno}: incorrect encode spec.";
|
|
0
|
|
|
|
|
0
|
|
1288
|
0
|
|
|
|
|
0
|
return;
|
1289
|
|
|
|
|
|
|
}
|
1290
|
|
|
|
|
|
|
}
|
1291
|
|
|
|
|
|
|
|
1292
|
|
|
|
|
|
|
# read source text
|
1293
|
1
|
|
|
|
|
3
|
my $source;
|
1294
|
|
|
|
|
|
|
my $fh;
|
1295
|
1
|
50
|
|
|
|
29
|
if(not open $fh,"<",$self->{source_name} ){
|
1296
|
0
|
|
|
|
|
0
|
push @{$self->{error}},"$self->{source_name} $self->{lno}: $!";
|
|
0
|
|
|
|
|
0
|
|
1297
|
0
|
|
|
|
|
0
|
return;
|
1298
|
|
|
|
|
|
|
}else{
|
1299
|
1
|
|
|
|
|
4
|
local $/=undef;
|
1300
|
1
|
|
|
|
|
28
|
$source = <$fh>;
|
1301
|
1
|
50
|
|
|
|
8
|
defined($enc) and $source = Encode::decode($enc,$source);
|
1302
|
1
|
50
|
|
|
|
231
|
if(not close $fh ){
|
1303
|
0
|
|
|
|
|
0
|
push @{$self->{error}},"$self->{source_name} $self->{lno}: $!";
|
|
0
|
|
|
|
|
0
|
|
1304
|
0
|
|
|
|
|
0
|
return;
|
1305
|
|
|
|
|
|
|
}
|
1306
|
|
|
|
|
|
|
}
|
1307
|
1
|
|
|
|
|
6
|
return $self->loadText($self->{source_name},\$source,$blockname);
|
1308
|
|
|
|
|
|
|
}
|
1309
|
|
|
|
|
|
|
|
1310
|
|
|
|
|
|
|
# $teml = Text::Template::Compact->new();
|
1311
|
|
|
|
|
|
|
sub new{
|
1312
|
|
|
|
|
|
|
return bless{
|
1313
|
|
|
|
|
|
|
error => [],
|
1314
|
|
|
|
|
|
|
paramEncoding => Encode::find_encoding('utf8'),
|
1315
|
2
|
|
|
3
|
0
|
8083
|
filter_default => $filter_map{'html'},
|
1316
|
|
|
|
|
|
|
undef_supply => '',
|
1317
|
|
|
|
|
|
|
} , shift;
|
1318
|
|
|
|
|
|
|
}
|
1319
|
|
|
|
|
|
|
|
1320
|
|
|
|
|
|
|
# get error as string.
|
1321
|
|
|
|
|
|
|
sub error{
|
1322
|
0
|
|
|
1
|
0
|
0
|
return join("\n",@{$_[0]->{error}},'');
|
|
0
|
|
|
|
|
0
|
|
1323
|
|
|
|
|
|
|
}
|
1324
|
|
|
|
|
|
|
# get error as string.
|
1325
|
|
|
|
|
|
|
sub undef_supply{
|
1326
|
1
|
|
|
2
|
0
|
5
|
my $self = shift;
|
1327
|
1
|
50
|
|
|
|
19
|
if(@_){
|
1328
|
1
|
|
|
|
|
9
|
$self->{undef_supply} = $_[0];
|
1329
|
|
|
|
|
|
|
}
|
1330
|
1
|
|
|
|
|
3
|
return $self->{undef_supply};
|
1331
|
|
|
|
|
|
|
}
|
1332
|
|
|
|
|
|
|
|
1333
|
|
|
|
|
|
|
# set encoding for decode parameter
|
1334
|
|
|
|
|
|
|
sub param_encoding{
|
1335
|
2
|
|
|
3
|
0
|
7911
|
my $self = shift;
|
1336
|
2
|
50
|
|
|
|
13
|
if(@_){
|
1337
|
2
|
|
|
|
|
6
|
my $enc = $_[0];
|
1338
|
|
|
|
|
|
|
# find encoding object for source
|
1339
|
2
|
50
|
|
|
|
8
|
if(defined $enc){
|
1340
|
2
|
50
|
|
|
|
13
|
ref($enc) or $enc = Encode::find_encoding($enc);
|
1341
|
2
|
50
|
|
|
|
42
|
ref($enc) =~/Encode/ or croak "incorrect encode spec.";
|
1342
|
|
|
|
|
|
|
}
|
1343
|
2
|
|
|
|
|
11
|
$self->{paramEncoding} = $enc;
|
1344
|
|
|
|
|
|
|
}
|
1345
|
2
|
|
|
|
|
7
|
return;
|
1346
|
|
|
|
|
|
|
}
|
1347
|
|
|
|
|
|
|
|
1348
|
|
|
|
|
|
|
# set default of filter for variable expand.
|
1349
|
|
|
|
|
|
|
sub filter_default{
|
1350
|
2
|
|
|
3
|
0
|
13
|
my $self = shift;
|
1351
|
2
|
50
|
|
|
|
9
|
if(@_){
|
1352
|
2
|
|
|
|
|
5
|
my $filtername = $_[0];
|
1353
|
2
|
50
|
33
|
|
|
39
|
if( not $filtername or not $filter_map{$filtername} ){
|
1354
|
0
|
|
|
|
|
0
|
croak "unknown filter '$filtername'";
|
1355
|
|
|
|
|
|
|
}
|
1356
|
2
|
|
|
|
|
8
|
$self->{filter_default} = $filter_map{$filtername};
|
1357
|
|
|
|
|
|
|
}
|
1358
|
2
|
|
|
|
|
6
|
return;
|
1359
|
|
|
|
|
|
|
}
|
1360
|
|
|
|
|
|
|
|
1361
|
|
|
|
|
|
|
# print template block(low-level method)
|
1362
|
|
|
|
|
|
|
sub printBlock{
|
1363
|
411
|
|
|
412
|
0
|
830
|
my($self,$block)=@_;
|
1364
|
411
|
|
|
|
|
934
|
for my $item ( @$block ){
|
1365
|
1753
|
100
|
66
|
|
|
19091
|
if( not ref $item ){
|
|
|
100
|
|
|
|
|
|
1366
|
883
|
|
|
|
|
2367
|
$self->{printer}->($item);
|
1367
|
|
|
|
|
|
|
}elsif( $item->{break} or $item->{continue} ){
|
1368
|
7
|
|
|
|
|
17
|
return $item;
|
1369
|
|
|
|
|
|
|
}else{
|
1370
|
863
|
|
|
|
|
2177
|
my $exit_tag = $item->{printer}($self,$item);
|
1371
|
863
|
100
|
|
|
|
2411
|
$exit_tag and return $exit_tag;
|
1372
|
|
|
|
|
|
|
}
|
1373
|
|
|
|
|
|
|
}
|
1374
|
396
|
|
|
|
|
5828
|
return;
|
1375
|
|
|
|
|
|
|
}
|
1376
|
|
|
|
|
|
|
|
1377
|
|
|
|
|
|
|
# print to filehandle
|
1378
|
|
|
|
|
|
|
sub print{
|
1379
|
1
|
|
|
2
|
0
|
636
|
my($self,$param,$fh,$enc)=@_;
|
1380
|
|
|
|
|
|
|
|
1381
|
|
|
|
|
|
|
# generate closure to print
|
1382
|
1
|
50
|
|
|
|
7
|
if(defined $enc){
|
1383
|
|
|
|
|
|
|
# find encoding object for source
|
1384
|
1
|
50
|
|
|
|
10
|
ref($enc) or $enc = Encode::find_encoding($enc);
|
1385
|
1
|
50
|
|
|
|
30
|
ref($enc) =~/Encode/ or croak "incorrect encode spec.";
|
1386
|
1
|
|
|
804
|
|
9
|
$self->{printer} = sub{ for(@_){ print $fh Encode::encode($enc,$_); } };
|
|
803
|
|
|
|
|
1697
|
|
|
803
|
|
|
|
|
2401
|
|
1387
|
|
|
|
|
|
|
}else{
|
1388
|
0
|
|
|
1
|
|
0
|
$self->{printer} = sub{ print $fh @_; };
|
|
0
|
|
|
|
|
0
|
|
1389
|
|
|
|
|
|
|
}
|
1390
|
1
|
|
|
|
|
8
|
$self->{param} = $param;
|
1391
|
|
|
|
|
|
|
|
1392
|
|
|
|
|
|
|
# start root node
|
1393
|
1
|
|
|
|
|
6
|
my $exit_tag = $self->printBlock( $self->{block}{""});
|
1394
|
|
|
|
|
|
|
}
|
1395
|
|
|
|
|
|
|
|
1396
|
|
|
|
|
|
|
sub toString{
|
1397
|
61
|
|
|
62
|
0
|
20717
|
my($self,$param)=@_;
|
1398
|
61
|
|
|
|
|
121
|
my $result='';
|
1399
|
61
|
|
|
|
|
123
|
$self->{param} = $param;
|
1400
|
61
|
|
|
551
|
|
290
|
$self->{printer} = sub{ for(@_){ $result .= $_; } };
|
|
550
|
|
|
|
|
1105
|
|
|
550
|
|
|
|
|
1503
|
|
1401
|
61
|
|
|
|
|
342
|
$self->printBlock( $self->{block}{""} );
|
1402
|
61
|
|
|
|
|
177
|
return $result;
|
1403
|
|
|
|
|
|
|
}
|
1404
|
|
|
|
|
|
|
|
1405
|
|
|
|
|
|
|
1;
|
1406
|
|
|
|
|
|
|
|
1407
|
|
|
|
|
|
|
__END__
|