File Coverage

blib/lib/PPIx/Regexp/Token/Reference.pm
Criterion Covered Total %
statement 65 66 98.4
branch 19 22 86.3
condition 3 6 50.0
subroutine 14 15 93.3
pod 6 6 100.0
total 107 115 93.0


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             PPIx::Regexp::Token::Reference - Represent a reference to a capture
4              
5             =head1 SYNOPSIS
6              
7             use PPIx::Regexp::Dumper;
8             PPIx::Regexp::Dumper->new( 'qr{\1}smx' )
9             ->print();
10              
11             =head1 INHERITANCE
12              
13             C<PPIx::Regexp::Token::Reference> is a
14             L<PPIx::Regexp::Token|PPIx::Regexp::Token>.
15              
16             C<PPIx::Regexp::Token::Reference> is the parent of
17             L<PPIx::Regexp::Token::Backreference|PPIx::Regexp::Token::Backreference>,
18             L<PPIx::Regexp::Token::Condition|PPIx::Regexp::Token::Condition> and
19             L<PPIx::Regexp::Token::Recursion|PPIx::Regexp::Token::Recursion>.
20              
21             =head1 DESCRIPTION
22              
23             This abstract class represents a reference to a capture buffer, either
24             numbered or named. It should never be instantiated, but it provides a
25             number of methods to its subclasses.
26              
27             =head1 METHODS
28              
29             This class provides the following public methods. Methods not documented
30             here are private, and unsupported in the sense that the author reserves
31             the right to change or remove them without notice.
32              
33             =cut
34              
35             package PPIx::Regexp::Token::Reference;
36              
37 9     9   63 use strict;
  9         13  
  9         258  
38 9     9   33 use warnings;
  9         13  
  9         386  
39              
40 9     9   32 use base qw{ PPIx::Regexp::Token };
  9         13  
  9         732  
41              
42 9     9   40 use Carp qw{ confess };
  9         13  
  9         508  
43 9     9   45 use List::Util qw{ first };
  9         12  
  9         541  
44 9     9   38 use PPIx::Regexp::Constant qw{ @CARP_NOT };
  9         11  
  9         6529  
