File Coverage

blib/lib/Marpa/HTML/Callback.pm
Criterion Covered Total %
statement 129 151 85.4
branch 33 58 56.9
condition n/a
subroutine 19 21 90.4
pod 11 11 100.0
total 192 241 79.6


line stmt bran cond sub pod time code
1             # This software is copyright (c) 2011 by Jeffrey Kegler
2             # This is free software; you can redistribute it and/or modify it
3             # under the same terms as the Perl 5 programming language system
4             # itself.
5              
6             package Marpa::HTML::Internal::Callback;
7              
8 6     6   168 use 5.010;
  6         19  
  6         234  
9 6     6   31 use warnings;
  6         8  
  6         175  
10 6     6   29 use strict;
  6         10  
  6         196  
11 6     6   30 use integer;
  6         9  
  6         44  
12              
13 6     6   136 use Carp;
  6         12  
  6         383  
14 6     6   33 use English qw( -no_match_vars );
  6         9  
  6         41  
15              
16             sub Marpa::HTML::start_tag {
17              
18 9     9 1 35 my $parse_instance = $Marpa::HTML::Internal::PARSE_INSTANCE;
19 9 50       21 Carp::croak(q{Attempt to fetch start tag outside of a parse})
20             if not defined $parse_instance;
21              
22 9         14 my $element = $Marpa::HTML::Internal::PER_NODE_DATA->{element};
23 9 50       21 return if not $element;
24              
25             #<<< perltidy cycles on this as of 2009-11-28
26 9 100       29 return if not defined (my $start_tag_token_id =
27             $Marpa::HTML::Internal::PER_NODE_DATA->{start_tag_token_id});
28             #>>>
29             #
30             # Inlining this might be faster, especially since I have to dummy
31             # up a tdesc list to make it work.
32 3         18 return ${
33 3         14 Marpa::HTML::Internal::tdesc_list_to_literal( $parse_instance,
34             [ [ UNVALUED_SPAN => $start_tag_token_id, $start_tag_token_id ] ]
35             )
36             };
37             } ## end sub Marpa::HTML::start_tag
38              
39             sub Marpa::HTML::end_tag {
40              
41 9     9 1 17 my $parse_instance = $Marpa::HTML::Internal::PARSE_INSTANCE;
42 9 50       35 Carp::croak(q{Attempt to fetch an end tag outside of a parse})
43             if not defined $parse_instance;
44              
45 9         105 my $element = $Marpa::HTML::Internal::PER_NODE_DATA->{element};
46 9 50       22 return if not $element;
47              
48             #<<< perltidy cycles on this as of 2009-11-28
49 9 100       32 return if not defined (my $end_tag_token_id =
50             $Marpa::HTML::Internal::PER_NODE_DATA->{end_tag_token_id});
51             #>>>
52             #
53             # Inlining this might be faster, especially since I have to dummy
54             # up a tdesc list to make it work.
55 1         5 return ${
56 1         2 Marpa::HTML::Internal::tdesc_list_to_literal( $parse_instance,
57             [ [ UNVALUED_SPAN => $end_tag_token_id, $end_tag_token_id ] ] )
58             };
59             } ## end sub Marpa::HTML::end_tag
60              
61             sub Marpa::HTML::contents {
62              
63 14     14 1 55 my $parse_instance = $Marpa::HTML::Internal::PARSE_INSTANCE;
64 14 50       32 Carp::croak(
65             q{Attempt to fetch an element contents outside of a parse})
66             if not defined $parse_instance;
67              
68 14         25 my $element = $Marpa::HTML::Internal::PER_NODE_DATA->{element};
69 14 50       29 return if not $element;
70              
71 14 100       44 my $contents_start_tdesc_ix =
72             defined $Marpa::HTML::Internal::PER_NODE_DATA->{start_tag_token_id}
73             ? 1
74             : 0;
75              
76 6         16 my $contents_end_tdesc_ix =
77             defined $Marpa::HTML::Internal::PER_NODE_DATA->{end_tag_token_id}
78 8         11 ? ( $#{$Marpa::HTML::Internal::TDESC_LIST} - 1 )
79 14 100       31 : $#{$Marpa::HTML::Internal::TDESC_LIST};
80              
81 14         48 return ${
82 14         20 Marpa::HTML::Internal::tdesc_list_to_literal(
83             $parse_instance,
84 14         28 [ @{$Marpa::HTML::Internal::TDESC_LIST}
85             [ $contents_start_tdesc_ix .. $contents_end_tdesc_ix ]
86             ]
87             )
88             };
89             } ## end sub Marpa::HTML::contents
90              
91             sub Marpa::HTML::values {
92              
93 12     12 1 64 my $parse_instance = $Marpa::HTML::Internal::PARSE_INSTANCE;
94 12 50       29 Carp::croak(q{Attempt to fetch an end tag outside of a parse})
95             if not defined $parse_instance;
96              
97 10         23 my @values = grep {defined}
  10         21  
98 43         89 map { $_->[Marpa::HTML::Internal::TDesc::Element::VALUE] }
99 12         27 grep { $_->[Marpa::HTML::Internal::TDesc::TYPE] eq 'VALUED_SPAN' }
100 12         20 @{$Marpa::HTML::Internal::TDESC_LIST};
101              
102 12         115 return \@values;
103             } ## end sub Marpa::HTML::values
104              
105             sub Marpa::HTML::descendants {
106              
107 395     395 1 7115 my ($argspecs) = @_;
108              
109 395         735 my $parse_instance = $Marpa::HTML::Internal::PARSE_INSTANCE;
110 395 50       890 Carp::croak(q{Attempt to fetch an end tag outside of a parse})
111             if not defined $parse_instance;
112 395         595 my $tokens = $parse_instance->{tokens};
113              
114 395         627 my @argspecs = ();
115 395         1543 for my $argspec ( split /,/xms, $argspecs ) {
116 1185         4229 $argspec =~ s/\A \s* //xms;
117 1185         4796 $argspec =~ s/ \s* \z//xms;
118 1185         2414 push @argspecs, $argspec;
119             }
120              
121 395         866 my @children = ();
122 395         543 for my $tdesc ( @{$Marpa::HTML::Internal::TDESC_LIST} ) {
  395         877  
123 1211         1722 given ( $tdesc->[Marpa::HTML::Internal::TDesc::TYPE] ) {
124 1211         1770 when ('UNVALUED_SPAN') {
125 212         310 my $start_token =
126             $tdesc->[Marpa::HTML::Internal::TDesc::START_TOKEN];
127 212         270 my $end_token =
128             $tdesc->[Marpa::HTML::Internal::TDesc::END_TOKEN];
129 212         911 push @children,
130 212         386 map { [ 'token', $_ ] } ( $start_token .. $end_token );
131             } ## end when ('UNVALUED_SPAN')
132 999         2011 when ('VALUED_SPAN') {
133 418         1407 push @children, [ 'valued_span', $tdesc ];
134             }
135             } ## end given
136             } ## end for my $tdesc ( @{$Marpa::HTML::Internal::TDESC_LIST})
137              
138 395         650 my @return;
139 395         639 CHILD: for my $child (@children) {
140 630         2005 my @values = ();
141 630         636 my ( $child_type, $data ) = @{$child};
  630         1274  
142 630         1199 for (@argspecs) {
143 1890         4087 when ('token_type') {
144 630 100       2084 push @values,
145             ( $child_type eq 'token' )
146             ? (
147             $tokens->[$data]->[Marpa::HTML::Internal::Token::TYPE] )
148             : undef;
149             } ## end when ('token_type')
150 1260         1437 when ('pseudoclass') {
151 0 0       0 push @values,
152             ( $child_type eq 'valued_span' )
153             ? $data
154             ->[Marpa::HTML::Internal::TDesc::Element::NODE_DATA]
155             ->{pseudoclass}
156             : undef;
157             } ## end when ('pseudoclass')
158 1260         1852 when ('element') {
159 630 100       2492 push @values,
160             ( $child_type eq 'valued_span' )
161             ? $data
162             ->[Marpa::HTML::Internal::TDesc::Element::NODE_DATA]
163             ->{element}
164             : undef;
165             } ## end when ('element')
166 630         735 when ('literal_ref') {
167 0 0       0 my $tdesc =
168             $child_type eq 'token'
169             ? [ 'UNVALUED_SPAN', $data, $data ]
170             : $data;
171 0         0 push @values,
172             Marpa::HTML::Internal::tdesc_list_to_literal(
173             $parse_instance, [$tdesc] );
174             } ## end when ('literal_ref')
175 630         903 when ('literal') {
176 630 100       1503 my $tdesc =
177             $child_type eq 'token'
178             ? [ 'UNVALUED_SPAN', $data, $data ]
179             : $data;
180 630         2362 push @values,
181             ${
182 630         725 Marpa::HTML::Internal::tdesc_list_to_literal(
183             $parse_instance, [$tdesc] )
184             };
185             } ## end when ('literal')
186 0         0 when ('original') {
187 0         0 my ( $first_token_id, $last_token_id ) =
188             $child_type eq 'token'
189             ? ( $data, $data )
190 0 0       0 : @{$data}[
191             Marpa::HTML::Internal::TDesc::START_TOKEN,
192             Marpa::HTML::Internal::TDesc::END_TOKEN
193             ];
194 0         0 my $start_offset =
195             $tokens->[$first_token_id]
196             ->[Marpa::HTML::Internal::Token::START_OFFSET];
197 0         0 my $end_offset =
198             $tokens->[$last_token_id]
199             ->[Marpa::HTML::Internal::Token::END_OFFSET];
200 0         0 my $document = $parse_instance->{document};
201 0         0 push @values, substr ${$document}, $start_offset,
  0         0  
202             ( $end_offset - $start_offset );
203             } ## end when ('original')
204 0         0 when ('value') {
205 0 0       0 push @values,
206             ( $child_type eq 'valued_span' )
207             ? $data->[Marpa::HTML::Internal::TDesc::Element::VALUE]
208             : undef;
209             } ## end when ('value')
210 0         0 default {
211 0         0 Carp::croak(qq{Unrecognized argspec: "$_"})
212             }
213             } ## end for (@argspecs)
214 630         15108 push @return, \@values;
215             } ## end for my $child (@children)
216              
217 395         1731 return \@return;
218             } ## end sub Marpa::HTML::descendants
219              
220             sub Marpa::HTML::attributes {
221              
222 395     395 1 1660 my $parse_instance = $Marpa::HTML::Internal::PARSE_INSTANCE;
223 395 50       852 Carp::croak(
224             q{Attempt to fetch attributes from an undefined parse instance})
225             if not defined $parse_instance;
226              
227             # It is OK to call this routine on a non-element -- you'll just
228             # get back an empty list of attributes.
229 395         571 my $start_tag_token_id =
230             $Marpa::HTML::Internal::PER_NODE_DATA->{start_tag_token_id};
231 395 100       1484 return {} if not defined $start_tag_token_id;
232              
233 133         200 my $tokens = $parse_instance->{tokens};
234 133         219 my $start_tag_token = $tokens->[$start_tag_token_id];
235 133         315 return $start_tag_token->[Marpa::HTML::Internal::Token::ATTR];
236             } ## end sub Marpa::HTML::attributes
237              
238             # This assumes that a start token, if there is one
239             # with attributes, is the first token
240             sub create_fetch_attribute_closure {
241 18     18   35 my ($attribute) = @_;
242             return sub {
243 6530     6530   6972 my $parse_instance = $Marpa::HTML::Internal::PARSE_INSTANCE;
244 6530 50       12198 Carp::croak(
245             qq{Attempt to fetch attribute "$attribute" outside of a parse instance}
246             ) if not defined $parse_instance;
247              
248             # It is OK to call this routine on a non-element.
249 6530         8517 my $start_tag_token_id =
250             $Marpa::HTML::Internal::PER_NODE_DATA->{start_tag_token_id};
251              
252 6530 100       13084 return if not defined $start_tag_token_id;
253 5900         7475 my $tokens = $parse_instance->{tokens};
254 5900         7028 my $start_tag_token = $tokens->[$start_tag_token_id];
255 5900         9499 my $attribute_value =
256             $start_tag_token->[Marpa::HTML::Internal::Token::ATTR]
257             ->{$attribute};
258              
259 5900 100       23038 return defined $attribute_value ? lc $attribute_value : undef;
260 18         76 };
261             } ## end sub create_fetch_attribute_closure
262              
263 6     6   15510 no strict 'refs';
  6         15  
  6         427  
264             *{'Marpa::HTML::id'} = create_fetch_attribute_closure('id');
265             *{'Marpa::HTML::class'} = create_fetch_attribute_closure('class');
266             *{'Marpa::HTML::title'} = create_fetch_attribute_closure('title');
267 6     6   30 use strict;
  6         13  
  6         2546  
268              
269             package Marpa::HTML::Internal::Callback;
270              
271             sub Marpa::HTML::tagname {
272 404     404 1 1965 return $Marpa::HTML::Internal::PER_NODE_DATA->{element};
273             }
274              
275             sub Marpa::HTML::literal_ref {
276              
277 0     0 1 0 my $parse_instance = $Marpa::HTML::Internal::PARSE_INSTANCE;
278 0 0       0 Carp::croak('Attempt to get literal value outside of a parse')
279             if not defined $parse_instance;
280 0         0 my $tdesc_list = $Marpa::HTML::Internal::TDESC_LIST;
281 0         0 return Marpa::HTML::Internal::tdesc_list_to_literal( $parse_instance,
282             $tdesc_list );
283             } ## end sub Marpa::HTML::literal_ref
284              
285             sub Marpa::HTML::literal {
286              
287 108     108 1 434 my $parse_instance = $Marpa::HTML::Internal::PARSE_INSTANCE;
288 108 50       278 Carp::confess('Attempt to get literal value outside of a parse')
289             if not defined $parse_instance;
290 108 50       244 Carp::croak('Attempt to get literal value outside of a parse')
291             if not defined $parse_instance;
292 108         165 my $tdesc_list = $Marpa::HTML::Internal::TDESC_LIST;
293 108         357 return ${
294 108         119 Marpa::HTML::Internal::tdesc_list_to_literal( $parse_instance,
295             $tdesc_list )
296             };
297             } ## end sub Marpa::HTML::literal
298              
299             sub Marpa::HTML::offset {
300 0     0 1 0 my $parse_instance = $Marpa::HTML::Internal::PARSE_INSTANCE;
301 0 0       0 Carp::croak('Attempt to read offset outside of a parse instance')
302             if not defined $parse_instance;
303 0         0 return Marpa::HTML::Internal::earleme_to_offset( $parse_instance,
304             $Marpa::HTML::Internal::PER_NODE_DATA->{first_token_id} );
305             } ## end sub Marpa::HTML::offset
306              
307             sub Marpa::HTML::original {
308 2     2 1 12 my $parse_instance = $Marpa::HTML::Internal::PARSE_INSTANCE;
309 2 50       8 Carp::croak('Attempt to read offset outside of a parse instance')
310             if not defined $parse_instance;
311 2         5 my $tokens = $Marpa::HTML::Internal::PARSE_INSTANCE->{tokens};
312 2         6 my $document = $Marpa::HTML::Internal::PARSE_INSTANCE->{document};
313 2         4 my $first_token_id =
314             $Marpa::HTML::Internal::PER_NODE_DATA->{first_token_id};
315 2         3 my $last_token_id =
316             $Marpa::HTML::Internal::PER_NODE_DATA->{last_token_id};
317 2         5 my $start_offset =
318             $tokens->[$first_token_id]
319             ->[Marpa::HTML::Internal::Token::START_OFFSET];
320 2         22 my $end_offset =
321             $tokens->[$last_token_id]->[Marpa::HTML::Internal::Token::END_OFFSET];
322 2         3 return substr ${$document}, $start_offset,
  2         18  
323             ( $end_offset - $start_offset );
324             } ## end sub Marpa::HTML::original
325              
326             1;