File Coverage

blib/lib/Lingua/IT/Conjugate.pm
Criterion Covered Total %
statement 124 265 46.7
branch 75 184 40.7
condition 20 102 19.6
subroutine 10 14 71.4
pod 0 11 0.0
total 229 576 39.7


line stmt bran cond sub pod time code
1             package Lingua::IT::Conjugate;
2            
3             # use strict;
4             # use warnings;
5            
6             @ISA = qw( Exporter );
7            
8             @EXPORT_OK = qw(
9             coniuga
10             coniugazione
11             declina
12             );
13            
14 1     1   1594 use FindBin;
  1         1007  
  1         48  
15             #use Tie::RegexpHash;
16            
17 1         742 use vars qw(
18             $VERSION
19             %Desinenza
20             %Regolarizza
21             %Irregolarita
22             %Prefissi
23             %Simile
24             @Ausiliari_essere
25             @Pronome
26             @Pronome_riflessivo
27             @Tempi
28             $Errore
29             %Opzioni
30 1     1   5 );
  1         1  
31            
32             $VERSION = "0.50";
33            
34             @Pronome = (
35             'nessuno',
36             'io ',
37             'tu ',
38             'lui ',
39             'noi ',
40             'voi ',
41             'essi',
42             );
43             @Pronome_riflessivo = (
44             'nessuno',
45             'mi',
46             'ti',
47             'si',
48             'ci',
49             'vi',
50             'si',
51             );
52            
53             @Tempi = qw(
54             presente imperfetto
55             passato_prossimo trapassato_prossimo
56             passato_remoto trapassato_remoto
57             futuro_semplice futuro_anteriore
58             congiuntivo_presente congiuntivo_imperfetto
59             congiuntivo_passato congiuntivo_trapassato
60             condizionale_presente condizionale_passato
61             );
62            
63             #tie %Opzioni, 'Tie::RegexpHash';
64             %Opzioni = (
65             # qr/^(pronomi|pronouns)$/ => 1,
66             # qr/^(coniuga_sconosciuti|conjugate_unknown)$/ => 1,
67             # prefer_csv => 0,
68             # qr/^(gender|sesso)$/ => 'M'
69             pronomi => 1,
70             coniuga_sconosciuti => 1,
71             prefer_csv => 0,
72             sesso => 'M',
73             );
74            
75             inizializza();
76            
77             sub inizializza {
78 1     1 0 2 my($in_pod, $sezione, $verbo, $declinazione, $tempo, $tempo_ausiliare, $desinenze);
79 0         0 my($forma_regolare, $tempi, $prefissi, $persona, $forma, $prefisso);
80 1         1 $in_pod = 1;
81 1         2 $sezione = "";
82 1         5 while() {
83 427 100       736 if($in_pod) {
84 54 100       77 $in_pod = 0 if /^=cut/;
85 54 100       118 next if $in_pod;
86             }
87 374 100 100     1621 next if /^\s*#/ or /^\s*$/;
88 328         311 chomp;
89 328         2409 s/^\s+|\s+$//;
90 328 100       548 if(/^\[(.*)\]/) {
91 6         35 $sezione = ucfirst(lc($1));
92             } else {
93 322 100       1016 if($sezione eq "Desinenze") {
    100          
    100          
    100          
    100          
    100          
94 24         63 ($declinazione, $tempo, $desinenze) = split(/\s+/, $_, 3);
95 24 100       59 $Desinenza{$declinazione} = {} unless exists $Desinenza{$declinazione};
96 24 50       71 $Desinenza{$declinazione}{$tempo} = [] unless exists $Desinenza{$declinazione}{$tempo};
97 24         270 $Desinenza{$declinazione}{$tempo} = [ split(/\s*,\s*/, $desinenze) ];
98            
99             } elsif($sezione eq "Composti") {
100 7         17 ($tempo, $tempo_ausiliare) = split(/\s+/, $_, 2);
101 7         10 foreach $declinazione ( qw( are ere ire ) ) {
102 21 50       36 $Desinenza{$declinazione} = {} unless exists $Desinenza{$declinazione};
103 21         63 $Desinenza{$declinazione}{$tempo} = "ausiliare($tempo_ausiliare)+participio";
104             }
105            
106             } elsif($sezione eq "Regolarizza") {
107 10         29 ($verbo, $forma_regolare, $tempi) = split(/\s+/, $_, 3);
108 10         56 $Regolarizza{$verbo} = "$forma_regolare;$tempi";
109            
110             } elsif($sezione eq "Ausiliari_essere") {
111 14         47 push(@Ausiliari_essere, $_);
112            
113             } elsif($sezione eq "Prefissi") {
114 21         49 ($verbo, $prefissi) = split(/\s+/, $_, 2);
115 21 50       91 $Prefissi{$verbo} = [] unless exists $Prefissi{$verbo};
116 21         123 $Prefissi{$verbo} = [ split(/\s+/, $prefissi) ];
117            
118             } elsif($sezione eq "Irregolarita") {
119 245         706 ($verbo, $tempo, $persona, $forma) = split(/\s+/, $_, 4);
120 245 100       564 $Irregolarita{$verbo} = {} unless exists $Irregolarita{$verbo};
121 245 100       575 $Irregolarita{$verbo}{$tempo} = {} unless exists $Irregolarita{$verbo}{$tempo};
122 245         977 $Irregolarita{$verbo}{$tempo}{$persona} = $forma;
123             }
124             }
125             }
126 1         6 foreach $verbo (keys %Prefissi) {
127 21         23 foreach $prefisso (@{$Prefissi{$verbo}}) {
  21         30  
128 101         238 $Simile{ $prefisso.$verbo } = $verbo;
129             }
130             }
131             }
132            
133             sub opzioni_default {
134 1     1   5 no warnings;
  1         4  
  1         3060  
135 14     14 0 18 my($opzioni) = @_;
136 14         18 my %default;
137             # tie %default, 'Tie::RegexpHash';
138 14         34 foreach my $opzione (keys %Opzioni) {
139 56         107 $default{$opzione} = $Opzioni{$opzione};
140             }
141            
142 14         79 my $chiamante = (caller(1))[3];
143 14         45 $chiamante =~ s/Lingua::IT::Conjugate:://;
144            
145 14 100       43 if($chiamante eq 'coniuga') {
    50          
146 3         6 $default{ pronomi } = 0;
147             } elsif($chiamante eq 'coniugazione') {
148 0         0 $default{ pronomi } = 0;
149             }
150 14 100 66     53 if(defined $opzioni and ref($opzioni) eq "HASH") {
151 9         26 foreach (keys %$opzioni) {
152 27         47 $default{$_} = $opzioni->{$_};
153             }
154             }
155 14         29 return \%default;
156             }
157            
158             sub coniuga {
159 3     3 0 132 my($verbo, $tempo, $persona, $opzioni) = @_;
160 3         4 my @risultato;
161             my %risultato;
162            
163 3         10 $opzioni = opzioni_default( $opzioni );
164            
165 3 50       9 if( $opzioni->{coniuga_sconosciuti} == 0) {
166 0 0       0 if(not verbo_esistente( $verbo )) {
167 0         0 $Errore = "unknown verb ('$verbo')";
168 0         0 return "[unknown verb ('$verbo')]";
169             }
170             }
171            
172 3 50 33     41 if(defined $tempo and defined $persona) {
    0 0        
    0 0        
173 3         8 return coniuga_forma($verbo, $tempo, $persona);
174             } elsif(not defined $tempo and defined $persona) {
175 0         0 foreach $tempo (@Tempi) {
176 0         0 $risultato{$tempo} = coniuga_forma($verbo, $tempo, $persona);
177             }
178 0 0       0 return wantarray ? %risultato : \%risultato;
179             } elsif(defined $tempo and not defined $persona) {
180 0         0 foreach $persona (1..6) {
181 0         0 push(@risultato, coniuga_forma($verbo, $tempo, $persona));
182             }
183 0 0       0 return wantarray ? @risultato : join(", ", @risultato);
184             } else {
185 0         0 foreach $tempo (@Tempi) {
186 0         0 foreach $persona (1..6) {
187 0         0 push(@risultato, coniuga_forma($verbo, $tempo, $persona));
188             }
189 0         0 $risultato{$tempo} = [ @risultato ];
190             }
191 0 0       0 return wantarray ? %risultato : \%risultato;
192             }
193             }
194            
195             sub applica_irregolarita {
196 2     2 0 4 my($risultato, $verbo, $tempo) = @_;
197 2 100       8 if(exists $Irregolarita{$verbo}{$tempo}{'*'}) {
198 1 50       4 if($Irregolarita{$verbo}{$tempo}{'*'} =~ /^~/) {
199 0         0 eval "\$risultato =".$Irregolarita{$verbo}{$tempo}{'*'}.";"
200             } else {
201 1         3 $risultato = $Irregolarita{$verbo}{$tempo}{'*'};
202             }
203             }
204 2         5 return $risultato;
205             }
206            
207             sub coniuga_forma {
208 10     10 0 15 my($verbo, $tempo, $persona, $opzioni) = @_;
209            
210 10         14 my($tema, $coniugazione, $base, $prefisso, $prefisso_tema, $desinenza, $risultato);
211 0         0 my($ausiliare, $verbo_ausiliare, $tempo_ausiliare, $riflessivo);
212 0         0 my @aggiustamenti;
213 0         0 my %opzioni;
214            
215 10         16 $opzioni = opzioni_default( $opzioni );
216            
217 10 50       26 if($verbo =~ s/si$/e/) { $riflessivo = 1; }
  0         0  
218 10 50       24 if($verbo =~ /[ou]re$/) {
219 0         0 my $prova;
220 0         0 ($prova = $verbo) =~ s/re$/rre/;
221 0         0 $prova =~ s/urre$/ucere/i;
222 0         0 $prova =~ s/orre$/onere/i;
223 0 0 0     0 if(exists $Simile{$prova}
      0        
224             or exists $Regolarizza{$prova}
225             or exists $Prefissi{$prova}) {
226 0         0 $verbo = $prova;
227             }
228             }
229            
230 10         18 $verbo =~ s/urre$/ucere/i;
231 10         17 $verbo =~ s/orre$/onere/i;
232            
233 10 50       23 if(exists $Simile{$verbo}) {
234 0         0 ($prefisso_tema = $verbo) =~ s/$Simile{$verbo}$//;
235 0         0 $verbo = $Simile{$verbo};
236             }
237            
238 10 50       20 if(exists $Regolarizza{$verbo}) {
239 0         0 my($forma_regolare, $tempi) = split(/;/, $Regolarizza{$verbo});
240 0 0 0     0 if($tempi eq "*" or $tempi =~ /$tempo/) {
241 0         0 $verbo = $forma_regolare;
242             }
243             }
244            
245 10 100       36 if(exists $Irregolarita{$verbo}{$tempo}{$persona}) {
246 8         18 $risultato = $Irregolarita{$verbo}{$tempo}{$persona};
247 8 50       18 $risultato = $prefisso_tema . $risultato if defined $prefisso_tema;
248 8 50       14 if($riflessivo) {
249 0         0 $risultato = $Pronome_riflessivo[$persona]." ".$risultato;
250             }
251 8         37 return $risultato;
252             }
253            
254 2         6 foreach (keys %Desinenza) {
255 2 50       36 if($verbo =~ /^(.*)$_$/i) {
256 2         6 $tema = $1;
257 2         3 $coniugazione = $_;
258 2         4 last;
259             }
260             }
261 2 50       538 if(defined $coniugazione) {
262 2 100       8 if(ref( $Desinenza{$coniugazione}{$tempo} )) {
263            
264 1         3 $desinenza = $Desinenza{$coniugazione}{$tempo}[$persona-1];
265 1         3 ($tema, $desinenza) = aggiusta(
266             $coniugazione,
267             $tempo,
268             $persona,
269             $tema,
270             $desinenza,
271             );
272            
273 1         2 $risultato = $tema . $desinenza;
274 1         2 $risultato = applica_irregolarita( $risultato, $verbo, $tempo );
275 1 50       3 $risultato = $prefisso_tema . $risultato if defined $prefisso_tema;
276 1 50       3 if($riflessivo) {
277 0         0 $risultato = $Pronome_riflessivo[$persona]." ".$risultato;
278             }
279             } else {
280 1         6 ($prefisso, $base) = split(/\+/, $Desinenza{$coniugazione}{$tempo});
281            
282 1 50       5 if($prefisso =~ /^ausiliare/) {
283 1         5 ($tempo_ausiliare = $prefisso) =~ s/^.*\((.*)\)$/$1/;
284 1 50 33     28 if(grep( /^$verbo$/, @Ausiliari_essere)
285             or $riflessivo) {
286 1         2 $verbo_ausiliare = "essere";
287             } else {
288 0         0 $verbo_ausiliare = "avere";
289             }
290 1         9 $ausiliare = coniuga_forma($verbo_ausiliare, $tempo_ausiliare, $persona);
291 1         4 $desinenza = $Desinenza{$coniugazione}{$base}[$persona-1];
292 1         4 ($tema, $desinenza) = aggiusta(
293             $coniugazione,
294             $base,
295             $persona,
296             $tema,
297             $desinenza,
298             );
299            
300 1         3 $risultato = $tema . $desinenza;
301 1         3 $risultato = applica_irregolarita( $risultato, $verbo, $base );
302 1 50 33     6 if($verbo_ausiliare eq "essere" and $persona > 3) {
303 0         0 $risultato =~ s/o$/i/;
304             }
305 1 50       3 $risultato = $prefisso_tema . $risultato if defined $prefisso_tema;
306 1         2 $risultato = $ausiliare . " " . $risultato;
307 1 50       3 if($riflessivo) {
308 0         0 $risultato = $Pronome_riflessivo[$persona]." ".$risultato;
309             }
310             } else {
311            
312 0         0 ($base, @aggiustamenti) = split(/;/, $base);
313            
314 0         0 my %aggiustamenti;
315 0         0 map { /(\w+)=(\w+)/; $aggiustamenti{$1} = $2; } @aggiustamenti;
  0         0  
  0         0  
316            
317 0         0 $desinenza = $Desinenza{$coniugazione}{$base}[$persona-1];
318            
319 0 0       0 if( exists $aggiustamenti{$persona} ) {
320 0         0 $desinenza = $aggiustamenti{$persona};
321             }
322            
323 0         0 ($tema, $desinenza) = aggiusta(
324             $coniugazione,
325             $tempo,
326             $persona,
327             $tema,
328             $prefisso . $desinenza,
329             );
330            
331 0         0 $risultato = $tema . $desinenza;
332 0         0 $risultato = applica_irregolarita( $risultato, $verbo, $tempo );
333 0 0       0 $risultato = $prefisso_tema . $risultato if defined $prefisso_tema;
334 0 0       0 if($riflessivo) {
335 0         0 $risultato = $Pronome_riflessivo[$persona]." ".$risultato;
336             }
337             }
338             }
339 2         43 return $risultato;
340             } else {
341 0         0 return "NON LO ".uc(coniuga_forma("sapere", "presente", $persona))." FARE!";
342             }
343             }
344            
345             sub aggiusta {
346 2     2 0 6 my($coniugazione, $tempo, $persona, $tema, $desinenza) = @_;
347 2         3 my($prima, $seconda);
348            
349 2 50       8 if( $coniugazione eq "are" ) {
    50          
350 0 0 0     0 if( $tema =~ /[gc]$/ and $desinenza =~ /^[ie]/ ) {
    0 0        
    0 0        
351 0         0 $tema .= "h";
352             } elsif( $tema =~ /[gc]i$/ and $desinenza =~ /^[ie]/ ) {
353 0         0 chop $tema;
354             } elsif( $tema =~ /i$/ and $desinenza =~ /^i/ ) {
355 0         0 chop $tema;
356             }
357             } elsif( $coniugazione eq "ere" ) {
358            
359 2 50 33     45 if($tema =~ /g(n|li)$/) {
    50 33        
    50 0        
    50 33        
    50 33        
    50 0        
    100 33        
      0        
      33        
      0        
      0        
      33        
      66        
360 0 0 0     0 if($tempo eq "participio") {
    0 0        
    0          
    0          
361 0 0       0 $tema =~ s/g(l|n)i?$/($1 eq "n") ? "n" : "l"/e;
  0         0  
362 0         0 $desinenza = "to";
363             } elsif($tempo eq "passato_remoto"
364             and ($persona == 1 or $persona == 3 or $persona == 6) ) {
365 0         0 $tema =~ s/g(l|n)i?$/$1s/;
366 0         0 $desinenza =~ s/ei/i/;
367 0         0 $desinenza =~ s/Š/e/;
368 0         0 $desinenza =~ s/erono/ero/;
369             } elsif($tempo eq "presente") {
370 0 0 0     0 if($persona == 1 or $persona == 6) {
371 0         0 $tema =~ s/g(n|l)i?$/$1g/;
372             } else {
373 0 0       0 $desinenza =~ s/^i// if $tema =~ /i$/;
374             }
375             } elsif($tempo eq "congiuntivo_presente") {
376 0 0       0 if($desinenza =~ /^a/) {
377 0         0 $tema =~ s/g(n|l)i?$/$1g/;
378             } else {
379 0 0       0 $desinenza =~ s/^i// if $tema =~ /i$/;
380             }
381             }
382            
383             } elsif( $tema =~ /n$/ and $desinenza =~ /^[oa]/ ) {
384 0         0 $tema .= "g";
385            
386             } elsif( $tema =~ /[gnr]g$/ and $tempo eq "passato_remoto"
387             and ($persona == 1 or $persona == 3 or $persona == 6) ) {
388 0 0       0 $tema =~ s/(.)g$/( ($1 eq "g") ? "s" : $1 ) . "s"/e;
  0         0  
389 0         0 $desinenza =~ s/ei/i/;
390 0         0 $desinenza =~ s/Š/e/;
391 0         0 $desinenza =~ s/erono/ero/;
392            
393             } elsif( $tema =~ /[nr]d$/ and $tempo eq "passato_remoto"
394             and ($persona == 1 or $persona == 3 or $persona == 6) ) {
395 0 0       0 $tema =~ s/(.)d$/( ($1 eq "n") ? "" : $1 ) . "s"/e;
  0         0  
396 0         0 $desinenza =~ s/ei/i/;
397 0         0 $desinenza =~ s/Š/e/;
398 0         0 $desinenza =~ s/erono/ero/;
399            
400             } elsif( $tema =~ /isc$/
401             and ($tempo eq "presente" or $tempo eq "congiuntivo_presente")
402             and ($persona == 4 or $persona == 5) ) {
403 0         0 $tema =~ s/isc$//;
404 0         0 $desinenza =~ s/^./i/;
405            
406             } elsif( $tema =~ /[aeious][cg]$/ and $tempo eq "participio") {
407 0         0 $tema .= "i";
408            
409             } elsif( $tema =~ /([^aeiou])([^aeiou])$/ and $tempo eq "participio") {
410 1         4 ($prima, $seconda) = ($1, $2);
411 1 50 33     15 if($seconda eq "g") {
    50 33        
    50 33        
    50          
412 0 0       0 $prima = "t" if $prima eq $seconda;
413 0         0 $seconda = "t";
414 0         0 $desinenza = "o";
415             } elsif($prima eq "m" and $seconda eq "p") {
416 0         0 $prima = "t";
417 0         0 $seconda = "t";
418 0         0 $desinenza = "o";
419             } elsif($prima eq "r" and $seconda eq "d") {
420 0         0 $seconda = "s";
421 0         0 $desinenza = "o";
422            
423             } elsif($prima eq "n" and $seconda eq "d") {
424 0 0       0 if($tema =~ /o..$/) {
    0          
425 0         0 $prima = "s";
426 0         0 $seconda = "t";
427 0         0 $desinenza = "o";
428             } elsif($tema =~ /[ue]..$/) {
429 0         0 $prima = "";
430 0         0 $seconda="s";
431 0         0 $desinenza = "o";
432             }
433             }
434 1         7 $tema =~ s/..$/$prima$seconda/;
435             }
436             }
437 2         8 return ($tema, $desinenza);
438             }
439            
440             sub declina {
441 1     1 0 36 my($verbo, $tempo, $opzioni) = @_;
442 1         2 $opzioni = opzioni_default( $opzioni );
443 1         2 my @result;
444 1         3 for my $persona (1..6) {
445 6 50       13 if($opzioni{pronomi}) {
446 0         0 push(@result, $Pronome[$persona] . " " . coniuga_forma($verbo, $tempo, $persona, $opzioni));
447             } else {
448 6         14 push(@result, coniuga_forma($verbo, $tempo, $persona, $opzioni));
449             }
450             }
451 1         7 return @result;
452             }
453            
454             sub verbo {
455 0     0 0   my($forma) = @_;
456             }
457            
458             sub verbo_esistente {
459 0     0 0   my($verbo) = @_;
460 0           $verbo =~ s/si$/e/;
461 0 0         if($verbo =~ /[ou]re$/) {
462 0           my $prova;
463 0           ($prova = $verbo) =~ s/re$/rre/;
464 0           $prova =~ s/urre$/ucere/i;
465 0           $prova =~ s/orre$/onere/i;
466 0 0 0       if(exists $Simile{$prova}
      0        
467             or exists $Regolarizza{$prova}
468             or exists $Prefissi{$prova}) {
469 0           $verbo = $prova;
470             }
471             }
472 0 0         if(open(VERBI, "$FindBin::RealBin/verbi") ) {
473 0           my $conosciuto = 0;
474 0           while() {
475 0           chomp;
476 0 0         $_ eq $verbo and $conosciuto = 1, last;
477             }
478 0           return $conosciuto;
479             } else {
480 0           return 1;
481             }
482             }
483            
484             sub coniugazione {
485 0     0 0   my($verbo, $opzioni) = @_;
486 0           my($tempo, $persona, $risultato);
487            
488 0           $opzioni = opzioni_default( $opzioni );
489            
490 0 0         if( $opzioni->{coniuga_sconosciuti} == 0) {
491 0 0         if(not verbo_esistente( $verbo )) {
492 0           $Errore = "unknown verb ('$verbo')";
493 0           return "[unknown verb ('$verbo')]";
494             }
495             }
496            
497 0           $risultato = "";
498 0           foreach ($tempo = 0; $tempo <= $#Tempi; $tempo += 2) {
499 0           $risultato .= centered(uc($Tempi[$tempo]), 35, "-");
500 0           $risultato .= " ";
501 0           $risultato .= centered(uc($Tempi[$tempo+1]), 35, "-");
502 0           $risultato .= "\n";
503 0           for $persona (1..6) {
504 0 0         $risultato .= sprintf "%-35s %-35s\n",
    0          
505             ( ($opzioni->{pronomi} == 1) ? $Pronome[$persona]." " : "" ).coniuga_forma($verbo, $Tempi[$tempo], $persona),
506             ( ($opzioni->{pronomi} == 1) ? $Pronome[$persona]." " : "" ).coniuga_forma($verbo, $Tempi[$tempo+1], $persona);
507             }
508             }
509 0           return $risultato;
510            
511             sub centered {
512 0     0 0   my($string, $len, $fill) = @_;
513 0 0         $fill = " " unless defined $fill;
514 0           my $result = $fill x (($len-length($string))/2-1);
515 0           $result .= " ";
516 0           $result .= $string;
517 0           $result .= " ";
518 0           $result .= $fill x ($len-length($result));
519 0           return $result;
520             }
521             }
522            
523             ### TEST_START
524             if(defined $ARGV[0]) {
525             if(not defined $ARGV[1] or $ARGV[1] eq "*") {
526             print coniugazione( $ARGV[0] , { pronomi => 1 }), "\n";
527             } else {
528             print join("\n", declina($ARGV[0], $ARGV[1])), "\n";
529             }
530             }
531             ### TEST_END
532            
533             1;
534            
535             __DATA__