File Coverage

blib/lib/Lingua/SLV/Word2Num.pm
Criterion Covered Total %
statement 23 36 63.8
branch 0 6 0.0
condition 2 16 12.5
subroutine 9 10 90.0
pod 3 3 100.0
total 37 71 52.1


line stmt bran cond sub pod time code
1             # For Emacs: -*- mode:cperl; mode:folding; coding:utf-8; -*-
2              
3             package Lingua::SLV::Word2Num;
4             # ABSTRACT: Word to number conversion in Slovenian
5              
6 1     1   97490 use 5.16.0;
  1         3  
7 1     1   4 use utf8;
  1         2  
  1         9  
8 1     1   21 use warnings;
  1         2  
  1         62  
9              
10             # {{{ use block
11              
12 1     1   511 use Export::Attrs;
  1         11119  
  1         7  
13 1     1   1328 use Parse::RecDescent;
  1         38092  
  1         8  
14              
15             # }}}
16             # {{{ var block
17             our $VERSION = '0.2603300';
18             my $parser = slv_numerals();
19              
20             # }}}
21              
22             # {{{ w2n convert text to number
23              
24             sub w2n :Export {
25 15   100 15 1 928631 my $input = shift // return;
26              
27 14         185 return $parser->numeral($input);
28 1     1   103 }
  1         5  
  1         6  
