File Coverage

blib/lib/Lingua/RON/Word2Num.pm
Criterion Covered Total %
statement 23 35 65.7
branch 0 12 0.0
condition 2 4 50.0
subroutine 9 10 90.0
pod 3 3 100.0
total 37 64 57.8


line stmt bran cond sub pod time code
1             # For Emacs: -*- mode:cperl; eval: (folding-mode 1); coding:utf-8 -*-
2             package Lingua::RON::Word2Num;
3             # ABSTRACT: Word to number conversion in Romanian
4              
5 1     1   136153 use 5.16.0;
  1         4  
6 1     1   6 use utf8;
  1         2  
  1         14  
7 1     1   34 use warnings;
  1         4  
  1         107  
8              
9             # {{{ use block
10              
11 1     1   664 use Export::Attrs;
  1         13044  
  1         8  
12 1     1   1464 use Parse::RecDescent;
  1         53299  
  1         11  
13              
14             # }}}
15             # {{{ var block
16             our $VERSION = '0.2603300';
17             my $parser = ron_numerals();
18              
19             # }}}
20              
21             # {{{ w2n convert text to number
22              
23             sub w2n :Export {
24 2   100 2 1 266704 my $input = shift // return;
25              
26 1         20 return $parser->numeral($input);
27 1     1   153 }
  1         7  
  1         9  
28              
29             # }}}
30             # {{{ ron_numerals create parser for romanian numerals
31              
32             sub ron_numerals {
33 1     1 1 7 return Parse::RecDescent->new(q{
34            
35              
36             numeral: mega
37             | kOhOd
38             | 'zero' { 0 }
39             | { }
40              
41             number: 'unsprezece' { 11 }
42             | 'doisprezece' { 12 }
43             | 'treisprezece' { 13 }
44             | 'paisprezece' { 14 }
45             | 'cincisprezece' { 15 }
46             | /[sș]aisprezece/ { 16 }
47             | /[sș]aptesprezece/ { 17 }
48             | 'optsprezece' { 18 }
49             | /nou[aă]sprezece/ { 19 }
50             | 'zece' { 10 }
51             | /un[ua]?/ { 1 }
52             | /dou[aă]/ { 2 }
53             | 'doi' { 2 }
54             | 'trei' { 3 }
55             | 'patru' { 4 }
56             | 'cinci' { 5 }
57             | /[sș]ase/ { 6 }
58             | /[sș]apte/ { 7 }
59             | 'opt' { 8 }
60             | /nou[aă]/ { 9 }
61              
62             tens: /dou[aă]zeci/ { 20 }
63             | 'treizeci' { 30 }
64             | 'patruzeci' { 40 }
65             | 'cincizeci' { 50 }
66             | /[sș]aizeci/ { 60 }
67             | /[sș]aptezeci/ { 70 }
68             | 'optzeci' { 80 }
69             | /nou[aă]zeci/ { 90 }
70              
71             deca: tens /[sș]i/ number { $item[1] + $item[3] }
72             | tens
73             | number
74              
75             hecto: 'o' /sut[aă]/ deca { 100 + $item[3] }
76             | 'o' /sut[aă]/ { 100 }
77             | /dou[aă]/ 'sute' deca { 200 + $item[3] }
78             | /dou[aă]/ 'sute' { 200 }
79             | number 'sute' deca { $item[1] * 100 + $item[3] }
80             | number 'sute' { $item[1] * 100 }
81              
82             hOd: hecto
83             | deca
84              
85             kilo: 'o' 'mie' hOd { 1000 + $item[3] }
86             | 'o' 'mie' { 1000 }
87             | /dou[aă]/ 'mii' hOd { 2000 + $item[3] }
88             | /dou[aă]/ 'mii' { 2000 }
89             | hOd 'mii' hOd { $item[1] * 1000 + $item[3] }
90             | hOd 'mii' { $item[1] * 1000 }
91              
92             kOhOd: kilo
93             | hOd
94              
95             mega: 'un' 'milion' kOhOd { 1_000_000 + $item[3] }
96             | 'un' 'milion' { 1_000_000 }
97             | /dou[aă]/ 'milioane' kOhOd { 2_000_000 + $item[3] }
98             | /dou[aă]/ 'milioane' { 2_000_000 }
99             | hOd 'milioane' kOhOd { $item[1] * 1_000_000 + $item[3] }
100             | hOd 'milioane' { $item[1] * 1_000_000 }
101             });
102             }
103              
104             # }}}
105             # {{{ ordinal2cardinal convert ordinal text to cardinal text
106              
107             sub ordinal2cardinal :Export {
108 0   0 0 1   my $input = shift // return;
109              
110             # Romanian ordinals:
111             # "primul/prima" → suppletive for 1st (cardinal: "unu"/"una")
112             # 2-10: "al doilea/a doua" etc. — irregular stems
113             # 11+: "al " + cardinal + "lea" / "a " + cardinal + "a"
114              
115             # Masculine suppletive 1st
116 0 0         return 'unu' if $input =~ m{\A primul \z}xms;
117 0 0         return 'una' if $input =~ m{\A prima \z}xms;
118              
119             # Feminine ordinals: "a a"
120             # (must check before masculine to avoid ambiguity)
121 0           state $fem_irregular = {
122             'a doua' => 'două',
123             'a treia' => 'trei',
124             'a patra' => 'patru',
125             'a cincea' => 'cinci',
126             'a șasea' => 'șase',
127             'a șaptea' => 'șapte',
128             'a opta' => 'opt',
129             'a noua' => 'nouă',
130             'a zecea' => 'zece',
131             };
132              
133 0 0         return $fem_irregular->{$input} if exists $fem_irregular->{$input};
134              
135             # Masculine ordinals: "al lea"
136 0           state $masc_irregular = {
137             'al doilea' => 'doi',
138             'al treilea' => 'trei',
139             'al patrulea' => 'patru',
140             'al cincilea' => 'cinci',
141             'al șaselea' => 'șase',
142             'al șaptelea' => 'șapte',
143             'al optulea' => 'opt',
144             'al nouălea' => 'nouă',
145             'al zecelea' => 'zece',
146             };
147              
148 0 0         return $masc_irregular->{$input} if exists $masc_irregular->{$input};
149              
150             # Regular masculine (11+): "al " + cardinal + "lea"
151 0 0         if ($input =~ m{\A al \s+ (?.+?) lea \z}xms) {
152 0           return $+{card};
153             }
154              
155             # Regular feminine (11+): "a " + cardinal + "a"
156 0 0         if ($input =~ m{\A a \s+ (?.+?) a \z}xms) {
157 0           return $+{card};
158             }
159              
160 0           return; # not an ordinal
161 1     1   1004 }
  1         3  
  1         33  
162              
163             # }}}
164              
165             1;
166              
167             __END__