File Coverage

blib/lib/YATT/Lite/LRXML/ParseEntpath.pm
Criterion Covered Total %
statement 106 109 97.2
branch 54 60 90.0
condition 10 11 90.9
subroutine 12 12 100.0
pod n/a
total 182 192 94.7


line stmt bran cond sub pod time code
1             package YATT::Lite::LRXML::ParseEntpath;
2 16     16   8722 use strict;
  16         43  
  16         582  
3 16     16   122 use warnings qw(FATAL all NONFATAL misc);
  16         41  
  16         610  
4              
5 16     16   91 package YATT::Lite::LRXML; use YATT::Lite::LRXML;
  16         38  
  16         4007  
6              
7             # item ::=
8             # pathItem
9             # [ pathItem+ ]
10              
11             # pathItem ::=
12             # [call => name, item, item, ...]
13             # [var => name]
14             # [array => item, item, ...]
15             # [hash => item, item, ...]
16             # [aref => item]
17             # [href => item]
18              
19             # Ex:
20             # [aref => [var => x]]
21             # [aref => [[var => i], [var => j]]
22              
23             sub _parse_text_entities {
24 177     177   584 (my MY $self, local $_, my $proceed) = @_;
25 177         476 my ($curpos, $endpos) = ($self->{curpos});
26 177         330 my @result;
27             {
28 177         318 local $self->{curpos};
  177         396  
29 177         368 my $total = length $_;
30 177         1541 while (s{^(.*?)$$self{re_entopn}}{}xs) {
31 28 100       127 if (length $1) {
32 15         44 push @result, $1;
33 15         60 $self->{endln} += numLines($1);
34 15         39 $curpos += length $1;
35             }
36 28         121 push @result, my $node = $self->mkentity($curpos, undef, $self->{endln});
37 28         70 $curpos = $total - length $_;
38 28         157 $node->[NODE_END] = $curpos;
39             }
40 177         545 $endpos = $self->{curpos};
41             }
42 177 50       462 if ($proceed) {
43 0         0 $self->{curpos} = $endpos;
44             }
45 177 100       493 if (@result) {
46 25 100       85 push @result, $_ if length $_;
47 25         140 \@result;
48             } else {
49 152         737 $_;
50             }
51             }
52              
53             # &yatt:foo:bar
54             #
55             # entpath ::= pipeline ';'
56             # pipeline ::= (pathElem | '[' | '{' )+
57             # pathElem ::= ':' name ('(' )?
58             # group C ::= term* C
59             # term ::= (pipeline | expr | text) [,:]?
60              
61             our (%open_head, %open_rest, %close_ch, %for_expr);
62             BEGIN {
63 16     16   110 %open_head = qw| ( call [ array { hash|;
64 16         55 %open_rest = qw| ( invoke [ aref { href|;
65 16         43 %close_ch = qw( ( ) [ ] { } );
66 16         14805 %for_expr = (aref => 1);
67             }
68             sub _parse_entpath {
69 442     442   36080 my MY $self = shift;
70 442         1253 local $self->{_original_entpath} = $_;
71 442   100     1911 my $how = shift || '_parse_pipeline';
72 442         959 my $prevlen = length $_;
73 442         1485 my @pipe = $self->$how(@_);
74 438 100       1942 unless (s{^;}{}xs) {
75 7 100       32 if (/^\s|^$/) {
76             die $self->synerror_at($self->{startln}
77 3         15 , q{Entity has no terminator: '%s'}
78             , $self->shortened_original_entpath);
79              
80             } else {
81             die $self->synerror_at($self->{startln}
82 4         22 , q{Syntax error in entity: '%s'}
83             , $self->shortened_original_entpath);
84             }
85             }
86 431         1181 $self->{curpos} += $prevlen - length $_;
87 431         2417 @pipe;
88             }
89             sub _parse_pipeline {
90 628     628   1238 (my MY $self) = @_;
91 628         1079 my @pipe;
92 628         3641 while (s{^ : (?\w+) (?\()?
93             | ^ (?\[)
94             | ^ (?(?\{))}{}xs) {
95 705 100       2071 my $table = @pipe ? \%open_rest : \%open_head;
96             my $type = $+{open} ? $table->{$+{open}}
97 705 100       4078 : @pipe ? 'prop' : 'var';
    100          
98 705         1617 push @pipe, do {
99 705 100 100     3700 if (not @pipe and $+{hash}) {
100 20         52 [$type, $self->_parse_hash]
101             } else {
102             [$type, defined $+{var} ? $+{var} : ()
103             , $+{open}
104 685 100       7078 ? $self->_parse_entgroup($close_ch{$+{open}}, $for_expr{$type})
    100          
105             : ()];
106             }
107             };
108             }
109 624 100       1672 if (wantarray) {
110             @pipe
111 436         1179 } else {
112 188 100       630 @pipe > 1 ? \@pipe : $pipe[0]
113             }
114             }
115             sub _parse_entgroup {
116 389     389   1185 (my MY $self, my ($close, $for_expr)) = @_;
117 389         899 my $prevlen = length $_;
118 389         702 my $emptycnt;
119             my @pipe;
120 389         642 do {
121 662         1655 push @pipe, $self->_parse_entterm($for_expr);
122 662 100 100     2225 if (length $_ == $prevlen and $emptycnt++) {
123             die $self->synerror_at($self->{startln}
124 1         5 , q{Syntax error in entity: '%s'}
125             , $self->shortened_original_entpath);
126             }
127 661         3578 $prevlen = length $_;
128             } until (s{^ ($$self{re_eclose})}{}xs);
129 388 100       1335 die $self->synerror_at($self->{startln}, q{Paren mismatch: expect %s got %s: str=%s}
130             , $close, $1, $_)
131             unless $1 eq $close;
132 385         4902 @pipe;
133             }
134             sub _parse_entterm {
135 691     691   1358 (my MY $self, my ($for_expr)) = @_;
136 691 100       1518 my $text_type = $for_expr ? 'expr' : 'text';
137 691 100       3000 if (s{^ ,}{}xs) {
    100          
138 10         28 return [text => ''];
139             } elsif (s{^ (?=[\)\]\};])}{}xs) {
140 62         180 return;
141             }
142 619         987 my $term = do {
143 619 100       4633 if (s{^(?: (? $$self{ch_etext} (?:$$self{ch_etext} | :)* )
144             | $$self{re_eparen}
145             )}{}xs) {
146 431         847 my $text = '';
147             TEXT: {
148 431         799 do {
  431         711  
149 880 100       3925 last TEXT if $+{close};
150 449 100       1829 if (defined $+{text}) {
    100          
151 431         1429 $text .= $+{text};
152             } elsif (defined $+{paren}) {
153 8         31 $text .= $+{paren};
154             }
155             $text .= $+{open} . $self->_parse_group_string($close_ch{$+{open}})
156 449 100       4638 if $+{open};
157             } while (s{^ (?: (? (?:$$self{ch_etext} | :)+)
158             | $$self{re_eparen}
159             | $$self{re_eopen}
160             | (?= (?[\)\]\};,])))}{}xs);
161             }
162 431 100       1807 [($text =~ s/^=// ? 'expr' : $text_type) => $text];
163             } else {
164 188         520 $self->_parse_pipeline;
165             }
166             };
167             # Suffix.
168 619         2233 s{^ [,:]?}{}xs;
169 619         1376 $term;
170             }
171              
172             sub _parse_group_string {
173 10     10   24 (my MY $self, my $close) = @_;
174 10         22 my $oldpos = pos;
175 10         16 my $text = '';
176 10         204 while (s{^ ((?:$$self{ch_etext}+ | [,:])*)
177             (?: $$self{re_eopen} | $$self{re_eclose})}{}xs) {
178             # print pos($_), "\n";
179 10         31 $text .= $&;
180 10 50       44 if ($+{close}) {
181             die $self->synerror_at($self->{startln}, q{Paren mismatch: expect %s got %s: str=%s}
182             , $close, $+{close}, substr($_, $oldpos, pos))
183 10 50       48 unless $+{close} eq $close;
184 10         25 last;
185             }
186 0 0       0 $text .= $self->_parse_group_string($close_ch{$+{open}}) if $+{open};
187             }
188 10         81 $text;
189             }
190              
191             sub _parse_hash {
192 20     20   33 (my MY $self) = @_;
193              
194 20         34 my ($lastlen, @hash);
195 20   66     56 while (not defined $lastlen or length $_ < $lastlen) {
196 49         73 $lastlen = length $_;
197 49 100       212 return @hash if s/^\}//;
198 29 50       167 s{^ ($$self{ch_etext}*) (?: [:,])}{}xs or last;
199 29         88 push @hash, [text => $1];
200 29         65 push @hash, $self->_parse_entterm;
201 29         135 s{^,}{};
202             }
203 0           die $self->synerror_at($self->{startln}, q{Paren mismatch: expect \} got %s}
204             , $self->shortened_original_entpath);
205             }
206              
207 16     16   148 use YATT::Lite::Breakpoint qw(break_load_parseentpath);
  16         42  
  16         908  
208             break_load_parseentpath();
209              
210             1;