line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Regexp::Common::balanced; { |
2
|
|
|
|
|
|
|
|
3
|
72
|
|
|
72
|
|
647
|
use 5.10.0; |
|
72
|
|
|
|
|
161
|
|
4
|
|
|
|
|
|
|
|
5
|
72
|
|
|
72
|
|
304
|
use strict; |
|
72
|
|
|
|
|
95
|
|
|
72
|
|
|
|
|
1271
|
|
6
|
72
|
|
|
72
|
|
220
|
use warnings; |
|
72
|
|
|
|
|
91
|
|
|
72
|
|
|
|
|
1744
|
|
7
|
72
|
|
|
72
|
|
330
|
no warnings 'syntax'; |
|
72
|
|
|
|
|
171
|
|
|
72
|
|
|
|
|
2368
|
|
8
|
|
|
|
|
|
|
|
9
|
72
|
|
|
72
|
|
254
|
use Regexp::Common qw /pattern clean no_defaults/; |
|
72
|
|
|
|
|
113
|
|
|
72
|
|
|
|
|
476
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
our $VERSION = '2017040401'; |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
my %closer = ( '{'=>'}', '('=>')', '['=>']', '<'=>'>' ); |
14
|
|
|
|
|
|
|
my %cache; |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
sub nested { |
17
|
17
|
|
|
17
|
0
|
25
|
my ($start, $finish) = @_; |
18
|
|
|
|
|
|
|
|
19
|
17
|
100
|
|
|
|
50
|
return $cache {$start} {$finish} if exists $cache {$start} {$finish}; |
20
|
|
|
|
|
|
|
|
21
|
12
|
|
|
|
|
68
|
my @starts = map {s/\\(.)/$1/g; $_} grep {length} |
|
15
|
|
|
|
|
23
|
|
|
15
|
|
|
|
|
28
|
|
|
15
|
|
|
|
|
23
|
|
22
|
|
|
|
|
|
|
$start =~ /([^|\\]+|\\.)+/gs; |
23
|
12
|
|
|
|
|
39
|
my @finishes = map {s/\\(.)/$1/g; $_} grep {length} |
|
14
|
|
|
|
|
15
|
|
|
14
|
|
|
|
|
22
|
|
|
14
|
|
|
|
|
16
|
|
24
|
|
|
|
|
|
|
$finish =~ /([^|\\]+|\\.)+/gs; |
25
|
|
|
|
|
|
|
|
26
|
12
|
|
|
|
|
25
|
push @finishes => ($finishes [-1]) x (@starts - @finishes); |
27
|
|
|
|
|
|
|
|
28
|
12
|
|
|
|
|
13
|
my @re; |
29
|
12
|
|
|
|
|
14
|
local $" = "|"; |
30
|
12
|
|
|
|
|
21
|
foreach my $begin (@starts) { |
31
|
15
|
|
|
|
|
11
|
my $end = shift @finishes; |
32
|
|
|
|
|
|
|
|
33
|
15
|
|
|
|
|
20
|
my $qb = quotemeta $begin; |
34
|
15
|
|
|
|
|
15
|
my $qe = quotemeta $end; |
35
|
15
|
|
|
|
|
19
|
my $fb = quotemeta substr $begin => 0, 1; |
36
|
15
|
|
|
|
|
15
|
my $fe = quotemeta substr $end => 0, 1; |
37
|
|
|
|
|
|
|
|
38
|
15
|
|
|
|
|
18
|
my $tb = quotemeta substr $begin => 1; |
39
|
15
|
|
|
|
|
16
|
my $te = quotemeta substr $end => 1; |
40
|
|
|
|
|
|
|
|
41
|
15
|
|
|
|
|
11
|
my $add; |
42
|
15
|
100
|
|
|
|
27
|
if ($fb eq $fe) { |
43
|
1
|
|
|
|
|
6
|
push @re => |
44
|
|
|
|
|
|
|
qq /(?:$qb(?:(?>[^$fb]+)|$fb(?!$tb)(?!$te)|(?-1))*$qe)/; |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
else { |
47
|
14
|
|
|
|
|
28
|
my @clauses = "(?>[^$fb$fe]+)"; |
48
|
14
|
100
|
|
|
|
28
|
push @clauses => "$fb(?!$tb)" if length $tb; |
49
|
14
|
100
|
|
|
|
25
|
push @clauses => "$fe(?!$te)" if length $te; |
50
|
14
|
|
|
|
|
13
|
push @clauses => "(?-1)"; |
51
|
14
|
|
|
|
|
50
|
push @re => qq /(?:$qb(?:@clauses)*$qe)/; |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
} |
54
|
|
|
|
|
|
|
|
55
|
12
|
|
|
|
|
375
|
$cache {$start} {$finish} = qr /(@re)/; |
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
pattern name => [qw /balanced -parens=() -begin= -end=/], |
60
|
|
|
|
|
|
|
create => sub { |
61
|
|
|
|
|
|
|
my $flag = $_[1]; |
62
|
|
|
|
|
|
|
unless (defined $flag -> {-begin} && length $flag -> {-begin} && |
63
|
|
|
|
|
|
|
defined $flag -> {-end} && length $flag -> {-end}) { |
64
|
|
|
|
|
|
|
my @open = grep {index ($flag->{-parens}, $_) >= 0} |
65
|
|
|
|
|
|
|
('[','(','{','<'); |
66
|
|
|
|
|
|
|
my @close = map {$closer {$_}} @open; |
67
|
|
|
|
|
|
|
$flag -> {-begin} = join "|" => @open; |
68
|
|
|
|
|
|
|
$flag -> {-end} = join "|" => @close; |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
return nested @$flag {qw /-begin -end/}; |
71
|
|
|
|
|
|
|
}, |
72
|
|
|
|
|
|
|
; |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
1; |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
__END__ |