45              
46             our $VERSION = '0.091';
47              
48             sub __new {
49 113     113   627 my ( $class, $content, %arg ) = @_;
50              
51 113 100       453 if ( defined $arg{capture} ) {
    100          
52             } elsif ( defined $arg{tokenizer} ) {
53 101     116   544 $arg{capture} = first { defined $_ } $arg{tokenizer}->capture();
  116         262  
54             }
55              
56 113 100       474 unless ( defined $arg{capture} ) {
57 24         67 foreach ( $class->__PPIX_TOKEN__recognize() ) {
58 49         54 my ( $re, $a ) = @{ $_ };
  49         71  
59 49 100       324 $content =~ $re or next;
60 24         29 @arg{ keys %{ $a } } = @{ $a }{ keys %{ $a } };
  24         43  
  24         37  
  24         43  
61 24         83 foreach my $inx ( 1 .. $#- ) {
62 34 100       89 defined $-[$inx] or next;
63 21         90 $arg{capture} = substr $content, $-[$inx], $+[$inx] - $-[$inx];
64 21         35 last;
65             }
66 24         37 last;
67             }
68             }
69              
70             defined $arg{capture}
71 113 50       279 or confess q{Programming error - reference '},
72             $content, q{' of unknown form};
73              
74 113 50       432 my $self = $class->SUPER::__new( $content, %arg )
75             or return;
76              
77 113         246 $self->{is_named} = $arg{is_named};
78              
79 113         232 my $capture = delete $arg{capture};
80              
81 113 100       361 if ( $self->{is_named} ) {
    100          
82 35         76 $self->{absolute} = undef;
83 35         56 $self->{is_relative} = undef;
84 35         83 $self->{name} = $capture;
85             } elsif ( $capture !~ m/ \A [-+] /smx ) {
86 59         204 $self->{absolute} = $self->{number} = $capture;
87 59         140 $self->{is_relative} = undef;
88             } else {
89 19         47 $self->{number} = $capture;
90 19         37 $self->{is_relative} = 1;
91             }
92              
93 113         308 return $self;
94             }
95              
96             =head2 absolute
97              
98             print "The absolute reference is ", $ref->absolute(), "\n";
99              
100             This method returns the absolute number of the capture buffer referred
101             to. This is the same as number() for unsigned numeric references. If the
102             reference is to a named buffer, C<undef> is returned.
103              
104             =cut
105              
106             sub absolute {
107 69     69 1 156 my ( $self ) = @_;
108 69         204 return $self->{absolute};
109             }
110              
111             =head2 is_named
112              
113             $ref->is_named and print "named reference\n";
114              
115             This method returns true if the reference is named rather than numbered.
116              
117             =cut
118              
119             sub is_named {
120 87     87 1 153 my ( $self ) = @_;
121 87         244 return $self->{is_named};
122             }
123              
124             =head2 is_relative
125              
126             $ref->is_relative()
127             and print "relative numbered reference\n";
128              
129             This method returns true if the reference is numbered and it is a
130             relative number (i.e. if it is signed).
131              
132             =cut
133              
134             sub is_relative {
135 5     5 1 12 my ( $self ) = @_;
136 5         26 return $self->{is_relative};
137             }
138              
139             =head2 is_matcher
140              
141             This method returns a true value because, although we do not actually
142             perform an analysis on the referred-to entity, we presume it matches
143             something.
144              
145             =cut
146              
147 0     0 1 0 sub is_matcher { return 1; }
148              
149             =head2 name
150              
151             print "The name is ", $ref->name(), "\n";
152              
153             This method returns the name of the capture buffer referred to. In the
154             case of a reference to a numbered capture (i.e. C<is_named> returns
155             false), this method returns C<undef>.
156              
157             =cut
158              
159             sub name {
160 39     39 1 77 my ( $self ) = @_;
161 39         127 return $self->{name};
162             }
163              
164             =head2 number
165              
166             print "The number is ", $ref->number(), "\n";
167              
168             This method returns the number of the capture buffer referred to. In the
169             case of a reference to a named capture (i.e. C<is_named> returns true),
170             this method returns C<undef>.
171              
172             =cut
173              
174             sub number {
175 22     22 1 55 my ( $self ) = @_;
176 22         59 return $self->{number};
177             }
178              
179             # Called by the lexer to record the capture number.
180             sub __PPIX_LEXER__record_capture_number {
181 63     63   120 my ( $self, $number ) = @_;
182 63 50 66     293 if ( ! exists $self->{absolute} && exists $self->{number}
      33        
183             && $self->{number} =~ m/ \A [-+] /smx ) {
184              
185 10         29 my $delta = $self->{number};
186 10 100       37 $delta > 0 and --$delta; # no -0 or +0.
187 10         25 $self->{absolute} = $number + $delta;
188              
189             }
190 63         107 return $number;
191             }
192              
193             1;
194              
195             __END__
196              
197             =head1 SUPPORT
198              
199             Support is by the author. Please file bug reports at
200             L<https://rt.cpan.org/Public/Dist/Display.html?Name=PPIx-Regexp>,
201             L<https://github.com/trwyant/perl-PPIx-Regexp/issues>, or in
202             electronic mail to the author.
203              
204             =head1 AUTHOR
205              
206             Thomas R. Wyant, III F<wyant at cpan dot org>
207              
208             =head1 COPYRIGHT AND LICENSE
209              
210             Copyright (C) 2009-2023, 2025 by Thomas R. Wyant, III
211              
212             This program is free software; you can redistribute it and/or modify it
213             under the same terms as Perl 5.10.0. For more details, see the full text
214             of the licenses in the directory LICENSES.
215              
216             This program is distributed in the hope that it will be useful, but
217             without any warranty; without even the implied warranty of
218             merchantability or fitness for a particular purpose.
219              
220             =cut
221              
222             # ex: set textwidth=72 :