29              
30             # }}}
31             # {{{ slv_numerals create parser for numerals
32              
33             sub slv_numerals {
34 1     1 1 5 return Parse::RecDescent->new(q{
35            
36              
37             numeral: mega
38             | kOhOd
39             | "nič" { 0 }
40             | { }
41              
42             number: 'enajst' { 11 }
43             | 'dvanajst' { 12 }
44             | 'trinajst' { 13 }
45             | "štirinajst" { 14 }
46             | 'petnajst' { 15 }
47             | "šestnajst" { 16 }
48             | 'sedemnajst' { 17 }
49             | 'osemnajst' { 18 }
50             | 'devetnajst' { 19 }
51             | 'ena' { 1 }
52             | 'en' { 1 }
53             | 'eno' { 1 }
54             | 'dve' { 2 }
55             | 'dva' { 2 }
56             | 'tri' { 3 }
57             | "štiri" { 4 }
58             | 'pet' { 5 }
59             | "šest" { 6 }
60             | 'sedem' { 7 }
61             | 'osem' { 8 }
62             | 'devet' { 9 }
63             | 'deset' { 10 }
64              
65             tens: 'dvajset' { 20 }
66             | 'trideset' { 30 }
67             | "štirideset" { 40 }
68             | 'petdeset' { 50 }
69             | "šestdeset" { 60 }
70             | 'sedemdeset' { 70 }
71             | 'osemdeset' { 80 }
72             | 'devetdeset' { 90 }
73              
74             deca: number 'in' tens { $item[1] + $item[3] }
75             | tens number { $item[1] + $item[2] }
76             | tens
77             | number
78              
79             hecto: number /sto/ deca { $item[1] * 100 + $item[3] }
80             | number /sto/ { $item[1] * 100 }
81             | 'dvesto' deca { 200 + $item[2] }
82             | 'dvesto' { 200 }
83             | 'tristo' deca { 300 + $item[2] }
84             | 'tristo' { 300 }
85             | "štiristo" deca { 400 + $item[2] }
86             | "štiristo" { 400 }
87             | 'petsto' deca { 500 + $item[2] }
88             | 'petsto' { 500 }
89             | "šeststo" deca { 600 + $item[2] }
90             | "šeststo" { 600 }
91             | 'sedemsto' deca { 700 + $item[2] }
92             | 'sedemsto' { 700 }
93             | 'osemsto' deca { 800 + $item[2] }
94             | 'osemsto' { 800 }
95             | 'devetsto' deca { 900 + $item[2] }
96             | 'devetsto' { 900 }
97             | 'sto' deca { 100 + $item[2] }
98             | 'sto' { 100 }
99              
100             hOd: hecto
101             | deca
102              
103             kilo: hOd "tisoč" hOd { $item[1] * 1000 + $item[3] }
104             | hOd "tisoč" { $item[1] * 1000 }
105             | number "tisoč" hOd { $item[1] * 1000 + $item[3] }
106             | number "tisoč" { $item[1] * 1000 }
107             | "tisoč" hOd { 1000 + $item[2] }
108             | "tisoč" { 1000 }
109              
110             kOhOd: kilo
111             | hOd
112              
113             mega: hOd megas kOhOd { $item[1] * 1_000_000 + $item[3] }
114             | hOd megas { $item[1] * 1_000_000 }
115             | 'en' 'milijon' kOhOd { 1_000_000 + $item[3] }
116             | 'en' 'milijon' { 1_000_000 }
117             | 'milijon' kOhOd { 1_000_000 + $item[2] }
118             | 'milijon' { 1_000_000 }
119              
120             megas: 'milijonov'
121             | 'milijone'
122             | 'milijona'
123             | 'milijon'
124             });
125             }
126              
127             # }}}
128             # {{{ ordinal2cardinal convert ordinal text to cardinal text
129              
130             sub ordinal2cardinal :Export {
131 0   0 0 1   my $input = shift // return;
132              
133             # Slovenian ordinals: strip gender/case suffixes, then map stems.
134             # Inflection: -i/-a/-o/-ega/-emu/-em/-im (masc/fem/neut/oblique).
135              
136 0           my %irregular = (
137             'ničti' => 'nič',
138             'prvi' => 'ena',
139             'drugi' => 'dva',
140             'tretji' => 'tri',
141             'četrti' => 'štiri',
142             'peti' => 'pet',
143             'šesti' => 'šest',
144             'sedmi' => 'sedem',
145             'osmi' => 'osem',
146             'deveti' => 'devet',
147             'deseti' => 'deset',
148             'enajsti' => 'enajst',
149             'dvanajsti' => 'dvanajst',
150             'trinajsti' => 'trinajst',
151             'štirinajsti' => 'štirinajst',
152             'petnajsti' => 'petnajst',
153             'šestnajsti' => 'šestnajst',
154             'sedemnajsti' => 'sedemnajst',
155             'osemnajsti' => 'osemnajst',
156             'devetnajsti' => 'devetnajst',
157             'dvajseti' => 'dvajset',
158             'trideseti' => 'trideset',
159             'štirideseti' => 'štirideset',
160             'petdeseti' => 'petdeset',
161             'šestdeseti' => 'šestdeset',
162             'sedemdeseti' => 'sedemdeset',
163             'osemdeseti' => 'osemdeset',
164             'devetdeseti' => 'devetdeset',
165             'dvestoti' => 'dvesto',
166             'tristoti' => 'tristo',
167             'štiristoti' => 'štiristo',
168             'petstoti' => 'petsto',
169             'šeststoti' => 'šeststo',
170             'sedemstoti' => 'sedemsto',
171             'osemstoti' => 'osemsto',
172             'devetstoti' => 'devetsto',
173             'stoti' => 'sto',
174             'tisočti' => 'tisoč',
175             'tisoči' => 'tisoč',
176             'milijonti' => 'milijon',
177             );
178              
179             # Compound ordinals: ALL components are ordinal forms.
180             # Normalize each word individually, then look up in the mapping.
181 0           my @words = split /\s+/, $input;
182 0           my @result;
183 0           my $matched = 0;
184              
185 0           for my $word (@words) {
186             # Strip gender/case suffixes to masculine nominative (-i)
187 0           my $norm = $word;
188 0 0 0       $norm =~ s{ega\z}{i}xms
      0        
      0        
      0        
189             or $norm =~ s{emu\z}{i}xms
190             or $norm =~ s{em\z}{i}xms
191             or $norm =~ s{im\z}{i}xms
192             or $norm =~ s{a\z}{i}xms # fem: prva → prvi
193             or $norm =~ s{o\z}{i}xms; # neut: prvo → prvi
194              
195 0 0         if (exists $irregular{$norm}) {
196 0           push @result, $irregular{$norm};
197 0           $matched = 1;
198             }
199             else {
200 0           push @result, $word; # pass through unchanged (connectors, etc.)
201             }
202             }
203              
204 0 0         return $matched ? join(' ', @result) : undef;
205 1     1   853 }
  1         1  
  1         5  
206              
207             # }}}
208              
209             1;
210              
211             __END__