File Coverage

blib/lib/Lingua/SLK/Word2Num.pm
Criterion Covered Total %
statement 23 36 63.8
branch 0 6 0.0
condition 2 19 10.5
subroutine 9 10 90.0
pod 3 3 100.0
total 37 74 50.0


line stmt bran cond sub pod time code
1             # For Emacs: -*- mode:cperl; mode:folding; coding:utf-8; -*-
2              
3             package Lingua::SLK::Word2Num;
4             # ABSTRACT: Word to number conversion in Slovak
5              
6 1     1   97233 use 5.16.0;
  1         3  
7 1     1   4 use utf8;
  1         2  
  1         12  
8 1     1   21 use warnings;
  1         2  
  1         51  
9              
10             # {{{ use block
11              
12 1     1   519 use Export::Attrs;
  1         9401  
  1         6  
13 1     1   1202 use Parse::RecDescent;
  1         35471  
  1         8  
14              
15             # }}}
16             # {{{ var block
17             our $VERSION = '0.2603300';
18             my $parser = slk_numerals();
19              
20             # }}}
21              
22             # {{{ w2n convert text to number
23              
24             sub w2n :Export {
25 2   100 2 1 304811 my $input = shift // return;
26              
27 1         19 return $parser->numeral($input);
28 1     1   116 }
  1         3  
  1         8  
