|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
  
 
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # This code can be redistributed and modified under the terms of the GNU Affero  | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # General Public License as published by the Free Software Foundation, either  | 
| 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # version 3 of the License, or (at your option) any later version.  | 
| 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # See the "COPYING" file for details.  | 
| 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package HTML::Blitz::RuleSet;  | 
| 
6
 | 
11
 | 
 
 | 
 
 | 
  
11
  
 | 
 
 | 
81
 | 
 use HTML::Blitz::pragma;  | 
| 
 
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
31
 | 
    | 
| 
 
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
84
 | 
    | 
| 
7
 | 
11
 | 
 
 | 
 
 | 
  
11
  
 | 
 
 | 
9970
 | 
 use HTML::Blitz::Matcher ();  | 
| 
 
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
    | 
| 
 
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
265
 | 
    | 
| 
8
 | 
11
 | 
 
 | 
 
 | 
  
11
  
 | 
 
 | 
6540
 | 
 use HTML::Blitz::Parser ();  | 
| 
 
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
39
 | 
    | 
| 
 
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
508
 | 
    | 
| 
9
 | 
11
 | 
 
 | 
 
 | 
  
11
  
 | 
 
 | 
108
 | 
 use HTML::Blitz::CodeGen ();  | 
| 
 
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
    | 
| 
 
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
306
 | 
    | 
| 
10
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
865
 | 
 use HTML::Blitz::TokenType qw(  | 
| 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     TT_TAG_OPEN  | 
| 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     TT_TAG_CLOSE  | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     TT_TEXT  | 
| 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     TT_COMMENT  | 
| 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     TT_DOCTYPE  | 
| 
16
 | 
11
 | 
 
 | 
 
 | 
  
11
  
 | 
 
 | 
59
 | 
 );  | 
| 
 
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
    | 
| 
17
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1057
 | 
 use HTML::Blitz::ActionType qw(  | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     AT_P_IMMEDIATE  | 
| 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     AT_P_VARIABLE  | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     AT_P_TRANSFORM  | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     AT_P_FRAGMENT  | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     AT_P_VARHTML  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     AT_A_REMOVE_ATTR  | 
| 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     AT_A_SET_ATTR  | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     AT_A_MODIFY_ATTR  | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     AT_AS_REPLACE_ATTRS  | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     AT_AS_MODIFY_ATTRS  | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     AT_REMOVE_IF  | 
| 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     AT_REPLACE_OUTER  | 
| 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     AT_REPEAT_OUTER  | 
| 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     AT_REPLACE_INNER  | 
| 
35
 | 
11
 | 
 
 | 
 
 | 
  
11
  
 | 
 
 | 
5723
 | 
 );  | 
| 
 
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
85
 | 
    | 
| 
36
 | 
11
 | 
 
 | 
 
 | 
  
11
  
 | 
 
 | 
87
 | 
 use List::Util qw(all reduce);  | 
| 
 
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
    | 
| 
 
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2091
 | 
    | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $VERSION = '0.07';  | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
40
 | 
248
 | 
  
 50
  
 | 
 
 | 
  
248
  
 | 
  
0
  
 | 
