line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# -*- mode: perl; coding: utf-8 -*- |
2
|
|
|
|
|
|
|
package YATT::LRXML::Node; |
3
|
|
|
|
|
|
|
# Media か? |
4
|
|
|
|
|
|
|
# To cooperate with JSON easily, Nodes should not rely on OO style. |
5
|
|
|
|
|
|
|
|
6
|
7
|
|
|
7
|
|
3094
|
use strict; |
|
7
|
|
|
|
|
18
|
|
|
7
|
|
|
|
|
207
|
|
7
|
7
|
|
|
7
|
|
35
|
use warnings qw(FATAL all NONFATAL misc); |
|
7
|
|
|
|
|
69
|
|
|
7
|
|
|
|
|
313
|
|
8
|
7
|
|
|
7
|
|
675
|
use YATT::Util::Symbol; |
|
7
|
|
|
|
|
10
|
|
|
7
|
|
|
|
|
640
|
|
9
|
7
|
|
|
7
|
|
36
|
use YATT::Util; |
|
7
|
|
|
|
|
14
|
|
|
7
|
|
|
|
|
1015
|
|
10
|
7
|
|
|
7
|
|
36
|
use Carp; |
|
7
|
|
|
|
|
10
|
|
|
7
|
|
|
|
|
387
|
|
11
|
|
|
|
|
|
|
|
12
|
7
|
|
|
7
|
|
45
|
use base qw(Exporter); |
|
7
|
|
|
|
|
12
|
|
|
7
|
|
|
|
|
942
|
|
13
|
|
|
|
|
|
|
our (@EXPORT_OK, @EXPORT); |
14
|
|
|
|
|
|
|
BEGIN { |
15
|
7
|
|
|
7
|
|
42
|
@EXPORT_OK = qw(stringify_node |
16
|
|
|
|
|
|
|
stringify_attlist |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
create_node |
19
|
|
|
|
|
|
|
create_node_from |
20
|
|
|
|
|
|
|
copy_node_renamed_as |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
create_attlist |
23
|
|
|
|
|
|
|
node_size |
24
|
|
|
|
|
|
|
node_children |
25
|
|
|
|
|
|
|
node_type_name |
26
|
|
|
|
|
|
|
node_name |
27
|
|
|
|
|
|
|
node_nsname |
28
|
|
|
|
|
|
|
node_path |
29
|
|
|
|
|
|
|
node_headings |
30
|
|
|
|
|
|
|
node_set_nlines |
31
|
|
|
|
|
|
|
node_user_data |
32
|
|
|
|
|
|
|
node_user_data_by |
33
|
|
|
|
|
|
|
node_attribute_format |
34
|
|
|
|
|
|
|
is_attribute |
35
|
|
|
|
|
|
|
is_primary_attribute |
36
|
|
|
|
|
|
|
is_bare_attribute |
37
|
|
|
|
|
|
|
is_quoted_by_element |
38
|
|
|
|
|
|
|
is_empty_element |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
quoted_by_element |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
copy_array |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
EMPTY_ELEMENT |
45
|
|
|
|
|
|
|
); |
46
|
7
|
|
|
|
|
546
|
@EXPORT = @EXPORT_OK; |
47
|
|
|
|
|
|
|
} |
48
|
|
|
|
|
|
|
|
49
|
6
|
|
|
6
|
0
|
78
|
sub exports { @EXPORT_OK } |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
sub MY () {__PACKAGE__} |
52
|
|
|
|
|
|
|
|
53
|
7
|
|
|
7
|
|
209
|
our @NODE_MEMBERS; BEGIN {@NODE_MEMBERS = qw(TYPE FLAG NLINES USER_SLOT |
54
|
|
|
|
|
|
|
RAW_NAME BODY)} |
55
|
7
|
|
|
7
|
|
3126
|
use YATT::Util::Enum -prefix => '_', @NODE_MEMBERS; |
|
7
|
|
|
|
|
16
|
|
|
7
|
|
|
|
|
71
|
|
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
BEGIN { |
58
|
7
|
|
|
7
|
|
22
|
foreach my $name (@NODE_MEMBERS) { |
59
|
42
|
|
|
|
|
244
|
my $offset = MY->can("_$name")->(); |
60
|
42
|
|
|
|
|
110
|
my $func = "node_".lc($name); |
61
|
42
|
|
|
|
|
144
|
*{globref(MY, $func)} = sub { |
62
|
1669
|
|
|
1669
|
|
7891
|
shift->[$offset] |
63
|
42
|
|
|
|
|
130
|
}; |
64
|
42
|
|
|
|
|
94
|
push @EXPORT_OK, $func; |
65
|
42
|
|
|
|
|
2022
|
push @EXPORT, $func; |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
our @NODE_TYPES; |
70
|
|
|
|
|
|
|
our %NODE_TYPES; |
71
|
|
|
|
|
|
|
our @NODE_FORMAT; |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
BEGIN { |
74
|
7
|
|
|
7
|
|
123
|
my @desc = ([text => '%s'] # May not be used. |
75
|
|
|
|
|
|
|
, [comment => ''] |
76
|
|
|
|
|
|
|
, [decl_comment => '--%1$s--'] |
77
|
|
|
|
|
|
|
, [pi => '%2$s' . '%1$s?>' ] |
78
|
|
|
|
|
|
|
, [entity => '%3$s'.'%2$s'.'%1$s;', ['&', '%']] |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
, [root => \&stringify_root] |
81
|
|
|
|
|
|
|
, [element => \&stringify_element] |
82
|
|
|
|
|
|
|
, [attribute => \&stringify_attribute] |
83
|
|
|
|
|
|
|
, [declarator => \&stringify_declarator] |
84
|
|
|
|
|
|
|
, [html => \&stringify_element] |
85
|
|
|
|
|
|
|
, [unknown => \&stringify_unknown] |
86
|
|
|
|
|
|
|
); |
87
|
7
|
|
|
|
|
134
|
$NODE_TYPES{$_->[0]} = keys %NODE_TYPES for @desc; |
88
|
7
|
|
|
|
|
17
|
@NODE_TYPES = map {$_->[0]} @desc; |
|
77
|
|
|
|
|
144
|
|
89
|
7
|
100
|
|
|
|
19
|
@NODE_FORMAT = map {ref $_->[1] eq 'CODE' ? $_->[1] : [@$_[1..$#$_]]} @desc; |
|
77
|
|
|
|
|
895
|
|
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
BEGIN { |
93
|
7
|
|
|
7
|
|
20
|
my @type_enum = map {uc($_) . '_TYPE'} @NODE_TYPES; |
|
77
|
|
|
|
|
338
|
|
94
|
7
|
|
|
|
|
80
|
require YATT::Util::Enum; |
95
|
7
|
|
|
|
|
36
|
import YATT::Util::Enum @type_enum; |
96
|
7
|
|
|
|
|
28
|
push @EXPORT_OK, @type_enum; |
97
|
7
|
|
|
|
|
366
|
push @EXPORT, @type_enum; |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
# ATTRIBUTE の FLAG の意味は、↓これと "ed_by_element が決める。 |
101
|
7
|
|
|
7
|
|
287
|
our @QUOTE_CHAR; BEGIN {@QUOTE_CHAR = ("", '\'', "\"", [qw([ ])])} |
102
|
|
|
|
|
|
|
# XXX: ↓ 役割は減る予定。 |
103
|
7
|
|
|
7
|
|
6447
|
our @QUOTE_TYPES; BEGIN {@QUOTE_TYPES = (1, 2, 0)} |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
sub new { |
106
|
8
|
|
|
8
|
0
|
4639
|
my $pack = shift; |
107
|
8
|
|
|
|
|
25
|
bless $pack->create_node(@_), $pack; |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
# $pack->create_node($typeName, $nodeName, $nodeBody) |
111
|
|
|
|
|
|
|
# $pack->create_node([$typeName, $flag], [@nodePath], @nodeBody) |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
sub sum_node_nlines { |
114
|
1491
|
|
|
1491
|
0
|
1817
|
my $nlines = 0; |
115
|
1491
|
|
|
|
|
2770
|
foreach my $item (@_) { |
116
|
393
|
100
|
|
|
|
1307
|
unless (ref $item) { |
|
|
50
|
|
|
|
|
|
117
|
171
|
|
|
|
|
464
|
$nlines += $item =~ tr,\n,,; |
118
|
|
|
|
|
|
|
} elsif (defined (my $sub = $item->[_NLINES])) { |
119
|
222
|
|
|
|
|
442
|
$nlines += $sub; |
120
|
|
|
|
|
|
|
} else { |
121
|
0
|
|
|
|
|
0
|
$nlines += sum_node_nlines(node_children($item)); |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
} |
124
|
1491
|
|
|
|
|
7367
|
$nlines; |
125
|
|
|
|
|
|
|
} |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
sub create_node { |
128
|
1353
|
|
|
1353
|
0
|
3716
|
my ($pack, $type, $name) = splice @_, 0, 3; |
129
|
1353
|
100
|
|
|
|
3194
|
my ($typename, $flag) = ref $type ? @$type : $type; |
130
|
1353
|
100
|
|
|
|
2865
|
$flag = 0 unless defined $flag; |
131
|
1353
|
|
|
|
|
2607
|
my $typeid = $NODE_TYPES{$typename}; |
132
|
1353
|
50
|
|
|
|
2499
|
die "Unknown type: $typename" unless defined $typeid; |
133
|
|
|
|
|
|
|
# DEPEND_ALIGNMENT: SET_NLINES: |
134
|
1353
|
|
|
|
|
2934
|
[$typeid, $flag, sum_node_nlines(@_), undef, $name, @_]; |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
sub create_node_from { |
138
|
138
|
|
|
138
|
0
|
350
|
my ($pack, $orig, $name) = splice @_, 0, 3; |
139
|
138
|
|
|
|
|
240
|
my ($typeid, $flag) = @{$orig}[_TYPE, _FLAG]; |
|
138
|
|
|
|
|
350
|
|
140
|
138
|
100
|
|
|
|
715
|
$name = copy_array($$orig[_RAW_NAME]) unless defined $name; |
141
|
|
|
|
|
|
|
# DEPEND_ALIGNMENT: SET_NLINES: |
142
|
138
|
|
|
|
|
405
|
[$typeid, $flag, sum_node_nlines(@_), undef, $name, @_] |
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
sub copy_node_renamed_as { |
146
|
5
|
|
|
5
|
0
|
15
|
my ($pack, $name, $orig) = splice @_, 0, 3; |
147
|
5
|
|
|
|
|
18
|
create_node_from($pack, $orig, $name, @{$orig}[_BODY .. $#$orig]); |
|
5
|
|
|
|
|
15
|
|
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
sub node_headings { |
151
|
114
|
|
|
114
|
0
|
185
|
my $node = shift; |
152
|
114
|
|
|
|
|
579
|
([$NODE_TYPES[$$node[_TYPE]], $$node[_FLAG]] |
153
|
|
|
|
|
|
|
, $$node[_RAW_NAME]); |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
sub node_body_starting () { _BODY } |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
sub node_size { |
159
|
526
|
|
|
526
|
0
|
858
|
my $node = shift; |
160
|
526
|
|
|
|
|
2902
|
@$node - _BODY; |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
sub node_children { |
164
|
240
|
|
|
240
|
0
|
370
|
my $node = shift; |
165
|
240
|
|
|
|
|
443
|
@{$node}[_BODY .. $#$node]; |
|
240
|
|
|
|
|
883
|
|
166
|
|
|
|
|
|
|
} |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
sub node_type_name { |
169
|
630
|
|
|
630
|
0
|
4578
|
$NODE_TYPES[shift->[_TYPE]]; |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
sub is_attribute { |
173
|
388
|
|
|
388
|
0
|
2136
|
$_[0]->[_TYPE] == ATTRIBUTE_TYPE; |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
sub is_primary_attribute { |
177
|
186
|
100
|
100
|
186
|
0
|
1958
|
$_[0]->[_TYPE] == ATTRIBUTE_TYPE |
178
|
|
|
|
|
|
|
&& (! defined $_[0]->[_FLAG] |
179
|
|
|
|
|
|
|
|| $_[0]->[_FLAG] < @QUOTE_CHAR); |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
sub is_bare_attribute { |
183
|
6
|
100
|
66
|
6
|
0
|
89
|
$_[0]->[_TYPE] == ATTRIBUTE_TYPE |
184
|
|
|
|
|
|
|
&& defined $_[0]->[_FLAG] |
185
|
|
|
|
|
|
|
&& $_[0]->[_FLAG] == 0; |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
sub stringify_node { |
189
|
138
|
|
|
138
|
0
|
933
|
my ($node) = shift; |
190
|
138
|
|
|
|
|
205
|
my $type = $node->[_TYPE]; |
191
|
138
|
50
|
33
|
|
|
696
|
if (not defined $type or $type eq '') { |
192
|
0
|
|
|
|
|
0
|
die "Invalid node object: ".YATT::Util::terse_dump($node); |
193
|
|
|
|
|
|
|
} |
194
|
138
|
50
|
|
|
|
331
|
if (@NODE_FORMAT <= $type) { |
195
|
0
|
|
|
|
|
0
|
die "Unknown type: $type"; |
196
|
|
|
|
|
|
|
} |
197
|
138
|
100
|
|
|
|
396
|
if (ref(my $desc = $NODE_FORMAT[$type]) eq 'CODE') { |
198
|
99
|
|
|
|
|
243
|
$desc->($node, @_); |
199
|
|
|
|
|
|
|
} else { |
200
|
39
|
|
|
|
|
78
|
my ($fmt, $prefix, $suffix) = @$desc; |
201
|
7
|
|
|
7
|
|
2325
|
use YATT::Util::redundant_sprintf; |
|
7
|
|
|
|
|
15
|
|
|
7
|
|
|
|
|
60
|
|
202
|
39
|
100
|
|
|
|
116
|
sprintf($fmt |
|
|
50
|
|
|
|
|
|
203
|
|
|
|
|
|
|
, stringify_each_by($node) |
204
|
|
|
|
|
|
|
, node_nsname($node, '') |
205
|
|
|
|
|
|
|
, defined $prefix ? $prefix->[$node->[_FLAG]] : '' |
206
|
|
|
|
|
|
|
, defined $suffix ? $suffix->[$node->[_FLAG]] : ''); |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
# node_path は name スロットを返す。wantarray 対応。 |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
sub node_path { |
213
|
1854
|
|
|
1854
|
0
|
2917
|
my ($node, $first, $sep, $default) = @_; |
214
|
1854
|
|
|
|
|
2102
|
my $raw; |
215
|
1854
|
100
|
|
|
|
6312
|
unless (defined ($raw = $node->[_RAW_NAME])) { |
|
|
100
|
|
|
|
|
|
216
|
42
|
100
|
|
|
|
351
|
defined $default ? $default : return; |
217
|
|
|
|
|
|
|
} elsif (not ref $raw) { |
218
|
|
|
|
|
|
|
# undef かつ wantarray は只の return に分離した方が良いかも? |
219
|
631
|
|
|
|
|
3094
|
$raw; |
220
|
|
|
|
|
|
|
} else { |
221
|
1181
|
|
100
|
|
|
6321
|
my @names = @$raw[($first || 0) .. $#$raw]; |
222
|
|
|
|
|
|
|
wantarray ? @names : join(($sep || ":") |
223
|
1181
|
50
|
100
|
|
|
7757
|
, map {defined $_ ? $_ : ''} @names); |
|
149
|
100
|
|
|
|
986
|
|
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
# node_nsname は namespace 込みのパスを返す。 |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
sub node_nsname { |
230
|
99
|
|
|
99
|
0
|
177
|
my ($node, $default, $sep) = @_; |
231
|
99
|
|
|
|
|
226
|
scalar node_path($node, 0, $sep, $default); |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
# node_name は namespace を除いたパスを返す。 |
235
|
|
|
|
|
|
|
# yatt:else なら else が返る。 |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
sub node_name { |
238
|
561
|
|
|
561
|
0
|
928
|
my ($node, $default, $sep) = @_; |
239
|
561
|
|
|
|
|
1126
|
node_path($node, 1, $sep, $default); |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
sub node_set_nlines { |
243
|
811
|
|
|
811
|
0
|
1271
|
my ($node, $nlines) = @_; |
244
|
811
|
|
|
|
|
1295
|
$node->[_NLINES] = $nlines; |
245
|
811
|
|
|
|
|
16897
|
$node; |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
sub node_user_data { |
249
|
0
|
|
|
0
|
0
|
0
|
my ($node) = shift; |
250
|
0
|
0
|
|
|
|
0
|
if (@_) { |
251
|
0
|
|
|
|
|
0
|
$node->[_USER_SLOT] = shift; |
252
|
|
|
|
|
|
|
} else { |
253
|
0
|
|
|
|
|
0
|
$node->[_USER_SLOT]; |
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
} |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
sub node_user_data_by { |
258
|
0
|
|
|
0
|
0
|
0
|
my ($node) = shift; |
259
|
0
|
|
0
|
|
|
0
|
my $slot = $node->[_USER_SLOT] ||= do { |
260
|
0
|
|
|
|
|
0
|
my ($obj, $meth) = splice @_, 0, 2; |
261
|
0
|
|
|
|
|
0
|
$obj->$meth(@_); |
262
|
|
|
|
|
|
|
}; |
263
|
0
|
0
|
|
|
|
0
|
wantarray ? @$slot : $slot; |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
#---------------------------------------- |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
sub stringify_element { |
269
|
21
|
|
|
21
|
0
|
41
|
my ($elem) = @_; |
270
|
21
|
|
|
|
|
61
|
stringify_as_tag($elem, node_nsname($elem), $elem->[_FLAG]); |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
sub stringify_declarator { |
274
|
6
|
|
|
6
|
0
|
17
|
my ($elem, $strip_ns) = @_; |
275
|
|
|
|
|
|
|
# XXX: 本物にせよ。 |
276
|
6
|
|
|
|
|
17
|
my $tag = node_nsname($elem); |
277
|
6
|
|
|
|
|
24
|
my $attlist = stringify_each_by($elem, ' ', ' ', '', _BODY); |
278
|
6
|
|
|
|
|
105
|
"" |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
sub stringify_root { |
282
|
10
|
|
|
10
|
0
|
18
|
my ($elem) = @_; |
283
|
10
|
|
|
|
|
41
|
stringify_each_by($elem |
284
|
|
|
|
|
|
|
, '' |
285
|
|
|
|
|
|
|
, '' |
286
|
|
|
|
|
|
|
, '' |
287
|
|
|
|
|
|
|
, _BODY); |
288
|
|
|
|
|
|
|
} |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
sub stringify_unknown { |
291
|
0
|
|
|
0
|
0
|
0
|
die 'unknown'; |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
#---------------------------------------- |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
sub stringify_as_tag { |
297
|
27
|
|
|
27
|
0
|
53
|
my ($node, $name, $is_ee) = @_; |
298
|
27
|
|
|
|
|
65
|
my $bodystart = node_beginning_of_body($node); |
299
|
27
|
|
|
|
|
100
|
my $tag = do { |
300
|
27
|
100
|
66
|
|
|
111
|
if (defined $name && is_attribute($node)) { |
301
|
6
|
|
|
|
|
19
|
":$name"; |
302
|
|
|
|
|
|
|
} else { |
303
|
21
|
|
|
|
|
43
|
$name; |
304
|
|
|
|
|
|
|
} |
305
|
|
|
|
|
|
|
}; |
306
|
27
|
|
|
|
|
80
|
my $attlist = stringify_attlist($node, $bodystart); |
307
|
27
|
100
|
|
|
|
68
|
if ($is_ee) { |
308
|
14
|
50
|
|
|
|
80
|
stringify_each_by($node |
309
|
|
|
|
|
|
|
, $tag ? qq(<$tag$attlist />) : '' |
310
|
|
|
|
|
|
|
, '' |
311
|
|
|
|
|
|
|
, '' |
312
|
|
|
|
|
|
|
, $bodystart); |
313
|
|
|
|
|
|
|
} else { |
314
|
13
|
50
|
|
|
|
82
|
stringify_each_by($node |
|
|
50
|
|
|
|
|
|
315
|
|
|
|
|
|
|
, $tag ? qq(<$tag$attlist>) : '' |
316
|
|
|
|
|
|
|
, '' |
317
|
|
|
|
|
|
|
, $tag ? qq($tag>) : '' |
318
|
|
|
|
|
|
|
, $bodystart); |
319
|
|
|
|
|
|
|
} |
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
sub stringify_attlist { |
323
|
27
|
|
|
27
|
0
|
47
|
my ($node) = shift; |
324
|
27
|
|
66
|
|
|
87
|
my $bodystart = shift || node_beginning_of_body($node); |
325
|
|
|
|
|
|
|
# print "[[for @{[$node->get_name]}; <", |
326
|
27
|
100
|
100
|
|
|
317
|
return '' if defined $bodystart and _BODY == $bodystart |
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
327
|
|
|
|
|
|
|
or not defined $bodystart and $#$node < _BODY; |
328
|
13
|
100
|
|
|
|
63
|
stringify_each_by($node, ' ', ' ', '', _BODY |
329
|
|
|
|
|
|
|
, (defined $bodystart ? ($bodystart - 1) : ())) |
330
|
|
|
|
|
|
|
} |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
sub stringify_each_by { |
333
|
151
|
|
|
151
|
0
|
454
|
my ($node, $open, $sep, $close) = splice @_, 0, 4; |
334
|
151
|
|
100
|
|
|
451
|
$open ||= ''; $sep ||= ''; $close ||= ''; |
|
151
|
|
100
|
|
|
509
|
|
|
151
|
|
100
|
|
|
450
|
|
335
|
151
|
100
|
|
|
|
324
|
my $from = @_ ? shift : _BODY; |
336
|
151
|
100
|
|
|
|
374
|
my $to = @_ ? shift : $#$node; |
337
|
151
|
|
|
|
|
230
|
my $result = $open; |
338
|
151
|
100
|
66
|
|
|
634
|
if (defined $from and defined $to) { |
339
|
|
|
|
|
|
|
$result .= join $sep, map { |
340
|
210
|
50
|
|
|
|
610
|
unless (defined $_) { |
|
|
100
|
|
|
|
|
|
341
|
0
|
|
|
|
|
0
|
'' |
342
|
|
|
|
|
|
|
} elsif (ref $_) { |
343
|
94
|
|
|
|
|
204
|
my $s = stringify_node($_); |
344
|
94
|
50
|
|
|
|
225
|
unless (defined $s) { |
345
|
0
|
|
|
|
|
0
|
require YATT::Util; |
346
|
0
|
|
|
|
|
0
|
die "Can't stringify node: ". YATT::Util::terse_dump($_) |
347
|
|
|
|
|
|
|
} |
348
|
94
|
|
|
|
|
276
|
$s; |
349
|
|
|
|
|
|
|
} else { |
350
|
116
|
|
|
|
|
350
|
$_ |
351
|
|
|
|
|
|
|
} |
352
|
141
|
|
|
|
|
235
|
} @{$node}[$from .. $to]; |
|
141
|
|
|
|
|
292
|
|
353
|
|
|
|
|
|
|
} |
354
|
151
|
50
|
|
|
|
475
|
$result .= $close if defined $close; |
355
|
151
|
|
|
|
|
672
|
$result; |
356
|
|
|
|
|
|
|
} |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
sub node_beginning_of_body { |
359
|
37
|
|
|
37
|
0
|
58
|
my ($node) = @_; |
360
|
|
|
|
|
|
|
lsearch { |
361
|
50
|
|
100
|
50
|
|
226
|
not ref $_ or not is_primary_attribute($_) |
362
|
37
|
|
|
|
|
204
|
} $node, _BODY; |
363
|
|
|
|
|
|
|
} |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
#---------------------------------------- |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
sub create_attlist { |
368
|
447
|
|
|
447
|
0
|
730
|
my ($parser) = shift; |
369
|
447
|
|
|
|
|
591
|
my @result; |
370
|
447
|
|
|
|
|
1072
|
while (@_) { |
371
|
514
|
|
|
|
|
2106
|
my ($sp, $name, $eq, @values) = splice @_, 0, 6; |
372
|
514
|
|
|
1433
|
|
2886
|
my $found = lsearch {defined} \@values; |
|
1433
|
|
|
|
|
5746
|
|
373
|
514
|
|
|
|
|
1593
|
my ($subtype, $attname, @attbody) = do { |
374
|
514
|
50
|
100
|
|
|
3962
|
unless (defined $found) { |
|
|
100
|
100
|
|
|
|
|
375
|
0
|
|
|
|
|
0
|
(undef, $name); |
376
|
|
|
|
|
|
|
} elsif (not defined $name and $found == 2 |
377
|
|
|
|
|
|
|
and $values[$found] =~ /^[\w\:\-\.]+$/) { |
378
|
|
|
|
|
|
|
# has single bareword. use it as name and keep value undef. |
379
|
275
|
|
|
|
|
734
|
(undef, $values[$found]); |
380
|
|
|
|
|
|
|
} else { |
381
|
|
|
|
|
|
|
# parse_entities can return (). |
382
|
239
|
|
|
|
|
1034
|
($QUOTE_TYPES[$found], $name => |
383
|
|
|
|
|
|
|
$parser->parse_entities($values[$found])); |
384
|
|
|
|
|
|
|
} |
385
|
|
|
|
|
|
|
}; |
386
|
514
|
100
|
|
|
|
861
|
my @typed; @typed = split /:/, $attname if defined $attname; |
|
514
|
|
|
|
|
1717
|
|
387
|
|
|
|
|
|
|
# DEPEND_ALIGNMENT: SET_NLINES: |
388
|
514
|
100
|
|
|
|
3147
|
push @result, [ATTRIBUTE_TYPE, $subtype, 0, undef |
389
|
|
|
|
|
|
|
, @typed > 1 ? \@typed : $attname |
390
|
|
|
|
|
|
|
, @attbody]; |
391
|
|
|
|
|
|
|
} |
392
|
447
|
|
|
|
|
3479
|
@result; |
393
|
|
|
|
|
|
|
} |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
sub stringify_attribute { |
396
|
62
|
|
|
62
|
0
|
93
|
my ($node) = @_; |
397
|
62
|
100
|
100
|
|
|
273
|
if (defined $$node[_FLAG] && $$node[_FLAG] >= @QUOTE_CHAR) { |
398
|
6
|
|
|
|
|
22
|
stringify_as_tag($node |
399
|
|
|
|
|
|
|
, node_nsname($node) |
400
|
|
|
|
|
|
|
, $$node[_FLAG] - MY->quoted_by_element(0)); |
401
|
|
|
|
|
|
|
} else { |
402
|
56
|
|
|
|
|
131
|
my (@stringify_as) = attribute_stringify_as($node); |
403
|
56
|
50
|
|
|
|
137
|
if (@stringify_as == 1) { |
404
|
0
|
|
|
|
|
0
|
$stringify_as[0] |
405
|
|
|
|
|
|
|
} else { |
406
|
56
|
|
|
|
|
147
|
stringify_each_by($node, @stringify_as, _BODY); |
407
|
|
|
|
|
|
|
} |
408
|
|
|
|
|
|
|
} |
409
|
|
|
|
|
|
|
} |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
sub node_attribute_format { |
412
|
22
|
|
|
22
|
0
|
37
|
my ($node) = @_; |
413
|
22
|
|
|
|
|
58
|
my ($open, $sep, $close) = attribute_stringify_as($node); |
414
|
22
|
|
|
|
|
87
|
($open, $close); |
415
|
|
|
|
|
|
|
} |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
sub attribute_stringify_as { |
418
|
78
|
|
|
78
|
0
|
124
|
my ($node) = @_; |
419
|
78
|
100
|
|
|
|
195
|
unless (defined $$node[_BODY]) { |
420
|
10
|
|
|
|
|
28
|
(join_or_string($$node[_RAW_NAME]), '', ''); |
421
|
|
|
|
|
|
|
} else { |
422
|
68
|
100
|
|
|
|
192
|
my $Q = $$node[_FLAG] ? @QUOTE_CHAR[$$node[_FLAG]] : ""; |
423
|
68
|
100
|
|
|
|
195
|
my ($sep, $opn, $clo) = ref $Q ? (' ', @$Q) : ('', $Q, $Q); |
424
|
68
|
|
|
|
|
162
|
my $prefix = join_or_empty(join_or_string($$node[_RAW_NAME]), '=').$opn; |
425
|
68
|
|
|
|
|
260
|
($prefix, $sep, $clo); |
426
|
|
|
|
|
|
|
} |
427
|
|
|
|
|
|
|
} |
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
sub join_or_string { |
430
|
78
|
100
|
|
78
|
0
|
347
|
ref $_[0] ? join(":", @{$_[0]}) : $_[0]; |
|
2
|
|
|
|
|
9
|
|
431
|
|
|
|
|
|
|
} |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
sub join_or_empty { |
434
|
68
|
|
|
68
|
0
|
115
|
my $str = ''; |
435
|
68
|
|
|
|
|
137
|
foreach my $item (@_) { |
436
|
131
|
100
|
|
|
|
287
|
return '' unless defined $item; |
437
|
126
|
|
|
|
|
214
|
$str .= $item; |
438
|
|
|
|
|
|
|
} |
439
|
63
|
|
|
|
|
150
|
$str; |
440
|
|
|
|
|
|
|
} |
441
|
|
|
|
|
|
|
|
442
|
248
|
|
|
248
|
0
|
1300
|
sub EMPTY_ELEMENT () { 1 + @QUOTE_CHAR } |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
sub quoted_by_element { |
445
|
28
|
|
|
28
|
0
|
60
|
my ($pack, $is_ee) = @_; |
446
|
28
|
100
|
|
|
|
69
|
if ($is_ee) { |
447
|
16
|
|
|
|
|
39
|
EMPTY_ELEMENT; |
448
|
|
|
|
|
|
|
} else { |
449
|
12
|
|
|
|
|
50
|
scalar @QUOTE_CHAR; # 3 for now. |
450
|
|
|
|
|
|
|
} |
451
|
|
|
|
|
|
|
} |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
sub is_quoted_by_element { |
454
|
115
|
|
|
115
|
0
|
195
|
my ($node) = @_; |
455
|
115
|
100
|
|
|
|
907
|
defined $node->[_FLAG] && $node->[_FLAG] >= @QUOTE_CHAR; |
456
|
|
|
|
|
|
|
} |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
sub is_empty_element { |
459
|
124
|
|
|
124
|
0
|
211
|
my ($node) = @_; |
460
|
124
|
50
|
|
|
|
524
|
defined $node->[_FLAG] && $node->[_FLAG] == EMPTY_ELEMENT; |
461
|
|
|
|
|
|
|
} |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
1; |