File Coverage

blib/lib/PPIx/Regexp/Token/GroupType.pm
Criterion Covered Total %
statement 83 85 97.6
branch 12 16 75.0
condition 12 14 85.7
subroutine 18 19 94.7
pod 1 1 100.0
total 126 135 93.3


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             PPIx::Regexp::Token::GroupType - Represent a grouping parenthesis type.
4              
5             =head1 SYNOPSIS
6              
7             use PPIx::Regexp::Dumper;
8             PPIx::Regexp::Dumper->new( 'qr{(?i:foo)}smx' )
9             ->print();
10              
11             =head1 INHERITANCE
12              
13             C is a
14             L.
15              
16             C is the parent of
17             L,
18             L,
19             L,
20             L,
21             L,
22             L,
23             L,
24             L
25             and
26             L.
27              
28             =head1 DESCRIPTION
29              
30             This class represents any of the magic sequences of characters that can
31             follow an open parenthesis. This particular class is intended to be
32             abstract.
33              
34             =head1 METHODS
35              
36             This class provides no public methods beyond those provided by its
37             superclass.
38              
39             =cut
40              
41             package PPIx::Regexp::Token::GroupType;
42              
43 9     9   78 use strict;
  9         17  
  9         284  
44 9     9   45 use warnings;
  9         19  
  9         238  
45              
46 9     9   45 use base qw{ PPIx::Regexp::Token };
  9         19  
  9         709  
47              
48 9     9   64 use PPIx::Regexp::Constant qw{ MINIMUM_PERL @CARP_NOT };
  9         19  
  9         762  
49 9     9   58 use PPIx::Regexp::Util qw{ __ns_can };
  9         22  
  9         3637  
