File Coverage

blib/lib/Lingua/Stem/Ru.pm
Criterion Covered Total %
statement 56 76 73.6
branch 20 38 52.6
condition 2 6 33.3
subroutine 8 10 80.0
pod 4 4 100.0
total 90 134 67.1


line stmt bran cond sub pod time code
1             package Lingua::Stem::Ru;
2              
3 1     1   834 use strict;
  1         2  
  1         46  
4              
5              
6 1     1   6 use strict;
  1         3  
  1         31  
7 1     1   6 use Exporter;
  1         6  
  1         50  
8 1     1   8 use Carp;
  1         2  
  1         144  
9 1     1   7 use vars qw (@ISA @EXPORT_OK @EXPORT %EXPORT_TAGS $VERSION);
  1         1  
  1         176  
10             BEGIN {
11 1     1   24 @ISA = qw (Exporter);
12 1         3 @EXPORT = ();
13 1         3 @EXPORT_OK = qw (stem stem_word clear_stem_cache stem_caching);
14 1         2433 %EXPORT_TAGS = ();
15             }
16             $VERSION = "0.01";
17              
18             my $Stem_Caching = 0;
19             my $Stem_Cache = {};
20              
21             my $VOWEL = qr/аеиоуыэюя/;
22             my $PERFECTIVEGROUND = qr/((ив|ивши|ившись|ыв|ывши|ывшись)|((?<=[ая])(в|вши|вшись)))$/;
23             my $REFLEXIVE = qr/(с[яь])$/;
24             my $ADJECTIVE = qr/(ее|ие|ые|ое|ими|ыми|ей|ий|ый|ой|ем|им|ым|ом|его|ого|ему|ому|их|ых|ую|юю|ая|яя|ою|ею)$/;
25             my $PARTICIPLE = qr/((ивш|ывш|ующ)|((?<=[ая])(ем|нн|вш|ющ|щ)))$/;
26             my $VERB = qr/((ила|ыла|ена|ейте|уйте|ите|или|ыли|ей|уй|ил|ыл|им|ым|ен|ило|ыло|ено|ят|ует|уют|ит|ыт|ены|ить|ыть|ишь|ую|ю)|((?<=[ая])(ла|на|ете|йте|ли|й|л|ем|н|ло|но|ет|ют|ны|ть|ешь|нно)))$/;
27             my $NOUN = qr/(а|ев|ов|ие|ье|е|иями|ями|ами|еи|ии|и|ией|ей|ой|ий|й|иям|ям|ием|ем|ам|ом|о|у|ах|иях|ях|ы|ь|ию|ью|ю|ия|ья|я)$/;
28             my $RVRE = qr/^(.*?[$VOWEL])(.*)$/;
29             my $DERIVATIONAL = qr/[^$VOWEL][$VOWEL]+[^$VOWEL]+[$VOWEL].*(?<=о)сть?$/;
30              
31             sub stem {
32 3 50   3 1 68 return [] if ($#_ == -1);
33 3         7 my $parm_ref;
34 3 50       9 if (ref $_[0]) {
35 3         6 $parm_ref = shift;
36             } else {
37 0         0 $parm_ref = { @_ };
38             }
39              
40 3         7 my $words = [];
41 3         4 my $locale = 'ru';
42 3         5 my $exceptions = {};
43 3         10 foreach (keys %$parm_ref) {
44 3         6 my $key = lc ($_);
45 3 50       7 if ($key eq '-words') {
    0          
    0          
46 3         4 @$words = @{$parm_ref->{$key}};
  3         13  
47             } elsif ($key eq '-exceptions') {
48 0         0 $exceptions = $parm_ref->{$key};
49             } elsif ($key eq '-locale') {
50 0         0 $locale = $parm_ref->{$key};
51             } else {
52 0         0 croak (__PACKAGE__ . "::stem() - Unknown parameter '$key' with value '$parm_ref->{$key}'\n");
53             }
54             }
55              
56 3         6 local( $_ );
57 3         6 foreach (@$words) {
58             # Flatten case
59 9         16 $_ = lc $_;
60              
61             # Check against exceptions list
62 9 50       21 if (exists $exceptions->{$_}) {
63 0         0 $_ = $exceptions->{$_};
64 0         0 next;
65             }
66              
67             # Check against cache of stemmed words
68 9         11 my $original_word = $_;
69 9 50 33     43 if ($Stem_Caching && exists $Stem_Cache->{$original_word}) {
70 0         0 $_ = $Stem_Cache->{$original_word};
71 0         0 next;
72             }
73              
74 9         16 $_ = stem_word($_);
75              
76 9 50       25 $Stem_Cache->{$original_word} = $_ if $Stem_Caching;
77             }
78 3 50       11 $Stem_Cache = {} if ($Stem_Caching < 2);
79              
80 3         11 return $words;
81             }
82              
83             sub stem_word {
84 49682     49682 1 664490 my $word = lc shift;
85              
86             # Check against cache of stemmed words
87 49682 50 33     114323 if ($Stem_Caching && exists $Stem_Cache->{$word}) {
88 0         0 return $Stem_Cache->{$word};
89             }
90              
91 49682         248138 my ($start, $RV) = $word =~ /$RVRE/;
92 49682 100       105972 return $word unless $RV;
93              
94             # Step 1
95 49465 100       268013 unless ($RV =~ s/$PERFECTIVEGROUND//) {
96 49033         131625 $RV =~ s/$REFLEXIVE//;
97              
98 49033 100       203184 if ($RV =~ s/$ADJECTIVE//) {
99 15241         58569 $RV =~ s/$PARTICIPLE//;
100             } else {
101 33792 100       253305 $RV =~ s/$NOUN// unless $RV =~ s/$VERB//;
102             }
103             }
104              
105             # Step 2
106 49465         73732 $RV =~ s/и$//;
107              
108             # Step 3
109 49465 100       158620 $RV =~ s/ость?$// if $RV =~ /$DERIVATIONAL/;
110              
111             # Step 4
112 49465 100       95993 unless ($RV =~ s/ь$//) {
113 49034         56881 $RV =~ s/ейше?//;
114 49034         63801 $RV =~ s/нн$/н/;
115             }
116              
117 49465         147493 return $start.$RV;
118             }
119              
120             sub stem_caching {
121 0     0 1   my $parm_ref;
122 0 0         if (ref $_[0]) {
123 0           $parm_ref = shift;
124             } else {
125 0           $parm_ref = { @_ };
126             }
127 0           my $caching_level = $parm_ref->{-level};
128 0 0         if (defined $caching_level) {
129 0 0         if ($caching_level !~ m/^[012]$/) {
130 0           croak(__PACKAGE__ . "::stem_caching() - Legal values are '0','1' or '2'. '$caching_level' is not a legal value");
131             }
132 0           $Stem_Caching = $caching_level;
133             }
134 0           return $Stem_Caching;
135             }
136              
137             sub clear_stem_cache {
138 0     0 1   $Stem_Cache = {};
139             }
140            
141              
142             1;
143             __END__