File Coverage

blib/lib/YATT/Lite/LRXML/ParseEntpath.pm
Criterion Covered Total %
statement 106 109 97.2
branch 54 60 90.0
condition 9 11 81.8
subroutine 12 12 100.0
pod n/a
total 181 192 94.2


line stmt bran cond sub pod time code
1             package YATT::Lite::LRXML::ParseEntpath;
2 10     10   9620 use strict;
  10         22  
  10         327  
3 10     10   54 use warnings qw(FATAL all NONFATAL misc);
  10         19  
  10         437  
4              
5 10     10   52 package YATT::Lite::LRXML; use YATT::Lite::LRXML;
  10         18  
  10         3577  
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 160     160   438 (my MY $self, local $_, my $proceed) = @_;
25 160         371 my ($curpos, $endpos) = ($self->{curpos});
26 160         214 my @result;
27             {
28 160         207 local $self->{curpos};
  160         335  
29 160         229 my $total = length $_;
30 160         1470 while (s{^(.*?)$$self{re_entopn}}{}xs) {
31 28 100       99 if (length $1) {
32 15         43 push @result, $1;
33 15         58 $self->{endln} += numLines($1);
34 15         37 $curpos += length $1;
35             }
36 28         112 push @result, my $node = $self->mkentity($curpos, undef, $self->{endln});
37 28         65 $curpos = $total - length $_;
38 28         175 $node->[NODE_END] = $curpos;
39             }
40 160         387 $endpos = $self->{curpos};
41             }
42 160 50       361 if ($proceed) {
43 0         0 $self->{curpos} = $endpos;
44             }
45 160 100       401 if (@result) {
46 25 100       84 push @result, $_ if length $_;
47 25         136 \@result;
48             } else {
49 135         687 $_;
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 10     10   58 %open_head = qw| ( call [ array { hash|;
64 10         36 %open_rest = qw| ( invoke [ aref { href|;
65 10         32 %close_ch = qw( ( ) [ ] { } );
66 10         12732 %for_expr = (aref => 1);
67             }
68             sub _parse_entpath {
69 314     314   28027 my MY $self = shift;
70 314         860 local $self->{_original_entpath} = $_;
71 314   100     1306 my $how = shift || '_parse_pipeline';
72 314         430 my $prevlen = length $_;
73 314         933 my @pipe = $self->$how(@_);
74 310 100       1316 unless (s{^;}{}xs) {
75 7 100       27 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 303         709 $self->{curpos} += $prevlen - length $_;
87 303         1837 @pipe;
88             }
89             sub _parse_pipeline {
90 398     398   641 (my MY $self) = @_;
91 398         462 my @pipe;
92 398         2132 while (s{^ : (?\w+) (?\()?
93             | ^ (?\[)
94             | ^ (?(?\{))}{}xs) {
95 475 100       1261 my $table = @pipe ? \%open_rest : \%open_head;
96             my $type = $+{open} ? $table->{$+{open}}
97 475 100       3261 : @pipe ? 'prop' : 'var';
    100          
98 475         973 push @pipe, do {
99 475 100 66     2547 if (not @pipe and $+{hash}) {
100 20         50 [$type, $self->_parse_hash]
101             } else {
102             [$type, defined $+{var} ? $+{var} : ()
103             , $+{open}
104 455 100       7549 ? $self->_parse_entgroup($close_ch{$+{open}}, $for_expr{$type})
    100          
105             : ()];
106             }
107             };
108             }
109 394 100       852 if (wantarray) {
110             @pipe
111 308         841 } else {
112 86 100       308 @pipe > 1 ? \@pipe : $pipe[0]
113             }
114             }
115             sub _parse_entgroup {
116 177     177   499 (my MY $self, my ($close, $for_expr)) = @_;
117 177         336 my $prevlen = length $_;
118 177         213 my $emptycnt;
119             my @pipe;
120 177         215 do {
121 254         634 push @pipe, $self->_parse_entterm($for_expr);
122 254 100 100     828 if (length $_ == $prevlen and $emptycnt++) {
123             die $self->synerror_at($self->{startln}
124 1         7 , q{Syntax error in entity: '%s'}
125             , $self->shortened_original_entpath);
126             }
127 253         1614 $prevlen = length $_;
128             } until (s{^ ($$self{re_eclose})}{}xs);
129 176 100       528 die $self->synerror_at($self->{startln}, q{Paren mismatch: expect %s got %s: str=%s}
130             , $close, $1, $_)
131             unless $1 eq $close;
132 173         1743 @pipe;
133             }
134             sub _parse_entterm {
135 283     283   429 (my MY $self, my ($for_expr)) = @_;
136 283 100       529 my $text_type = $for_expr ? 'expr' : 'text';
137 283 100       1126 if (s{^ ,}{}xs) {
    100          
138 10         28 return [text => ''];
139             } elsif (s{^ (?=[\)\]\};])}{}xs) {
140 30         62 return;
141             }
142 243         270 my $term = do {
143 243 100       2198 if (s{^(?: (? $$self{ch_etext} (?:$$self{ch_etext} | :)* )
144             | $$self{re_eparen}
145             )}{}xs) {
146 157         228 my $text = '';
147             TEXT: {
148 157         175 do {
  157         183  
149 332 100       1681 last TEXT if $+{close};
150 175 100       920 if (defined $+{text}) {
    100          
151 157         610 $text .= $+{text};
152             } elsif (defined $+{paren}) {
153 8         39 $text .= $+{paren};
154             }
155             $text .= $+{open} . $self->_parse_group_string($close_ch{$+{open}})
156 175 100       2474 if $+{open};
157             } while (s{^ (?: (? (?:$$self{ch_etext} | :)+)
158             | $$self{re_eparen}
159             | $$self{re_eopen}
160             | (?= (?[\)\]\};,])))}{}xs);
161             }
162 157 100       792 [($text =~ s/^=// ? 'expr' : $text_type) => $text];
163             } else {
164 86         202 $self->_parse_pipeline;
165             }
166             };
167             # Suffix.
168 243         691 s{^ [,:]?}{}xs;
169 243         521 $term;
170             }
171              
172             sub _parse_group_string {
173 10     10   20 (my MY $self, my $close) = @_;
174 10         14 my $oldpos = pos;
175 10         16 my $text = '';
176 10         224 while (s{^ ((?:$$self{ch_etext}+ | [,:])*)
177             (?: $$self{re_eopen} | $$self{re_eclose})}{}xs) {
178             # print pos($_), "\n";
179 10         25 $text .= $&;
180 10 50       55 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       50 unless $+{close} eq $close;
184 10         23 last;
185             }
186 0 0       0 $text .= $self->_parse_group_string($close_ch{$+{open}}) if $+{open};
187             }
188 10         115 $text;
189             }
190              
191             sub _parse_hash {
192 20     20   31 (my MY $self) = @_;
193              
194 20         22 my ($lastlen, @hash);
195 20   66     53 while (not defined $lastlen or length $_ < $lastlen) {
196 49         63 $lastlen = length $_;
197 49 100       265 return @hash if s/^\}//;
198 29 50       199 s{^ ($$self{ch_etext}*) (?: [:,])}{}xs or last;
199 29         91 push @hash, [text => $1];
200 29         64 push @hash, $self->_parse_entterm;
201 29         154 s{^,}{};
202             }
203 0           die $self->synerror_at($self->{startln}, q{Paren mismatch: expect \} got %s}
204             , $self->shortened_original_entpath);
205             }
206              
207 10     10   63 use YATT::Lite::Breakpoint qw(break_load_parseentpath);
  10         37  
  10         643  
208             break_load_parseentpath();
209              
210             1;