50              
51             our $VERSION = '0.087_01';
52              
53             # Return true if the token can be quantified, and false otherwise
54 19     19 1 85 sub can_be_quantified { return };
55              
56             =head2 __defining_string
57              
58             my $string = $class->__defining_string();
59              
60             This method is private to the C package, and is documented
61             for the author's benefit only. It may be changed or revoked without
62             notice.
63              
64             This method returns an array of strings that define the specific group
65             type. These strings will normally start with C<'?'>.
66              
67             Optionally, the first returned item may be a hash reference. The only
68             supported key is C<{suffix}>, which is a string to be suffixed to each
69             of the regular expressions made by C<__make_group_type_matcher()> out of
70             the defining strings, inside a C<(?= ... )>, so that it is not included
71             in the match.
72              
73             This method B be overridden, unless C<__make_group_type_matcher()>
74             is. The override B return the same thing each time, since the
75             results of C<__make_group_type_matcher()> are cached.
76              
77             =cut
78              
79             sub __defining_string {
80 0     0   0 require Carp;
81 0         0 Carp::confess(
82             'Programming error - __defining_string() must be overridden' );
83             }
84              
85             =head2 __make_group_type_matcher
86              
87             my $hash_ref = $class->__make_group_type_matcher();
88              
89             This method is private to the C package, and is documented
90             for the author's benefit only. It may be changed or revoked without
91             notice.
92              
93             This method returns a reference to a hash. The keys are regexp delimiter
94             characters which appear in the defining strings for the group type. For
95             each key, the value is a reference to an array of C objects,
96             properly escaped for the key character. Key C<''> provides the regular
97             expressions to be used if the regexp delimiter does not appear in any of
98             the defining strings.
99              
100             If this method is overridden by the subclass, method
101             C<__defining_string()> need not be, unless the overridden
102             C<__make_group_type_matcher()> calls C<__defining_string()>.
103              
104             =cut
105              
106             sub __make_group_type_matcher {
107 63     63   446 my ( $class ) = @_;
108              
109 63         328 my @defs = $class->__defining_string();
110              
111 63 100       200 my $opt = ref $defs[0] ? shift @defs : {};
112              
113             my $suffix = defined $opt->{suffix} ?
114 63 100       349 qr/ (?= \Q$opt->{suffix}\E ) /smx :
115             '';
116              
117 63         102 my %seen;
118 63         850 my @chars = grep { ! $seen{$_}++ } split qr{}smx, join '', @defs;
  2553         4846  
119              
120 63         262 my %rslt;
121 63         145 foreach my $str ( @defs ) {
122 318   100     546 push @{ $rslt{''} ||= [] }, qr{ \A \Q$str\E $suffix }smx;
  318         3683  
123 318         791 foreach my $chr ( @chars ) {
124 5505         49296 ( my $expr = $str ) =~ s/ (?= \Q$chr\E ) /\\/smxg;
125 5505   100     10408 push @{ $rslt{$chr} ||= [] }, qr{ \A \Q$expr\E $suffix }smx;
  5505         42385  
126             }
127             }
128 63         1526 return \%rslt;
129             }
130              
131             =head2 __match_setup
132              
133             $class->__match_setup( $tokenizer );
134              
135             This method is private to the C package, and is documented
136             for the author's benefit only. It may be changed or revoked without
137             notice.
138              
139             This method performs whatever setup is needed once it is determined that
140             the given group type has been detected. This method is called only if
141             the class matched at the current position in the string being parsed. It
142             must perform whatever extra setup is needed for the match. It returns
143             nothing.
144              
145             This method need not be overridden. The default does nothing.
146              
147             =cut
148              
149             sub __match_setup {
150 67     67   178 return;
151             }
152              
153             =head2 __setup_class
154              
155             $class->__setup_class( \%definition, \%opt );
156              
157             This method is private to the C package, and is documented
158             for the author's benefit only. It may be changed or revoked without
159             notice.
160              
161             This method uses the C<%definition> hash to create the
162             C<__defining_string()>, C, C, and
163             C methods for the calling class. Any of these
164             that already exist will B be replaced.
165              
166             The C<%definition> hash defines all the strings that specify tokens of
167             the invoking class. You can not (unfortunately) use this mechanism if
168             you need a regular expression to recognize a token that belongs to this
169             class. The keys of the C<%definition> hash are strings that specify
170             members of this class. The values are hashes that define the specific
171             member of the class. The following values are supported:
172              
173             =over
174              
175             =item {expl}
176              
177             This is the explanation of the element, to be returned by the
178             C method.
179              
180             =item {intro}
181              
182             This is the Perl version that introduced the element, as a string. The
183             default is the value of constant
184             L.
185              
186             =item {remov}
187              
188             This is the Perl version that removed the element, as a string. The
189             default is C, meaning that the element is still present in the
190             highest released version of Perl, whether development or production.
191              
192             =back
193              
194             The C<%opt> hash is optional, and defaults to the empty hash. It is
195             used, basically, for ad-hocery. The supported keys are:
196              
197             =over
198              
199             =item {suffix}
200              
201             If this element is defined, the first element returned by the generated
202             L<__defining_string()|/__defining_string> method is a hash containing
203             this key and value.
204              
205             =back
206              
207             =cut
208              
209             sub __setup_class {
210 63     63   187 my ( $class, $opt ) = @_;
211              
212 63   100     349 $opt ||= {};
213              
214 63 50       341 unless ( $class->__ns_can( '__defining_string' ) ) {
215 63         150 my $method = "${class}::__defining_string";
216 63         93 my @def_str = sort keys %{ $class->DEF };
  63         736  
217             defined $opt->{suffix}
218             and unshift @def_str, {
219             suffix => $opt->{suffix},
220 63 100       278 };
221 63         185 $class->DEF->{__defining_string} = \@def_str;
222 9     9   95 no strict qw{ refs };
  9         28  
  9         827  
223             *$method = sub {
224 63     63   136 my ( $self ) = @_;
225 63         97 return @{ $self->DEF->{__defining_string} };
  63         412  
226 63         488 };
227             }
228              
229 63 50       198 unless ( $class->__ns_can( 'explain' ) ) {
230 63         135 my $method = "${class}::explain";
231 9     9   54 no strict qw{ refs };
  9         19  
  9         840  
232             *$method = sub {
233 10     10   23 my ( $self ) = @_;
234 10         21 $DB::single = 1;
235 10         90 return $self->DEF->{ $self->unescaped_content() }{expl};
236 63         333 };
237             }
238              
239 63 50       177 unless ( $class->__ns_can( 'perl_version_introduced' ) ) {
240 63         139 my $method = "${class}::perl_version_introduced";
241 9     9   53 no strict qw{ refs };
  9         19  
  9         774  
242             *$method = sub {
243 40     40   8434 my ( $self ) = @_;
244 40   100     253 return $self->DEF->{ $self->unescaped_content() }{intro} || MINIMUM_PERL;
245 63         319 };
246             }
247              
248 63 50       170 unless ( $class->__ns_can( 'perl_version_removed' ) ) {
249 63         136 my $method = "${class}::perl_version_removed";
250 9     9   57 no strict qw{ refs };
  9         18  
  9         1653  
251             *$method = sub {
252 50     50   14676 my ( $self ) = @_;
253 50         213 return $self->DEF->{ $self->unescaped_content() }{remov};
254 63         306 };
255             }
256              
257 63         195 return;
258             }
259              
260             my %matcher;
261              
262             sub __PPIX_TOKENIZER__regexp {
263 1794     1794   3534 my ( $class, $tokenizer ) = @_; # $character unused
264              
265 1794   66     5351 my $mtch = $matcher{$class} ||= $class->__make_group_type_matcher();
266              
267             my $re_list = $mtch->{ $tokenizer->get_start_delimiter() } ||
268 1794   66     4250 $mtch->{''};
269              
270 1794         2965 foreach my $re ( @{ $re_list } ) {
  1794         3557  
271 5990 100       12419 my $accept = $tokenizer->find_regexp( $re )
272             or next;
273 161         1870 $class->__match_setup( $tokenizer );
274 161         639 return $accept;
275             }
276              
277 1633         4103 return;
278             }
279              
280             1;
281              
282             __END__