573
 | 
 method new($class:) {  | 
| 
 
 | 
248
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
544
 | 
    | 
| 
 
 | 
248
 | 
 
 | 
 
 | 
 
 | 
 
 | 
390
 | 
    | 
| 
 
 | 
248
 | 
 
 | 
 
 | 
 
 | 
 
 | 
357
 | 
    | 
| 
41
 | 
248
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1959
 | 
     bless {  | 
| 
42
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         rules            => [],  | 
| 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         keep_doctype     => 1,  | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         keep_comments_re => qr/\A/,  | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         dummy_marker_re  => qr/\A(?!)/,  | 
| 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }, $class  | 
| 
47
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
48
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
49
 | 
1
 | 
  
 50
  
 | 
 
 | 
  
1
  
 | 
  
0
  
 | 
5
 | 
 method set_keep_doctype($val) {  | 
| 
 
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
    | 
| 
50
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
     $self->{keep_doctype} = !!$val;  | 
| 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
53
 | 
4
 | 
  
 50
  
 | 
 
 | 
  
4
  
 | 
  
0
  
 | 
12
 | 
 method set_keep_comments_re($keep_comments_re) {  | 
| 
 
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
11
 | 
    | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
    | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
    | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
    | 
| 
54
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
80
 | 
     $self->{keep_comments_re} = qr/(?#)$keep_comments_re/;  | 
| 
55
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
57
 | 
4
 | 
  
 50
  
 | 
 
 | 
  
4
  
 | 
  
0
  
 | 
12
 | 
 method set_dummy_marker_re($dummy_marker_re) {  | 
| 
 
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
8
 | 
    | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
    | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
    | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
    | 
| 
58
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
45
 | 
     $self->{dummy_marker_re} = qr/(?#)$dummy_marker_re/;  | 
| 
59
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
61
 | 
13
 | 
  
 50
  
 | 
 
 | 
  
13
  
 | 
 
 | 
32
 | 
 fun _combine_params_plain($p1, $p2) {  | 
| 
 
 | 
13
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
24
 | 
    | 
| 
 
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
25
 | 
    | 
| 
 
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
    | 
| 
62
 | 
13
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
37
 | 
     if ($p1->{type} eq AT_P_IMMEDIATE) {  | 
| 
63
 | 
11
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
31
 | 
         if ($p2->{type} eq AT_P_IMMEDIATE) {  | 
| 
64
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
16
 | 
             return length($p1->{value}) <= length($p2->{value}) ? $p1 : $p2;  | 
| 
65
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
66
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
41
 | 
         return $p1;  | 
| 
67
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
68
 | 
2
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
7
 | 
     if ($p2->{type} eq AT_P_IMMEDIATE) {  | 
| 
69
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
         return $p2;  | 
| 
70
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
71
 | 
1
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
10
 | 
     $p1->{type} eq AT_P_VARIABLE && $p2->{type} eq AT_P_VARIABLE  | 
| 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         or die "Internal error: unexpected parameter types '$p1->{type}', '$p2->{type}'";  | 
| 
73
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     return $p1;  | 
| 
74
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
76
 | 
4
 | 
  
 50
  
 | 
 
 | 
  
4
  
 | 
 
 | 
9
 | 
 fun _combine_transforms($t1, $t2) {  | 
| 
 
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
9
 | 
    | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
    | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
    | 
| 
77
 | 
4
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
17
 | 
     $t1->{type} eq AT_P_TRANSFORM && $t2->{type} eq AT_P_TRANSFORM  | 
| 
78
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         or die "Internal error: unexpected transform types '$t1->{type}', '$t2->{type}'";  | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return {  | 
| 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         type    => AT_P_TRANSFORM,  | 
| 
81
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         static  => do {  | 
| 
82
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
             my ($f1, $f2) = ($t1->{static}, $t2->{static});  | 
| 
83
 | 
4
 | 
  
 50
  
 | 
 
 | 
  
8
  
 | 
 
 | 
29
 | 
             fun ($x) { $f1->($f2->($x)) }  | 
| 
 
 | 
8
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
33
 | 
    | 
| 
 
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
    | 
| 
 
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
    | 
| 
 
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
    | 
| 
 
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
    | 
| 
84
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         },  | 
| 
85
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
         dynamic => [@{$t1->{dynamic}}, @{$t2->{dynamic}}],  | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
    | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
40
 | 
    | 
| 
86
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     };  | 
| 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
89
 | 
14
 | 
  
 50
  
 | 
 
 | 
  
14
  
 | 
 
 | 
27
 | 
 fun _combine_params($p1, $p2) {  | 
| 
 
 | 
14
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
27
 | 
    | 
| 
 
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
32
 | 
    | 
| 
 
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
    | 
| 
90
 | 
14
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
35
 | 
     if ($p1->{type} eq AT_P_FRAGMENT) {  | 
| 
91
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
         if ($p2->{type} eq AT_P_FRAGMENT || $p2->{type} eq AT_P_TRANSFORM) {  | 
| 
92
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             return $p1;  | 
| 
93
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
94
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
         $p2->{type} eq AT_P_IMMEDIATE || $p2->{type} eq AT_P_VARIABLE || $p2->{type} eq AT_P_VARHTML  | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
95
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             or die "Internal error: unexpected parameter type '$p2->{type}'";  | 
| 
96
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return $p2;  | 
| 
97
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
98
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
99
 | 
14
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
29
 | 
     if ($p2->{type} eq AT_P_FRAGMENT) {  | 
| 
100
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
7
 | 
         if ($p1->{type} eq AT_P_TRANSFORM) {  | 
| 
101
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
             return $p2;  | 
| 
102
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
103
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
         $p1->{type} eq AT_P_IMMEDIATE || $p1->{type} eq AT_P_VARIABLE || $p1->{type} eq AT_P_VARHTML  | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             or die "Internal error: unexpected parameter type '$p1->{type}'";  | 
| 
105
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return $p1;  | 
| 
106
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
108
 | 
12
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
31
 | 
     if ($p1->{type} eq AT_P_VARHTML) {  | 
| 
109
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
         if ($p2->{type} eq AT_P_VARHTML || $p2->{type} eq AT_P_TRANSFORM) {  | 
| 
110
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             return $p1;  | 
| 
111
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
112
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
         $p2->{type} eq AT_P_IMMEDIATE || $p2->{type} eq AT_P_VARIABLE  | 
| 
113
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             or die "Internal error: unexpected parameter type '$p2->{type}'";  | 
| 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
115
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
116
 | 
12
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
22
 | 
     if ($p2->{type} eq AT_P_VARHTML) {  | 
| 
117
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         if ($p1->{type} eq AT_P_TRANSFORM) {  | 
| 
118
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             return $p2;  | 
| 
119
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
120
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
         $p1->{type} eq AT_P_IMMEDIATE || $p1->{type} eq AT_P_VARIABLE  | 
| 
121
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             or die "Internal error: unexpected parameter type '$p1->{type}'";  | 
| 
122
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return $p1;  | 
| 
123
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
124
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
125
 | 
12
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
26
 | 
     if ($p1->{type} eq AT_P_TRANSFORM) {  | 
| 
126
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
14
 | 
         if ($p2->{type} eq AT_P_TRANSFORM) {  | 
| 
127
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
             return _combine_transforms($p1, $p2);  | 
| 
128
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
129
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
         $p2->{type} eq AT_P_IMMEDIATE || $p2->{type} eq AT_P_VARIABLE  | 
| 
130
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             or die "Internal error: unexpected parameter type '$p2->{type}'";  | 
| 
131
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return $p2;  | 
| 
132
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
133
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
134
 | 
8
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
18
 | 
     if ($p2->{type} eq AT_P_TRANSFORM) {  | 
| 
135
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
         $p1->{type} eq AT_P_IMMEDIATE || $p1->{type} eq AT_P_VARIABLE  | 
| 
136
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             or die "Internal error: unexpected parameter type '$p1->{type}'";  | 
| 
137
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return $p1;  | 
| 
138
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
139
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
140
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
     _combine_params_plain $p1, $p2  | 
| 
141
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
142
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
143
 | 
75
 | 
  
 50
  
 | 
 
 | 
  
75
  
 | 
 
 | 
165
 | 
 fun _combine_contents($p1, $p2) {  | 
| 
 
 | 
75
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
150
 | 
    | 
| 
 
 | 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
144
 | 
    | 
| 
 
 | 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
119
 | 
    | 
| 
144
 | 
75
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
352
 | 
     return $p1 if !defined $p2;  | 
| 
145
 | 
17
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
48
 | 
     return $p2 if !defined $p1;  | 
| 
146
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
31
 | 
     _combine_params $p1, $p2  | 
| 
147
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
148
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
149
 | 
35
 | 
  
 50
  
 | 
 
 | 
  
35
  
 | 
 
 | 
64
 | 
 fun _combine_attr_actions($aa1, $aa2) {  | 
| 
 
 | 
35
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
66
 | 
    | 
| 
 
 | 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
54
 | 
    | 
| 
 
 | 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
46
 | 
    | 
| 
150
 | 
35
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
86
 | 
     return $aa1 if $aa1->{type} eq AT_A_REMOVE_ATTR;  | 
| 
151
 | 
15
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
38
 | 
     return $aa2 if $aa2->{type} eq AT_A_REMOVE_ATTR;  | 
| 
152
 | 
15
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
33
 | 
     if ($aa1->{type} eq AT_A_SET_ATTR) {  | 
| 
153
 | 
15
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
31
 | 
         if ($aa2->{type} eq AT_A_SET_ATTR) {  | 
| 
154
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
             return { type => AT_A_SET_ATTR, param => _combine_params_plain($aa1->{param}, $aa2->{param}) };  | 
| 
155
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
156
 | 
10
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
21
 | 
         $aa2->{type} eq AT_A_MODIFY_ATTR  | 
| 
157
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             or die "Internal error: unexpected attr action type '$aa2->{type}'";  | 
| 
158
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
         return $aa1;  | 
| 
159
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
160
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     if ($aa2->{type} eq AT_A_SET_ATTR) {  | 
| 
161
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $aa1->{type} eq AT_A_MODIFY_ATTR  | 
| 
162
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             or die "Internal error: unexpected attr action type '$aa1->{type}'";  | 
| 
163
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return $aa2;  | 
| 
164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
165
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
     $aa1->{type} eq AT_A_MODIFY_ATTR && $aa2->{type} eq AT_A_MODIFY_ATTR  | 
| 
166
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         or die "Internal error: unexpected attr action types '$aa1->{type}', '$aa2->{type}'";  | 
| 
167
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return { type => AT_A_MODIFY_ATTR, param => _combine_transforms($aa1->{param}, $aa2->{param}) };  | 
| 
168
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
169
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
170
 | 
75
 | 
  
 50
  
 | 
 
 | 
  
75
  
 | 
 
 | 
153
 | 
 fun _combine_attrset_actions($asa1, $asa2) {  | 
| 
 
 | 
75
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
179
 | 
    | 
| 
 
 | 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
131
 | 
    | 
| 
 
 | 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
118
 | 
    | 
| 
171
 | 
75
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
164
 | 
     if ($asa1->{type} eq AT_AS_REPLACE_ATTRS) {  | 
| 
172
 | 
15
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
29
 | 
         if ($asa2->{type} eq AT_AS_REPLACE_ATTRS) {  | 
| 
173
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             return  | 
| 
174
 | 
27
 | 
 
 | 
 
 | 
  
27
  
 | 
 
 | 
80
 | 
                 (all { $_->{type} eq AT_P_IMMEDIATE } values %{$asa1->{content}}) ? $asa1 :  | 
| 
 
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
49
 | 
    | 
| 
175
 | 
18
 | 
 
 | 
 
 | 
  
18
  
 | 
 
 | 
39
 | 
                 (all { $_->{type} eq AT_P_IMMEDIATE } values %{$asa2->{content}}) ? $asa2 :  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
    | 
| 
176
 | 
15
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
38
 | 
                 keys(%{$asa1->{content}}) <= keys(%{$asa2->{content}}) ? $asa1 :  | 
| 
 
 | 
2
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
    | 
| 
 
 | 
2
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
14
 | 
    | 
| 
177
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 $asa2;  | 
| 
178
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
179
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $asa2->{type} eq AT_AS_MODIFY_ATTRS  | 
| 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             or die "Internal error: unexpected attrset replacement type '$asa2->{type}'";  | 
| 
181
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return $asa1;  | 
| 
182
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
183
 | 
60
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
112
 | 
     if ($asa2->{type} eq AT_AS_REPLACE_ATTRS) {  | 
| 
184
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $asa1->{type} eq AT_AS_MODIFY_ATTRS  | 
| 
185
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             or die "Internal error: unexpected attrset replacement type '$asa1->{type}'";  | 
| 
186
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return $asa2;  | 
| 
187
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
188
 | 
60
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
199
 | 
     $asa1->{type} eq AT_AS_MODIFY_ATTRS && $asa2->{type} eq AT_AS_MODIFY_ATTRS  | 
| 
189
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         or die "Internal error: unexpected attrset replacement types '$asa1->{type}', '$asa2->{type}'";  | 
| 
190
 | 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
90
 | 
     my %content = %{$asa1->{content}};  | 
| 
 
 | 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
186
 | 
    | 
| 
191
 | 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
104
 | 
     for my $k (keys %{$asa2->{content}}) {  | 
| 
 
 | 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
135
 | 
    | 
| 
192
 | 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
67
 | 
         my $v = $asa2->{content}{$k};  | 
| 
193
 | 
43
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
108
 | 
         $content{$k} = exists $content{$k} ? _combine_attr_actions($content{$k}, $v) : $v;  | 
| 
194
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
195
 | 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
292
 | 
     return { type => AT_AS_MODIFY_ATTRS, content => \%content };  | 
| 
196
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
197
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
198
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
 fun _combine_actions_maybe($act1, $act2) {  | 
| 
 
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
199
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
     defined($act1) && defined($act2)  | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
200
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ? _combine_actions($act1, $act2)  | 
| 
201
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         : $act1 // $act2  | 
| 
202
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
203
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
204
 | 
75
 | 
  
 50
  
 | 
 
 | 
  
75
  
 | 
 
 | 
171
 | 
 fun _combine_actions($act1, $act2) {  | 
| 
 
 | 
75
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
138
 | 
    | 
| 
 
 | 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
138
 | 
    | 
| 
 
 | 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
91
 | 
    | 
| 
205
 | 
75
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
163
 | 
     if ($act1->{type} eq AT_REMOVE_IF) {  | 
| 
206
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         if ($act2->{type} eq AT_REMOVE_IF) {  | 
| 
207
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             return { type => AT_REMOVE_IF, cond => [@{$act1->{cond}}, @{$act2->{cond}}], else => _combine_actions_maybe($act1->{else}, $act2->{else}) };  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
208
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
209
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return { type => AT_REMOVE_IF, cond => $act1->{cond}, else => _combine_actions_maybe($act1->{else}, $act2) };  | 
| 
210
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
211
 | 
75
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
154
 | 
     if ($act2->{type} eq AT_REMOVE_IF) {  | 
| 
212
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return { type => AT_REMOVE_IF, cond => $act2->{cond}, else => _combine_actions_maybe($act1, $act2->{else}) };  | 
| 
213
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
214
 | 
75
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
146
 | 
     if ($act1->{type} eq AT_REPLACE_OUTER) {  | 
| 
215
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         if ($act2->{type} eq AT_REPLACE_OUTER) {  | 
| 
216
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             return { type => AT_REPLACE_OUTER, param => _combine_params($act1->{param}, $act2->{param}) };  | 
| 
217
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
218
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return $act1;  | 
| 
219
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
220
 | 
75
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
140
 | 
     if ($act2->{type} eq AT_REPLACE_OUTER) {  | 
| 
221
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return $act2;  | 
| 
222
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
223
 | 
75
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
146
 | 
     if ($act1->{type} eq AT_REPEAT_OUTER) {  | 
| 
224
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return { %$act1, nested => _combine_actions($act1->{nested}, $act2) };  | 
| 
225
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
226
 | 
75
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
148
 | 
     if ($act2->{type} eq AT_REPEAT_OUTER) {  | 
| 
227
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return { %$act2, nested => _combine_actions($act1, $act2->{nested}) };  | 
| 
228
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
229
 | 
75
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
316
 | 
     $act1->{type} eq AT_REPLACE_INNER && $act2->{type} eq AT_REPLACE_INNER  | 
| 
230
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         or die "Internal error: unexpected action types '$act1->{type}', '$act2->{type}'";  | 
| 
231
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return {  | 
| 
232
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         type    => AT_REPLACE_INNER,  | 
| 
233
 | 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
151
 | 
         repeat  => [@{$act1->{repeat}}, @{$act2->{repeat}}],  | 
| 
 
 | 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
206
 | 
    | 
| 
234
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         attrset => _combine_attrset_actions($act1->{attrset}, $act2->{attrset}),  | 
| 
235
 | 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
109
 | 
         content => _combine_contents($act1->{content}, $act2->{content}),  | 
| 
236
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     };  | 
| 
237
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
238
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
239
 | 
1778
 | 
 
 | 
 
 | 
  
1778
  
 | 
 
 | 
3252
 | 
 fun _reduce_actions(@actions) {  | 
| 
 
 | 
1778
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2344
 | 
    | 
| 
240
 | 
74
 | 
 
 | 
 
 | 
  
74
  
 | 
 
 | 
193
 | 
     reduce { _combine_actions $a, $b } @actions  | 
| 
241
 | 
1778
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11038
 | 
 }  | 
| 
242
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
243
 | 
261
 | 
  
 50
  
 | 
 
 | 
  
261
  
 | 
 
 | 
566
 | 
 fun _bind_scope($scope, $action) {  | 
| 
 
 | 
261
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
528
 | 
    | 
| 
 
 | 
261
 | 
 
 | 
 
 | 
 
 | 
 
 | 
502
 | 
    | 
| 
 
 | 
261
 | 
 
 | 
 
 | 
 
 | 
 
 | 
367
 | 
    | 
| 
244
 | 
261
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
963
 | 
     if ($action->{type} eq AT_REMOVE_IF) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
245
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         return {  | 
| 
246
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             type => AT_REMOVE_IF,  | 
| 
247
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
78
 | 
             cond => [map [$_->[0] // $scope, $_->[1]], @{$action->{cond}}],  | 
| 
248
 | 
5
 | 
 
 | 
  
 66
  
 | 
 
 | 
 
 | 
20
 | 
             else => $action->{else} && _bind_scope($scope, $action->{else}),  | 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
249
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         };  | 
| 
250
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif ($action->{type} eq AT_REPLACE_OUTER) {  | 
| 
251
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
         my $param = $action->{param};  | 
| 
252
 | 
7
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
34
 | 
         if ($param->{type} eq AT_P_VARIABLE || $param->{type} eq AT_P_VARHTML) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
253
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
             my $value = $param->{value};  | 
| 
254
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
8
 | 
             if (!defined $value->[0]) {  | 
| 
255
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
                 return { %$action, param => { %$param, value => [$scope, $value->[1]] } };  | 
| 
256
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
257
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } elsif ($param->{type} eq AT_P_TRANSFORM) {  | 
| 
258
 | 
2
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
10
 | 
             if (@{$param->{dynamic}}) {  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
    | 
| 
259
 | 
1
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
5
 | 
                 return { %$action, param => { %$param, dynamic => [ map [$_->[0] // $scope, $_->[1]], @{$param->{dynamic}} ] } };  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
    | 
| 
260
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
261
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
262
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif ($action->{type} eq AT_REPEAT_OUTER) {  | 
| 
263
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
5
 | 
         if (!defined $action->{var}[0]) {  | 
| 
264
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
             return { %$action, var => [$scope, $action->{var}[1]] };  | 
| 
265
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
266
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
267
 | 
248
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
581
 | 
         $action->{type} eq AT_REPLACE_INNER  | 
| 
268
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             or die "Internal error: unexpected action type '$action->{type}'";  | 
| 
269
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
270
 | 
248
 | 
 
 | 
 
 | 
 
 | 
 
 | 
339
 | 
         my $did_replace = 0;  | 
| 
271
 | 
30
 | 
  
 50
  
 | 
 
 | 
  
30
  
 | 
 
 | 
73
 | 
         my $scope_var = fun ($var) {  | 
| 
 
 | 
30
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
65
 | 
    | 
| 
 
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
55
 | 
    | 
| 
 
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
44
 | 
    | 
| 
272
 | 
30
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
60
 | 
             defined $var->[0] ? $var : do {  | 
| 
273
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
40
 | 
                 $did_replace++;  | 
| 
274
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
147
 | 
                 [$scope, $var->[1]]  | 
| 
275
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
276
 | 
248
 | 
 
 | 
 
 | 
 
 | 
 
 | 
967
 | 
         };  | 
| 
277
 | 
248
 | 
 
 | 
 
 | 
 
 | 
 
 | 
964
 | 
         my %replacement = (type => AT_REPLACE_INNER, attrset => {}, content => undef, repeat => []);  | 
| 
278
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
279
 | 
248
 | 
 
 | 
 
 | 
 
 | 
 
 | 
432
 | 
         my $asa = $action->{attrset};  | 
| 
280
 | 
248
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
533
 | 
         if ($asa->{type} eq AT_AS_REPLACE_ATTRS) {  | 
| 
281
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
             $replacement{attrset}{type} = AT_AS_REPLACE_ATTRS;  | 
| 
282
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
             my $content = $asa->{content};  | 
| 
283
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
             $replacement{attrset}{content} = \my %copy;  | 
| 
284
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
             for my $key (keys %$content) {  | 
| 
285
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
                 my $value = $content->{$key};  | 
| 
286
 | 
12
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
34
 | 
                 if ($value->{type} eq AT_P_VARIABLE && !defined $value->{value}[0]) {  | 
| 
287
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
                     $copy{$key} = { type => AT_P_VARIABLE, value => [$scope, $value->{value}[1]] };  | 
| 
288
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
                     $did_replace++;  | 
| 
289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 } else {  | 
| 
290
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
                     $copy{$key} = $value;  | 
| 
291
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
292
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
293
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } else {  | 
| 
294
 | 
242
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
554
 | 
             $asa->{type} eq AT_AS_MODIFY_ATTRS  | 
| 
295
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 or die "Internal error: unexpected attrset replacement type '$asa->{type}'";  | 
| 
296
 | 
242
 | 
 
 | 
 
 | 
 
 | 
 
 | 
501
 | 
             $replacement{attrset}{type} = AT_AS_MODIFY_ATTRS;  | 
| 
297
 | 
242
 | 
 
 | 
 
 | 
 
 | 
 
 | 
364
 | 
             my $content = $asa->{content};  | 
| 
298
 | 
242
 | 
 
 | 
 
 | 
 
 | 
 
 | 
437
 | 
             $replacement{attrset}{content} = \my %copy;  | 
| 
299
 | 
242
 | 
 
 | 
 
 | 
 
 | 
 
 | 
688
 | 
             for my $key (keys %$content) {  | 
| 
300
 | 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
73
 | 
                 my $value = $content->{$key};  | 
| 
301
 | 
43
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
294
 | 
                 if ($value->{type} eq AT_A_SET_ATTR && $value->{param}{type} eq AT_P_VARIABLE && !defined $value->{param}{value}[0]) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
302
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
32
 | 
                     $copy{$key} = { type => AT_A_SET_ATTR, param => { type => AT_P_VARIABLE, value => [$scope, $value->{param}{value}[1]] } };  | 
| 
303
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
                     $did_replace++;  | 
| 
304
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 } elsif ($value->{type} eq AT_A_MODIFY_ATTR && (my $param = $value->{param})->{dynamic}->@*) {  | 
| 
305
 | 
5
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
19
 | 
                     $param->{type} eq AT_P_TRANSFORM  | 
| 
306
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         or die "Internal error: unexpected parameter type '$param->{type}'";  | 
| 
307
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     $copy{$key} = {  | 
| 
308
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         type  => AT_A_MODIFY_ATTR,  | 
| 
309
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         param => {  | 
| 
310
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                             type    => AT_P_TRANSFORM,  | 
| 
311
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                             static  => $param->{static},  | 
| 
312
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                             dynamic => [  | 
| 
313
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
                                 map $scope_var->($_), @{$param->{dynamic}}  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
    | 
| 
314
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                             ],  | 
| 
315
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         },  | 
| 
316
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     };  | 
| 
317
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 } else {  | 
| 
318
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
81
 | 
                     $copy{$key} = $value;  | 
| 
319
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
320
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
321
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
322
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
323
 | 
248
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
607
 | 
         if (defined(my $param = $action->{content})) {  | 
| 
324
 | 
201
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
1200
 | 
             if (($param->{type} eq AT_P_VARIABLE || $param->{type} eq AT_P_VARHTML) && !defined $param->{value}[0]) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
325
 | 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
160
 | 
                 $replacement{content} = { %$param, value => [$scope, $param->{value}[1]] };  | 
| 
326
 | 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
75
 | 
                 $did_replace++;  | 
| 
327
 | 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
137
 | 
             } elsif ($param->{type} eq AT_P_TRANSFORM && @{$param->{dynamic}}) {  | 
| 
328
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 $replacement{content} = {  | 
| 
329
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     type    => AT_P_TRANSFORM,  | 
| 
330
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     static  => $param->{static},  | 
| 
331
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     dynamic => [  | 
| 
332
 | 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
46
 | 
                         map $scope_var->($_), @{$param->{dynamic}}  | 
| 
 
 | 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
58
 | 
    | 
| 
333
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     ],  | 
| 
334
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 };  | 
| 
335
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             } else {  | 
| 
336
 | 
143
 | 
 
 | 
 
 | 
 
 | 
 
 | 
297
 | 
                 $replacement{content} = $param;  | 
| 
337
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
338
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
339
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
340
 | 
248
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
346
 | 
         if (@{$replacement{repeat}} = @{$action->{repeat}}) {  | 
| 
 
 | 
248
 | 
 
 | 
 
 | 
 
 | 
 
 | 
685
 | 
    | 
| 
 
 | 
248
 | 
 
 | 
 
 | 
 
 | 
 
 | 
441
 | 
    | 
| 
341
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
             my $rfirst = \$replacement{repeat}[0];  | 
| 
342
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
21
 | 
             if (!defined $$rfirst->{var}[0]) {  | 
| 
343
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
                 $$rfirst = { var => $scope_var->($$rfirst->{var}), rules => $$rfirst->{rules} };  | 
| 
344
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
                 $did_replace++;  | 
| 
345
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
346
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
347
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
348
 | 
248
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1478
 | 
         return \%replacement if $did_replace;  | 
| 
349
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
350
 | 
178
 | 
 
 | 
 
 | 
 
 | 
 
 | 
453
 | 
     $action  | 
| 
351
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
352
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
353
 | 
244
 | 
  
 50
  
 | 
 
 | 
  
244
  
 | 
  
0
  
 | 
579
 | 
 method add_rule($selector, $action, @actions) {  | 
| 
 
 | 
244
 | 
 
 | 
 
 | 
 
 | 
 
 | 
395
 | 
    | 
| 
 
 | 
244
 | 
 
 | 
 
 | 
 
 | 
 
 | 
474
 | 
    | 
| 
 
 | 
244
 | 
 
 | 
 
 | 
 
 | 
 
 | 
330
 | 
    | 
| 
354
 | 
244
 | 
 
 | 
 
 | 
 
 | 
 
 | 
367
 | 
     push @{$self->{rules}}, {  | 
| 
 
 | 
244
 | 
 
 | 
 
 | 
 
 | 
 
 | 
796
 | 
    | 
| 
355
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         selector => $selector,  | 
| 
356
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         result   => _reduce_actions($action, @actions),  | 
| 
357
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     };  | 
| 
358
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
359
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
360
 | 
237
 | 
  
 50
  
 | 
  
 66
  
 | 
  
237
  
 | 
 
 | 
498
 | 
 fun _skip_children($name, $parser, :$collect_content = undef) {  | 
| 
 
 | 
237
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
659
 | 
    | 
| 
 
 | 
237
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
511
 | 
    | 
| 
 
 | 
237
 | 
 
 | 
 
 | 
 
 | 
 
 | 
418
 | 
    | 
| 
 
 | 
237
 | 
 
 | 
 
 | 
 
 | 
 
 | 
526
 | 
    | 
| 
 
 | 
237
 | 
 
 | 
 
 | 
 
 | 
 
 | 
299
 | 
    | 
| 
361
 | 
237
 | 
 
 | 
 
 | 
 
 | 
 
 | 
359
 | 
     my $content = '';  | 
| 
362
 | 
237
 | 
 
 | 
 
 | 
 
 | 
 
 | 
321
 | 
     my $depth = 0;  | 
| 
363
 | 
237
 | 
 
 | 
 
 | 
 
 | 
 
 | 
328
 | 
     while () {  | 
| 
364
 | 
520
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
1266
 | 
         my $token = $parser->parse // die "Internal error: missing '$name>' in parser results";  | 
| 
365
 | 
520
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
1883
 | 
         if ($token->{type} eq TT_TAG_CLOSE) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
366
 | 
252
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
757
 | 
             last if $depth == 0;  | 
| 
367
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
33
 | 
             $depth--;  | 
| 
368
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } elsif ($token->{type} eq TT_TAG_OPEN) {  | 
| 
369
 | 
30
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
152
 | 
             $depth++ if !$token->{is_self_closing};  | 
| 
370
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } elsif ($collect_content && $token->{type} eq TT_TEXT) {  | 
| 
371
 | 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
140
 | 
             $content .= $token->{content};  | 
| 
372
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
373
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
374
 | 
237
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
575
 | 
     $collect_content ? $content : undef  | 
| 
375
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
376
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
377
 | 
260
 | 
  
 50
  
 | 
 
 | 
  
260
  
 | 
 
 | 
570
 | 
 fun _with_stopper($alternatives, $result) {  | 
| 
 
 | 
260
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
475
 | 
    | 
| 
 
 | 
260
 | 
 
 | 
 
 | 
 
 | 
 
 | 
447
 | 
    | 
| 
 
 | 
260
 | 
 
 | 
 
 | 
 
 | 
 
 | 
313
 | 
    | 
| 
378
 | 
260
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1456
 | 
     map [ @$_, $result ], @$alternatives  | 
| 
379
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
380
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
381
 | 
273
 | 
  
 50
  
 | 
 
 | 
  
273
  
 | 
  
0
  
 | 
610
 | 
 method compile($name, $html) {  | 
| 
 
 | 
273
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
550
 | 
    | 
| 
 
 | 
273
 | 
 
 | 
 
 | 
 
 | 
 
 | 
387
 | 
    | 
| 
 
 | 
273
 | 
 
 | 
 
 | 
 
 | 
 
 | 
499
 | 
    | 
| 
 
 | 
273
 | 
 
 | 
 
 | 
 
 | 
 
 | 
386
 | 
    | 
| 
382
 | 
273
 | 
 
 | 
 
 | 
 
 | 
 
 | 
966
 | 
     my $codegen = HTML::Blitz::CodeGen->new(name => $name);  | 
| 
383
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $matcher = HTML::Blitz::Matcher->new([  | 
| 
384
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         map _with_stopper($_->{selector}, _bind_scope($codegen->scope, $_->{result})),  | 
| 
385
 | 
273
 | 
 
 | 
 
 | 
 
 | 
 
 | 
506
 | 
             @{$self->{rules}}  | 
| 
 
 | 
273
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1044
 | 
    | 
| 
386
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     ]);  | 
| 
387
 | 
273
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1133
 | 
     my $parser  = HTML::Blitz::Parser->new($name, $html);  | 
| 
388
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
389
 | 
273
 | 
 
 | 
 
 | 
 
 | 
 
 | 
780
 | 
     while (my $token = $parser->parse) {  | 
| 
390
 | 
4811
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
16261
 | 
         if ($token->{type} eq TT_DOCTYPE) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
391
 | 
9
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
25
 | 
             if ($self->{keep_doctype}) {  | 
| 
392
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
25
 | 
                 $codegen->emit_doctype;  | 
| 
393
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
394
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } elsif ($token->{type} eq TT_COMMENT) {  | 
| 
395
 | 
38
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
213
 | 
             if ($token->{content} =~ /$self->{keep_comments_re}/) {  | 
| 
396
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
90
 | 
                 $codegen->emit_comment($token->{content});  | 
| 
397
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
398
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } elsif ($token->{type} eq TT_TEXT) {  | 
| 
399
 | 
2151
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
9537
 | 
             if ($token->{content} =~ /$self->{dummy_marker_re}/) {  | 
| 
400
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
                 $parser->throw_for($token, "raw text contains forbidden dummy marker $self->{dummy_marker_re}");  | 
| 
401
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
402
 | 
2148
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5322
 | 
             my $cur_tag = $parser->current_tag;  | 
| 
403
 | 
2148
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
4944
 | 
             if ($cur_tag eq 'script') {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
404
 | 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
91
 | 
                 $codegen->emit_script_text($token->{content});  | 
| 
405
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             } elsif ($cur_tag eq 'style') {  | 
| 
406
 | 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
170
 | 
                 $codegen->emit_style_text($token->{content});  | 
| 
407
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             } else {  | 
| 
408
 | 
2054
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5069
 | 
                 $codegen->emit_text($token->{content});  | 
| 
409
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
410
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } elsif ($token->{type} eq TT_TAG_CLOSE) {  | 
| 
411
 | 
1086
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3655
 | 
             $matcher->leave(\my %ret);  | 
| 
412
 | 
1086
 | 
 
 | 
  
 66
  
 | 
 
 | 
 
 | 
5168
 | 
             ($ret{codegen} // $codegen)->emit_close_tag($token->{name});  | 
| 
413
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } elsif ($token->{type} eq TT_TAG_OPEN) {  | 
| 
414
 | 
1527
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4536
 | 
             my $action = _reduce_actions $matcher->enter($token->{name}, $token->{attrs});  | 
| 
415
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
416
 | 
1527
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
6420
 | 
             if (defined($action) && $action->{type} eq AT_REMOVE_IF) {  | 
| 
417
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
49
 | 
                 my $cond_gen = $codegen->insert_cond($action->{cond});  | 
| 
418
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
                 $action = $action->{else};  | 
| 
419
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
420
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
                 my $outer_gen = $codegen;  | 
| 
421
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
                 $codegen = $cond_gen;  | 
| 
422
 | 
5
 | 
  
 50
  
 | 
 
 | 
  
5
  
 | 
 
 | 
16
 | 
                 $matcher->on_leave(fun ($ret = {}) {  | 
| 
 
 | 
5
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
19
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
    | 
| 
423
 | 
5
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
29
 | 
                     $ret->{codegen} //= $cond_gen;  | 
| 
424
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
                     $codegen = $outer_gen;  | 
| 
425
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
43
 | 
                 });  | 
| 
426
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
427
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
428
 | 
1527
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
3064
 | 
             if (!defined $action) {  | 
| 
429
 | 
1177
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1913
 | 
                 my $attrs = $token->{attrs};  | 
| 
430
 | 
1177
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6312
 | 
                 my @bad_attrs = sort grep $attrs->{$_} =~ /$self->{dummy_marker_re}/, keys %$attrs;  | 
| 
431
 | 
1177
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
2758
 | 
                 if (@bad_attrs) {  | 
| 
432
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
                     $parser->throw_for($token, "'$token->{name}' tag contains forbidden dummy marker $self->{dummy_marker_re} in the following attribute(s): " . join(', ', @bad_attrs));  | 
| 
433
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
434
 | 
1176
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
5177
 | 
                 $codegen->emit_open_tag($token->{name}, $attrs, self_closing => $token->{is_self_closing} && !$token->{is_void});  | 
| 
435
 | 
1176
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
2833
 | 
                 $matcher->leave if $token->{is_self_closing};  | 
| 
436
 | 
1176
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5255
 | 
                 next;  | 
| 
437
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
438
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
439
 | 
350
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
771
 | 
             if ($action->{type} eq AT_REPLACE_OUTER) {  | 
| 
440
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
33
 | 
                 my $param = $action->{param};  | 
| 
441
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
                 my $skipped = 0;  | 
| 
442
 | 
7
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
31
 | 
                 if ($param->{type} eq AT_P_IMMEDIATE) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
443
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
                     $codegen->emit_text($param->{value});  | 
| 
444
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 } elsif ($param->{type} eq AT_P_VARIABLE) {  | 
| 
445
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
                     $codegen->emit_variable($param->{value});  | 
| 
446
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 } elsif ($param->{type} eq AT_P_FRAGMENT) {  | 
| 
447
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
                     $codegen->incorporate($param->{value});  | 
| 
448
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 } elsif ($param->{type} eq AT_P_VARHTML) {  | 
| 
449
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
                     $codegen->emit_variable_html($param->{value});  | 
| 
450
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 } else {  | 
| 
451
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
14
 | 
                     $param->{type} eq AT_P_TRANSFORM  | 
| 
452
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         or die "Internal error: unexpected parameter type '$param->{type}'";  | 
| 
453
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
7
 | 
                     if (!$token->{is_void}) {  | 
| 
454
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
9
 | 
                         my $text_content = $token->{is_self_closing} ? '' : _skip_children $token->{name}, $parser, collect_content => 1;  | 
| 
455
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
                         $skipped = 1;  | 
| 
456
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
                         $text_content = '' . $param->{static}->($text_content);  | 
| 
457
 | 
2
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
8
 | 
                         if (@{$param->{dynamic}}) {  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
    | 
| 
458
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
                             $codegen->emit_call($param->{dynamic}, $text_content);  | 
| 
459
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         } else {  | 
| 
460
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
                             $codegen->emit_text($text_content);  | 
| 
461
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         }  | 
| 
462
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     }  | 
| 
463
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
464
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
465
 | 
7
 | 
  
 50
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
51
 | 
                 _skip_children $token->{name}, $parser if !$skipped && !$token->{is_self_closing};  | 
| 
466
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
                 $matcher->leave;  | 
| 
467
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27
 | 
                 next;  | 
| 
468
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
469
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
470
 | 
343
 | 
 
 | 
 
 | 
 
 | 
 
 | 
828
 | 
             while ($action->{type} eq AT_REPEAT_OUTER) {  | 
| 
471
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
                 my $loop_gen = $codegen->insert_loop($action->{var});  | 
| 
472
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
473
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
                 for my $proto_rule (@{$action->{rules}}) {  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
    | 
| 
474
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
                     my ($selector, @actions) = @$proto_rule;  | 
| 
475
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
                     my $action = _bind_scope $loop_gen->scope, _reduce_actions @actions;  | 
| 
476
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
                     $matcher->add_temp_rule(_with_stopper($selector, $action));  | 
| 
477
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
478
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
479
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
                 my $inplace = _reduce_actions @{$action->{inplace}};  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
    | 
| 
480
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 $action = defined($inplace)  | 
| 
481
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     ? _combine_actions $action->{nested}, _bind_scope $loop_gen->scope, $inplace  | 
| 
482
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
9
 | 
                     : $action->{nested};  | 
| 
483
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
484
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
                 my $outer_gen = $codegen;  | 
| 
485
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
                 $codegen = $loop_gen;  | 
| 
486
 | 
1
 | 
  
 50
  
 | 
 
 | 
  
1
  
 | 
 
 | 
4
 | 
                 $matcher->on_leave(fun ($ret = {}) {  | 
| 
 
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
5
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
    | 
| 
487
 | 
1
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
6
 | 
                     $ret->{codegen} //= $loop_gen;  | 
| 
488
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
                     $codegen = $outer_gen;  | 
| 
489
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
                 });  | 
| 
490
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
491
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
492
 | 
343
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
707
 | 
             $action->{type} eq AT_REPLACE_INNER  | 
| 
493
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 or die "Internal error: unexpected action type '$action->{type}'";  | 
| 
494
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
495
 | 
343
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1209
 | 
             $codegen->emit_open_tag_name_fragment($token->{name});  | 
| 
496
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
497
 | 
343
 | 
 
 | 
 
 | 
 
 | 
 
 | 
643
 | 
             my $attrset = $action->{attrset};  | 
| 
498
 | 
343
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
721
 | 
             if ($attrset->{type} eq AT_AS_REPLACE_ATTRS) {  | 
| 
499
 | 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
                 my $attrs = $attrset->{content};  | 
| 
500
 | 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
64
 | 
                 for my $attr (sort keys %$attrs) {  | 
| 
501
 | 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
72
 | 
                     my $param = $attrs->{$attr};  | 
| 
502
 | 
37
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
68
 | 
                     if ($param->{type} eq AT_P_IMMEDIATE) {  | 
| 
503
 | 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
76
 | 
                         $codegen->emit_open_tag_attr_fragment($attr, $param->{value});  | 
| 
504
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     } else {  | 
| 
505
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
13
 | 
                         $param->{type} eq AT_P_VARIABLE  | 
| 
506
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                             or die "Internal error: unexpected parameter type '$param->{type}'";  | 
| 
507
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
                         $codegen->emit_open_tag_attr_var_fragment($attr, $param->{value});  | 
| 
508
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     }  | 
| 
509
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
510
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             } else {  | 
| 
511
 | 
327
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
746
 | 
                 $attrset->{type} eq AT_AS_MODIFY_ATTRS  | 
| 
512
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     or die "Internal error: unexpected attrset replacement type '$attrset->{type}'";  | 
| 
513
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
514
 | 
327
 | 
 
 | 
 
 | 
 
 | 
 
 | 
541
 | 
                 my $token_attrs = $token->{attrs};  | 
| 
515
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 my %attrs = map +(  | 
| 
516
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     $_ => {  | 
| 
517
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         type     => AT_P_IMMEDIATE,  | 
| 
518
 | 
327
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1901
 | 
                         value    => $token_attrs->{$_},  | 
| 
519
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         pristine => 1,  | 
| 
520
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     }  | 
| 
521
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 ), keys %$token_attrs;  | 
| 
522
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
523
 | 
327
 | 
 
 | 
 
 | 
 
 | 
 
 | 
667
 | 
                 my $attr_actions = $attrset->{content};  | 
| 
524
 | 
327
 | 
 
 | 
 
 | 
 
 | 
 
 | 
748
 | 
                 for my $attr (keys %$attr_actions) {  | 
| 
525
 | 
98
 | 
 
 | 
 
 | 
 
 | 
 
 | 
168
 | 
                     my $attr_action = $attr_actions->{$attr};  | 
| 
526
 | 
98
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
257
 | 
                     if ($attr_action->{type} eq AT_A_REMOVE_ATTR) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
527
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
47
 | 
                         delete $attrs{$attr};  | 
| 
528
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     } elsif ($attr_action->{type} eq AT_A_SET_ATTR) {  | 
| 
529
 | 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
145
 | 
                         $attrs{$attr} = $attr_action->{param};  | 
| 
530
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     } else {  | 
| 
531
 | 
46
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
97
 | 
                         $attr_action->{type} eq AT_A_MODIFY_ATTR  | 
| 
532
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                             or die "Internal error: unexpected attr action type '$attr_action->{type}'";  | 
| 
533
 | 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
76
 | 
                         my $param = $attr_action->{param};  | 
| 
534
 | 
46
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
100
 | 
                         $param->{type} eq AT_P_TRANSFORM  | 
| 
535
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                             or die "Internal error: unexpected parameter type '$param->{type}'";  | 
| 
536
 | 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
209
 | 
                         my $value = $param->{static}->($attrs{$attr}{value});  | 
| 
537
 | 
46
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
99
 | 
                         if (@{$param->{dynamic}}) {  | 
| 
 
 | 
46
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
131
 | 
    | 
| 
538
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
                             $attrs{$attr} = { type => AT_P_TRANSFORM, dynamic => $param->{dynamic}, value => $value };  | 
| 
539
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         } elsif (!defined $value) {  | 
| 
540
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
                             delete $attrs{$attr};  | 
| 
541
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         } else {  | 
| 
542
 | 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
146
 | 
                             $attrs{$attr} = { type => AT_P_IMMEDIATE, value => '' . $value };  | 
| 
543
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         }  | 
| 
544
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     }  | 
| 
545
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
546
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
547
 | 
327
 | 
 
 | 
 
 | 
 
 | 
 
 | 
541
 | 
                 my @bad_attrs;  | 
| 
548
 | 
327
 | 
 
 | 
 
 | 
 
 | 
 
 | 
901
 | 
                 for my $attr (sort keys %attrs) {  | 
| 
549
 | 
339
 | 
 
 | 
 
 | 
 
 | 
 
 | 
584
 | 
                     my $param = $attrs{$attr};  | 
| 
550
 | 
339
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
648
 | 
                     if ($param->{type} eq AT_P_IMMEDIATE) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
551
 | 
324
 | 
  
 50
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
1819
 | 
                         if ($param->{pristine} && $param->{value} =~ /$self->{dummy_marker_re}/) {  | 
| 
552
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                             push @bad_attrs, $attr;  | 
| 
553
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         }  | 
| 
554
 | 
324
 | 
 
 | 
 
 | 
 
 | 
 
 | 
946
 | 
                         $codegen->emit_open_tag_attr_fragment($attr, $param->{value});  | 
| 
555
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     } elsif ($param->{type} eq AT_P_VARIABLE) {  | 
| 
556
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
41
 | 
                         $codegen->emit_open_tag_attr_var_fragment($attr, $param->{value});  | 
| 
557
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     } else {  | 
| 
558
 | 
5
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
29
 | 
                         $param->{type} eq AT_P_TRANSFORM  | 
| 
559
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                             or die "Internal error: unexpected parameter type '$param->{type}'";  | 
| 
560
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
                         $codegen->emit_open_tag_attr_transform_fragment($attr, $param->{dynamic}, $param->{value});  | 
| 
561
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     }  | 
| 
562
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
563
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 @bad_attrs  | 
| 
564
 | 
327
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
1141
 | 
                     and $parser->throw_for($token, "<$token->{name}> tag contains forbidden dummy marker $self->{dummy_marker_re} in the following attribute(s): " . join(', ', @bad_attrs));  | 
| 
565
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
566
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
567
 | 
343
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1059
 | 
             $codegen->emit_open_tag_close_fragment;  | 
| 
568
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
569
 | 
343
 | 
 
 | 
 
 | 
 
 | 
 
 | 
506
 | 
             for my $repeat (@{$action->{repeat}}) {  | 
| 
 
 | 
343
 | 
 
 | 
 
 | 
 
 | 
 
 | 
782
 | 
    | 
| 
570
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
                 my $loop_gen = $codegen->insert_loop($repeat->{var});  | 
| 
571
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
                 for my $proto_rule (@{$repeat->{rules}}) {  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
    | 
| 
572
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
                     my ($selector, @actions) = @$proto_rule;  | 
| 
573
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
25
 | 
                     my $action = _bind_scope $loop_gen->scope, _reduce_actions @actions;  | 
| 
574
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
39
 | 
                     $matcher->add_temp_rule(_with_stopper($selector, $action));  | 
| 
575
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
576
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
577
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
                 my $outer_gen = $codegen;  | 
| 
578
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
                 $codegen = $loop_gen;  | 
| 
579
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
14
 | 
                 $matcher->on_leave(fun (@) { $codegen = $outer_gen; });  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
    | 
| 
580
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
581
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
582
 | 
343
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1068
 | 
             if (defined(my $param = $action->{content})) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
583
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 $token->{is_void}  | 
| 
584
 | 
241
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
524
 | 
                     and $parser->throw_for($token, "<$token->{name}> tag cannot have content");  | 
| 
585
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
586
 | 
241
 | 
 
 | 
 
 | 
 
 | 
 
 | 
342
 | 
                 my $skipped = 0;  | 
| 
587
 | 
241
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
612
 | 
                 if ($param->{type} eq AT_P_IMMEDIATE) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
588
 | 
153
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
351
 | 
                     if ($token->{name} eq 'script') {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
589
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
50
 | 
                         $codegen->emit_script_text($param->{value});  | 
| 
590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     } elsif ($token->{name} eq 'style') {  | 
| 
591
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
                         $codegen->emit_style_text($param->{value});  | 
| 
592
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     } else {  | 
| 
593
 | 
132
 | 
 
 | 
 
 | 
 
 | 
 
 | 
325
 | 
                         $codegen->emit_text($param->{value});  | 
| 
594
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     }  | 
| 
595
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 } elsif ($param->{type} eq AT_P_VARIABLE) {  | 
| 
596
 | 
30
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
108
 | 
                     if ($token->{name} eq 'script') {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
597
 | 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
49
 | 
                         $codegen->emit_variable_script($param->{value});  | 
| 
598
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     } elsif ($token->{name} eq 'style') {  | 
| 
599
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
                         $codegen->emit_variable_style($param->{value});  | 
| 
600
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     } else {  | 
| 
601
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
40
 | 
                         $codegen->emit_variable($param->{value});  | 
| 
602
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     }  | 
| 
603
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 } elsif ($param->{type} eq AT_P_FRAGMENT) {  | 
| 
604
 | 
7
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
83
 | 
                     $token->{name} eq 'script' || $token->{name} eq 'style' || $token->{name} eq 'title'  | 
| 
 
 | 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
605
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         and $parser->throw_for($token, "<$token->{name}> tag cannot have descendant elements");  | 
| 
606
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
                     $codegen->incorporate($param->{value});  | 
| 
607
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 } elsif ($param->{type} eq AT_P_VARHTML) {  | 
| 
608
 | 
4
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
56
 | 
                     $token->{name} eq 'script' || $token->{name} eq 'style' || $token->{name} eq 'title'  | 
| 
 
 | 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
609
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         and $parser->throw_for($token, "<$token->{name}> tag cannot have descendant elements");  | 
| 
610
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
                     $codegen->emit_variable_html($param->{value});  | 
| 
611
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 } else {  | 
| 
612
 | 
47
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
97
 | 
                     $param->{type} eq AT_P_TRANSFORM  | 
| 
613
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         or die "Internal error: unexpected parameter type '$param->{type}'";  | 
| 
614
 | 
47
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
136
 | 
                     my $text_content = $token->{is_self_closing} ? '' : _skip_children $token->{name}, $parser, collect_content => 1;  | 
| 
615
 | 
47
 | 
 
 | 
 
 | 
 
 | 
 
 | 
82
 | 
                     $skipped = 1;  | 
| 
616
 | 
47
 | 
 
 | 
 
 | 
 
 | 
 
 | 
161
 | 
                     $text_content = '' . $param->{static}->($text_content);  | 
| 
617
 | 
47
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
145
 | 
                     if (@{$param->{dynamic}}) {  | 
| 
 
 | 
47
 | 
 
 | 
 
 | 
 
 | 
 
 | 
102
 | 
    | 
| 
618
 | 
25
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
74
 | 
                         if ($token->{name} eq 'script') {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
619
 | 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
66
 | 
                             $codegen->emit_call_script($param->{dynamic}, $text_content);  | 
| 
620
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         } elsif ($token->{name} eq 'style') {  | 
| 
621
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
                             $codegen->emit_call_style($param->{dynamic}, $text_content);  | 
| 
622
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         } else {  | 
| 
623
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
31
 | 
                             $codegen->emit_call($param->{dynamic}, $text_content);  | 
| 
624
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         }  | 
| 
625
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     } else {  | 
| 
626
 | 
22
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
63
 | 
                         if ($token->{name} eq 'script') {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
627
 | 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
50
 | 
                             $codegen->emit_script_text($text_content);  | 
| 
628
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         } elsif ($token->{name} eq 'style') {  | 
| 
629
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
                             $codegen->emit_style_text($text_content);  | 
| 
630
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         } else {  | 
| 
631
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
                             $codegen->emit_text($text_content);  | 
| 
632
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                         }  | 
| 
633
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     }  | 
| 
634
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
635
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
636
 | 
225
 | 
  
 50
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
1084
 | 
                 _skip_children $token->{name}, $parser if !$skipped && !$token->{is_self_closing};  | 
| 
637
 | 
225
 | 
 
 | 
 
 | 
 
 | 
 
 | 
843
 | 
                 $matcher->leave(\my %ret);  | 
| 
638
 | 
225
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
1176
 | 
                 ($ret{codegen} // $codegen)->emit_close_tag($token->{name});  | 
| 
639
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             } elsif ($token->{is_self_closing}) {  | 
| 
640
 | 
42
 | 
 
 | 
 
 | 
 
 | 
 
 | 
136
 | 
                 $matcher->leave;  | 
| 
641
 | 
42
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
260
 | 
                 $codegen->emit_close_tag($token->{name}) if !$token->{is_void};  | 
| 
642
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
643
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
644
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } else {  | 
| 
645
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             # uncoverable statement  | 
| 
646
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             die "Internal error: unhandled token type '$token->{type}'";  | 
| 
647
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
648
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
649
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
650
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $codegen  | 
| 
651
 | 
236
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2386
 | 
 }  | 
| 
652
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
653
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1  |