29              
30             # }}}
31             # {{{ slk_numerals create parser for numerals
32              
33             sub slk_numerals {
34 1     1 1 6 return Parse::RecDescent->new(q{
35            
36              
37             numeral: mega
38             | kOhOd
39             | 'nula' { 0 }
40             | { }
41              
42             number: 'dvanásť' { 12 }
43             | 'trinásť' { 13 }
44             | 'štrnásť' { 14 }
45             | 'pätnásť' { 15 }
46             | 'šestnásť' { 16 }
47             | 'sedemnásť' { 17 }
48             | 'osemnásť' { 18 }
49             | 'devätnásť' { 19 }
50             | 'jedenásť' { 11 }
51             | 'jedna' { 1 }
52             | 'jeden' { 1 }
53             | 'dva' { 2 }
54             | 'dve' { 2 }
55             | 'tri' { 3 }
56             | 'štyri' { 4 }
57             | 'päť' { 5 }
58             | 'šesť' { 6 }
59             | 'sedem' { 7 }
60             | 'osem' { 8 }
61             | 'deväť' { 9 }
62             | 'desať' { 10 }
63              
64             tens: 'dvadsať' { 20 }
65             | 'tridsať' { 30 }
66             | 'štyridsať' { 40 }
67             | 'päťdesiat' { 50 }
68             | 'šesťdesiat' { 60 }
69             | 'sedemdesiat' { 70 }
70             | 'osemdesiat' { 80 }
71             | 'deväťdesiat' { 90 }
72              
73             deca: tens number { $item[1] + $item[2] }
74             | tens
75             | number
76              
77             hecto: 'deväťsto' deca { 900 + $item[2] }
78             | 'deväťsto' { 900 }
79             | 'osemsto' deca { 800 + $item[2] }
80             | 'osemsto' { 800 }
81             | 'sedemsto' deca { 700 + $item[2] }
82             | 'sedemsto' { 700 }
83             | 'šesťsto' deca { 600 + $item[2] }
84             | 'šesťsto' { 600 }
85             | 'päťsto' deca { 500 + $item[2] }
86             | 'päťsto' { 500 }
87             | 'štyristo' deca { 400 + $item[2] }
88             | 'štyristo' { 400 }
89             | 'tristo' deca { 300 + $item[2] }
90             | 'tristo' { 300 }
91             | 'dvesto' deca { 200 + $item[2] }
92             | 'dvesto' { 200 }
93             | 'sto' deca { 100 + $item[2] }
94             | 'sto' { 100 }
95              
96             hOd: hecto
97             | deca
98              
99             kilo: hOd /tisíce?/ hOd { $item[1] * 1000 + $item[3] }
100             | hOd /tisíce?/ { $item[1] * 1000 }
101             | number /tisíce?/ hOd { $item[1] * 1000 + $item[3] }
102             | number /tisíce?/ { $item[1] * 1000 }
103             | 'tisíc' hOd { 1000 + $item[2] }
104             | 'tisíc' { 1000 }
105             | hOd 'jeden' 'tisíc' hOd { ($item[1] + 1) * 1000 + $item[4] }
106             | hOd 'jeden' 'tisíc' { ($item[1] + 1) * 1000 }
107              
108             kOhOd: kilo
109             | hOd
110              
111             mega: hOd megas kOhOd { $item[1] * 1_000_000 + $item[3] }
112             | hOd megas { $item[1] * 1_000_000 }
113             | 'milión' kOhOd { 1_000_000 + $item[2] }
114             | 'milión' { 1_000_000 }
115             | hOd 'jeden' 'milión' kOhOd { ($item[1] + 1) * 1_000_000 + $item[4] }
116              
117             megas: /milión(y|ov)/
118             | 'milión'
119             });
120             }
121              
122             # }}}
123             # {{{ ordinal2cardinal convert ordinal text to cardinal text
124              
125             sub ordinal2cardinal :Export {
126 0   0 0 1   my $input = shift // return;
127              
128             # Slovak ordinals: strip gender suffixes, then map stems.
129             # Inflection: -ý/-á/-é/-ého/-ému/-ém/-ým (masc/fem/neut/oblique).
130              
131 0           my %irregular = (
132             'nultý' => 'nula',
133             'prvý' => 'jeden',
134             'druhý' => 'dva',
135             'tretí' => 'tri',
136             'štvrtý' => 'štyri',
137             'piaty' => 'päť',
138             'šiesty' => 'šesť',
139             'siedmy' => 'sedem',
140             'ôsmy' => 'osem',
141             'deviaty' => 'deväť',
142             'desiaty' => 'desať',
143             'jedenásty' => 'jedenásť',
144             'dvanásty' => 'dvanásť',
145             'trinásty' => 'trinásť',
146             'štrnásty' => 'štrnásť',
147             'pätnásty' => 'pätnásť',
148             'šestnásty' => 'šestnásť',
149             'sedemnásty' => 'sedemnásť',
150             'osemnásty' => 'osemnásť',
151             'devätnásty' => 'devätnásť',
152             'dvadsiaty' => 'dvadsať',
153             'tridsiaty' => 'tridsať',
154             'štyridsiaty' => 'štyridsať',
155             'päťdesiaty' => 'päťdesiat',
156             'šesťdesiaty' => 'šesťdesiat',
157             'sedemdesiaty' => 'sedemdesiat',
158             'osemdesiaty' => 'osemdesiat',
159             'deväťdesiaty' => 'deväťdesiat',
160             'dvojstý' => 'dvesto',
161             'trojstý' => 'tristo',
162             'štvorstý' => 'štyristo',
163             'päťstý' => 'päťsto',
164             'šesťstý' => 'šesťsto',
165             'sedemstý' => 'sedemsto',
166             'osemstý' => 'osemsto',
167             'deväťstý' => 'deväťsto',
168             'stý' => 'sto',
169             'tisíci' => 'tisíc',
170             'miliónty' => 'milión',
171             );
172              
173             # Compound ordinals: ALL components are ordinal forms.
174             # Normalize each word individually, then look up in the mapping.
175 0           my @words = split /\s+/, $input;
176 0           my @result;
177 0           my $matched = 0;
178              
179 0           for my $word (@words) {
180             # Strip gender/case suffixes to masculine nominative
181 0           my $norm = $word;
182 0 0 0       $norm =~ s{(í)ho\z}{$1}xms
      0        
      0        
      0        
      0        
183             or $norm =~ s{ého\z}{ý}xms
184             or $norm =~ s{ému\z}{ý}xms
185             or $norm =~ s{ém\z}{ý}xms
186             or $norm =~ s{ým\z}{ý}xms
187             or $norm =~ s{á\z}{ý}xms
188             or $norm =~ s{é\z}{ý}xms;
189              
190 0 0         if (exists $irregular{$norm}) {
191 0           push @result, $irregular{$norm};
192 0           $matched = 1;
193             }
194             else {
195 0           push @result, $word; # pass through unchanged (connectors, etc.)
196             }
197             }
198              
199 0 0         return $matched ? join(' ', @result) : undef;
200 1     1   754 }
  1         2  
  1         4  
201              
202             # }}}
203              
204             1;
205              
206             __END__