File Coverage

blib/lib/Regexp/MatchContext.pm
Criterion Covered Total %
statement 55 98 56.1
branch 6 20 30.0
condition 2 3 66.6
subroutine 14 22 63.6
pod n/a
total 77 143 53.8


line stmt bran cond sub pod time code
1             package Regexp::MatchContext;
2              
3 3     3   133855 use version; $VERSION = qv('0.0.2');
  3         18669  
  3         21  
4              
5 3     3   274 use warnings;
  3         7  
  3         112  
6             # use strict;
7 3     3   19 use Carp;
  3         11  
  3         608  
8              
9             my $matchcontents;
10             $matchcontents = qr{ (?:
11             (?> [^()]* )
12             (?>
13             [(] (?{$matchcontents}) [)]
14             )*
15             )*
16             }x;
17              
18             sub import {
19 3     3   6424 use overload;
  3         18834  
  3         24  
20              
21 3     3   36 my $vars = grep {/\A (?: -vars | -all ) \z/x} @_;
  5         22  
22 3   66     20 my $subs = !$vars || grep {/\A (?: -subs | -all ) \z/x} @_;
23              
24             overload::constant
25             qr => sub {
26 2     2   6 my ($raw) = @_;
27 2 50       214 $raw =~ s{ \(\?
28             <
29             ([^\W\d]\w*)
30             >
31             ($matchcontents)
32             \)
33             }
34 0         0 { push @vars, "undef\$$1;"; "($2)(?{eval'\$$1=\$^N'})" }gex
  0         0  
35             and $raw =~ s/$/|(??{@vars'(?!)'})/;
36 2 50       13 $raw =~ s/\(\?p\)/(?{\$Regexp::MatchContext::target_ref=\\\$_})/g
37             or $raw =~ s/\A/(?{\$Regexp::MatchContext::target_ref=undef})/;
38 2         2722 return $raw;
39 3         33 };
40              
41 3         86 my $caller = caller;
42 3     3   13416 no warnings 'once';
  3         7  
  3         926  
43 3         9 for my $name (qw(PREMATCH MATCH POSTMATCH)) {
44 9         20 tie ${$name}, "Regexp::MatchContext::$name";
  9         95  
45 9 100       77 if ($vars) {
46 3         1 *{$caller.'::'.$name} = \${$name};
  3         12  
  3         7  
47             }
48 9 100       83 if ($subs) {
49 6     0   19 *{$caller.'::'.$name} = sub :lvalue { ${$name} };
  6         72  
  0            
  0            
50             }
51             }
52             }
53              
54             sub _cant_assign {
55 0     0     my ($varname) = @_;
56 0           require Carp;
57 0           @CARP_NOT = qw(
58             Regexp::MatchContext::PREMATCH
59             Regexp::MatchContext::MATCH
60             Regexp::MatchContext::POSTMATCH
61             );
62 0           Carp::croak
63             "Can't assign to $varname because the preceding match didn't set it.\n",
64             "(Did you forget to include a (?p) in your regex?)\n",
65             "Died";
66             }
67              
68             package Regexp::MatchContext::PREMATCH;
69 3     3   3281 use Tie::Scalar;
  3         1926  
  3         91  
70 3     3   94 use base 'Tie::StdScalar';
  3         6  
  3         2372  
71              
72             sub FETCH {
73 0 0   0     return undef unless defined ${$Regexp::MatchContext::target_ref};
  0            
74 0           return substr ${$Regexp::MatchContext::target_ref}, 0, $-[0];
  0            
75             }
76              
77             sub STORE {
78 0     0     my ($self, $newval) = @_;
79 0           Regexp::MatchContext::_cant_assign('$PREMATCH')
80 0 0         unless defined ${$Regexp::MatchContext::target_ref};
81 0           my $oldlen = length substr ${$Regexp::MatchContext::target_ref}, 0, $-[0], $newval;
  0            
82 0           my $delta = length($newval) - $oldlen;
83 3     3   3284 *- = [map { $_ + $delta } @-];
  3         2263  
  3         303  
  0            
  0            
84 0           *+ = [map { $_ + $delta } @+];
  0            
85             }
86              
87              
88              
89             package Regexp::MatchContext::MATCH;
90 3     3   22 use Tie::Scalar;
  3         6  
  3         73  
91 3     3   34 use base 'Tie::StdScalar';
  3         7  
  3         2121  
92              
93             sub FETCH {
94 0 0   0     return undef unless defined ${$Regexp::MatchContext::target_ref};
  0            
95 0           return substr ${$Regexp::MatchContext::target_ref}, $-[0], $+[0]-$-[0];
  0            
96             }
97              
98             sub STORE {
99 0     0     my ($self, $newval) = @_;
100 0           Regexp::MatchContext::_cant_assign('$MATCH')
101 0 0         unless defined ${$Regexp::MatchContext::target_ref};
102 0           my $oldlen = length substr ${$Regexp::MatchContext::target_ref}, $-[0], $+[0]-$-[0], $newval;
  0            
103 0           my $delta = length($newval) - $oldlen;
104 0           *- = [$-[0] ];
105 0           *+ = [$+[0] + $delta];
106             }
107              
108              
109              
110             package Regexp::MatchContext::POSTMATCH;
111 3     3   30 use Tie::Scalar;
  3         11  
  3         61  
112 3     3   14 use base 'Tie::StdScalar';
  3         5  
  3         1987  
113              
114             sub FETCH {
115 0 0   0     return undef unless defined ${$Regexp::MatchContext::target_ref};
  0            
116 0           return substr ${$Regexp::MatchContext::target_ref}, $+[0];
  0            
117             }
118              
119             sub STORE {
120 0     0     my ($self, $newval) = @_;
121 0           Regexp::MatchContext::_cant_assign('$POSTMATCH')
122 0 0         unless defined ${$Regexp::MatchContext::target_ref};
123 0           substr(${$Regexp::MatchContext::target_ref}, $+[0]) = $newval;
  0            
124             }
125              
126              
127             1; # Magic true value required at end of module
128             __END__