File Coverage

blib/lib/String/Pattern.pm
Criterion Covered Total %
statement 9 119 7.5
branch 0 30 0.0
condition 0 11 0.0
subroutine 3 13 23.0
pod 5 10 50.0
total 17 183 9.2


line stmt bran cond sub pod time code
1             # Copyright (c) 2000 Ivo Zdravkov. All rights reserved. This program is
2             # free software; you can redistribute it and/or modify it under the same terms
3             # as Perl itself.
4            
5             package Pattern;
6            
7 1     1   1223 use strict;
  1         3  
  1         43  
8             use overload
9 1     1   2345 '""' => "to_string";
  1         2448  
  1         7  
10 1     1   74 use vars qw($VERSION);
  1         7  
  1         1577  
11             $VERSION='0.90';
12            
13             sub new{
14 0     0 0   my $proto = shift;
15 0           my $pattern = shift;
16            
17 0   0       my $class = ref($proto) || $proto;
18            
19 0           my $self = {};
20 0           $self->{PATTERN} = undef;
21 0           $self->{MATCHES} = undef;
22 0           $self->{DATA} = {}; # tag => {REX => '.+', VAR_REF => variable ref}
23 0           $self->{PREPARED} = undef;
24            
25 0           bless($self, $class);
26 0 0         $self->pattern($pattern) if $pattern;
27 0           return $self
28             }
29            
30             sub bind{
31 0     0 1   my $self = shift;
32 0           my $tag = shift; my $var_ref = shift; my $rex=shift;
  0            
  0            
33            
34 0 0 0       if ($rex and $rex=~/\((..)/ and $1 ne '?:') {
      0        
35 0           warn "Bind failed for tag $tag \n".
36             "Brackets are not allowed in regular expression, excep like these : (?:..)";
37             return undef
38 0           }
39            
40 0           $self->{DATA}->{$tag}->{VAR_REF} = $var_ref;
41 0   0       $self->{DATA}->{$tag}->{REX} = $rex || '.*';
42 0           $self->{PREPARED} = 0;
43            
44 0           my $q_tag = $self->quote($tag);
45 0 0         warn "There is no $tag tag in the pattern \n"
46             unless $self->{PATTERN} =~/$q_tag/;
47            
48 0           return 1
49             }
50            
51             sub bind_like{
52 0     0 1   my $self = shift;
53 0           my $other = shift;
54            
55 0 0         unless ( ref($other) eq ref($self) ) {
56 0           warn "Not same object type: ".ref($self)."\n";
57             return undef
58 0           }
59            
60 0           my $success = 1;
61 0           my ($tag, $info);
62 0           while ( ($tag, $info) = each %{$other->{DATA}} ) {
  0            
63 0 0         $self->bind( $tag => $info->{VAR_REF}, $info->{REX})
64             or $success = 0;
65             }
66            
67 0           return $success
68             }
69            
70             sub pattern{
71 0     0 1   my $self = shift;
72 0           my $pattern = shift;
73            
74 0 0         if (defined $pattern) {
75 0           $self->{PATTERN}=$pattern;
76 0           $self->{PREPARED} = 0;
77 0           return 1
78             }else{
79 0           return $self->{PATTERN}
80             }
81             }
82            
83             sub prepare{
84 0     0 0   my $self = shift;
85            
86 0           my $index=0;
87 0           my $pattern=$self->{PATTERN};
88            
89             # clear old indexes
90 0           $self->{DATA}->{$_}->{APPEARANCE}=[] for (keys %{$self->{DATA}});
  0            
91            
92             # create indexes
93 0           my $s_p = join('|', map {'(?:'.$self->quote($_).')'} keys %{$self->{DATA}} );
  0            
  0            
94 0 0         die "There is no any bindings defined" unless $s_p;
95            
96 0           while ($pattern=~/($s_p)/gs){
97 0           push @{$self->{DATA}->{$1}->{APPEARANCE}}, $index++
  0            
98             }
99            
100             # compile rex
101 0           $self->{REX} = $self->to_rex;;
102 0           $self->{PREPARED}=1;
103            
104 0           return 1
105             }
106            
107             sub identify{
108 0     0 1   my $self = shift;
109 0           my $string = shift;
110            
111 0 0         $self->prepare unless $self->{PREPARED};
112            
113 0           my $identical=1;
114 0           my $tag; my $first; my @appearances;
  0            
115 0           my $rex=$self->{REX};
116            
117 0 0         if (@{$self->{MATCHES}} = $string=~/$rex/s) {
  0            
118 0           $identical=1
119             }else{
120 0           return 0
121             }
122            
123             # check for identical repetitions
124 0           for $tag (keys %{$self->{DATA}} ){
  0            
125 0           ($first, @appearances)=@{$self->{DATA}->{$tag}->{APPEARANCE}};
  0            
126 0 0         next unless defined $first;
127            
128 0           for (@appearances) {
129 0 0         $identical=0 if $self->{MATCHES}[$first] ne $self->{MATCHES}[$_] ;
130             }
131 0 0         last unless $identical
132             }
133            
134             # set bounded variables
135 0 0         if ($identical) {
136 0           for $tag (keys %{$self->{DATA}} ){
  0            
137 0 0         if (@{$self->{DATA}->{$tag}->{APPEARANCE}}) {
  0            
138 0           ${$self->{DATA}->{$tag}->{VAR_REF}}=
  0            
139             $self->{MATCHES}[$self->{DATA}->{$tag}->{APPEARANCE}[0]]
140             }else{
141             next
142 0           }
143             }
144             }
145 0           return $identical
146             }
147            
148             sub quote{
149 0     0 0   my $self = shift;
150 0           my $rex = shift;
151            
152 0           $rex=~s/([\$\?@\[\]{}*+\.^|\\])/\\$1/g;
153            
154 0           return $rex
155             }
156            
157             sub dequote{
158 0     0 0   my $self = shift;
159 0           my $string = shift;
160            
161 0           $string =~ s/\\(.)/$1/g;
162 0           return $string;
163             }
164            
165             sub to_rex{
166 0     0 0   my $self = shift;
167            
168 0           my $rex=$self->quote($self->{PATTERN});
169 0           my $s_p = join('|', map {'(?:'.$self->quote($self->quote($_)).')'} keys %{$self->{DATA}} );
  0            
  0            
170            
171 0           $rex=~s/($s_p)/
172 0 0         if (exists $self->{DATA}->{$self->dequote($1)}) {
173 0           "(".$self->{DATA}->{$self->dequote($1)}->{REX}.")"
174             }else{
175 0           warn "problems with rex creation for tag $1"
176             }
177             /ge;
178            
179 0           return '^'.$rex.'$';
180             }
181            
182             sub to_string{
183 0     0 1   my $self = shift;
184            
185 0           my $result = $self->{PATTERN};
186            
187 0           for my $tag (keys %{ $self->{DATA} }) {
  0            
188 0           $result =~ s/$tag/${$self->{DATA}->{$tag}->{VAR_REF}}/g;
  0            
189             }
190            
191 0           return $result
192             }
193             1;
194             __END__