File Coverage

blib/lib/Lingua/GLG/Word2Num.pm
Criterion Covered Total %
statement 26 41 63.4
branch 0 22 0.0
condition 2 4 50.0
subroutine 9 10 90.0
pod 3 3 100.0
total 40 80 50.0


line stmt bran cond sub pod time code
1             # For Emacs: -*- mode:cperl; eval: (folding-mode 1); coding:utf-8; -*-
2              
3             package Lingua::GLG::Word2Num;
4             # ABSTRACT: Word to number conversion in Galician
5              
6 1     1   91311 use 5.16.0;
  1         4  
7 1     1   8 use utf8;
  1         4  
  1         20  
8 1     1   51 use warnings;
  1         2  
  1         97  
9              
10             # {{{ use block
11              
12 1     1   1412 use Parse::RecDescent;
  1         40791  
  1         9  
13 1     1   620 use Export::Attrs;
  1         9683  
  1         8  
14              
15             # }}}
16             # {{{ var block
17             our $VERSION = '0.2603300';
18             my $parser = glg_numerals();
19              
20             # }}}
21              
22             # {{{ w2n convert text to number
23              
24             sub w2n :Export {
25 9   100 9 1 621111 my $input = shift // return;
26              
27 8         31 $input = lc $input;
28 8         62 $input =~ s/\s+/ /g;
29 8         63 $input =~ s/^\s+|\s+$//g;
30              
31 8         87 return $parser->numeral($input);
32 1     1   223 }
  1         2  
  1         8  
33             # }}}
34             # {{{ glg_numerals create parser for numerals
35              
36             sub glg_numerals {
37 1     1 1 7 return Parse::RecDescent->new(q{
38            
39            
40              
41             numeral: mega
42             | kOhOd
43             | 'cero' { 0 }
44             | { }
45              
46             number: 'un' { 1 }
47             | 'dous' { 2 }
48             | 'tres' { 3 }
49             | 'catro' { 4 }
50             | 'cinco' { 5 }
51             | 'seis' { 6 }
52             | 'sete' { 7 }
53             | 'oito' { 8 }
54             | 'nove' { 9 }
55             | 'dezaseis' { 16 }
56             | 'dezasete' { 17 }
57             | 'dezaoito' { 18 }
58             | 'dezanove' { 19 }
59             | 'dez' { 10 }
60             | 'once' { 11 }
61             | 'doce' { 12 }
62             | 'trece' { 13 }
63             | 'catorce' { 14 }
64             | 'quince' { 15 }
65              
66             tens: 'vinte' { 20 }
67             | 'trinta' { 30 }
68             | 'corenta' { 40 }
69             | 'cincuenta' { 50 }
70             | 'sesenta' { 60 }
71             | 'setenta' { 70 }
72             | 'oitenta' { 80 }
73             | 'noventa' { 90 }
74              
75             hundreds: 'cincocentos' { 500 }
76             | 'setecentos' { 700 }
77             | 'novecentos' { 900 }
78             | 'oitocentos' { 800 }
79             | 'seiscentos' { 600 }
80             | 'catrocentos' { 400 }
81             | 'trescentos' { 300 }
82             | 'douscentos' { 200 }
83             | /cen(to)?/ { 100 }
84              
85             deca: tens 'e' number { $item[1] + $item[3] }
86             | tens
87             | number
88              
89             hecto: hundreds 'e' deca { $item[1] + $item[3] }
90             | hundreds deca { $item[1] + $item[2] }
91             | hundreds
92              
93             hOd: hecto
94             | deca
95              
96             kilo: hOd milnotmeg 'e' hOd { $item[1] * 1000 + $item[4] }
97             | hOd milnotmeg hOd { $item[1] * 1000 + $item[3] }
98             | hOd milnotmeg { $item[1] * 1000 }
99             | milnotmeg 'e' hOd { 1000 + $item[3] }
100             | milnotmeg hOd { 1000 + $item[2] }
101             | milnotmeg { 1000 }
102              
103             milnotmeg: ...!/mill(ón|óns)/ 'mil'
104              
105             kOhOd: kilo
106             | hOd
107              
108             mega: hOd /mill(óns|ón)/ 'e' kOhOd { $item[1] * 1_000_000 + $item[4] }
109             | hOd /mill(óns|ón)/ kOhOd { $item[1] * 1_000_000 + $item[3] }
110             | hOd /mill(óns|ón)/ { $item[1] * 1_000_000 }
111             });
112             }
113              
114             # }}}
115             # {{{ ordinal2cardinal convert ordinal text to cardinal text
116              
117             sub ordinal2cardinal :Export {
118 0   0 0 1   my $input = shift // return;
119              
120             # Galician ordinals 1-10 are fully irregular
121 0           state $irregular = {
122             'primeiro' => 'un', 'primeira' => 'un',
123             'segundo' => 'dous', 'segunda' => 'dous',
124             'terceiro' => 'tres', 'terceira' => 'tres',
125             'cuarto' => 'catro', 'cuarta' => 'catro',
126             'quinto' => 'cinco', 'quinta' => 'cinco',
127             'sexto' => 'seis', 'sexta' => 'seis',
128             'sétimo' => 'sete', 'sétima' => 'sete',
129             'oitavo' => 'oito', 'oitava' => 'oito',
130             'noveno' => 'nove', 'novena' => 'nove',
131             'décimo' => 'dez', 'décima' => 'dez',
132             };
133              
134 0 0         return $irregular->{$input} if exists $irregular->{$input};
135              
136             # Regular (11+): cardinal (drop final vowel) + "ésimo/ésima"
137 0 0         $input =~ s{ésim[oa]\z}{}xms or return;
138              
139             # Galician drops the final vowel before adding -ésimo. The dropped
140             # vowel varies by word, so we restore it based on the stem ending.
141              
142             # cinco: cinc→cinco (must precede the general -c rule)
143 0 0         if ($input =~ m{\Acinc\z}xms) { $input .= 'o' }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
144             # also "vinte e cinc" etc. — cinc at end of compound
145 0           elsif ($input =~ m{cinc\z}xms) { $input .= 'o' }
146             # teens ending in -c: onc→once, doc→doce, trec→trece, catorc→catorce, quinc→quince
147 0           elsif ($input =~ m{c\z}xms) { $input .= 'e' }
148             # oito family: dezaoit→dezaoito, oit→oito
149 0           elsif ($input =~ m{oit\z}xms) { $input .= 'o' }
150             # sete family: dezaset→dezasete, set→sete
151 0           elsif ($input =~ m{set\z}xms) { $input .= 'e' }
152             # vinte: vint→vinte
153 0           elsif ($input =~ m{vint\z}xms) { $input .= 'e' }
154             # decades (trinta, corenta, etc.): trint→trinta, corent→corenta
155 0           elsif ($input =~ m{nt\z}xms) { $input .= 'a' }
156             # nove family: dezanov→dezanove, nov→nove
157 0           elsif ($input =~ m{ov\z}xms) { $input .= 'e' }
158             # catro: catr→catro
159 0           elsif ($input =~ m{tr\z}xms) { $input .= 'o' }
160              
161 0           return $input;
162 1     1   525 }
  1         2  
  1         4  
163              
164             # }}}
165              
166             1;
167              
168             __END__