File Coverage

blib/lib/Lingua/SWA/Word2Num.pm
Criterion Covered Total %
statement 25 31 80.6
branch 0 6 0.0
condition 2 4 50.0
subroutine 9 10 90.0
pod 3 3 100.0
total 39 54 72.2


line stmt bran cond sub pod time code
1             # For Emacs: -*- mode:cperl; eval: (folding-mode 1); coding:utf-8 -*-
2             package Lingua::SWA::Word2Num;
3             # ABSTRACT: Word to number conversion in Swahili
4              
5 1     1   92220 use 5.16.0;
  1         4  
6 1     1   8 use utf8;
  1         2  
  1         18  
7 1     1   34 use warnings;
  1         2  
  1         86  
8              
9             # {{{ use block
10              
11 1     1   722 use Export::Attrs;
  1         13153  
  1         9  
12 1     1   1412 use Parse::RecDescent;
  1         55708  
  1         11  
13              
14             # }}}
15             # {{{ var block
16             our $VERSION = '0.2603300';
17             my $parser = swa_numerals();
18              
19             # }}}
20              
21             # {{{ w2n convert text to number
22              
23             sub w2n :Export {
24 2   100 2 1 177400 my $input = shift // return;
25              
26 1         4 $input =~ s/\s+/ /g;
27 1         4 $input =~ s/^\s+|\s+$//g;
28              
29 1         13 return $parser->numeral($input);
30 1     1   277 }
  1         3  
  1         9  
31              
32             # }}}
33             # {{{ swa_numerals create parser for swahili numerals
34              
35             sub swa_numerals {
36 1     1 1 6 return Parse::RecDescent->new(q{
37            
38              
39             numeral: mega
40             | kOhOd
41             | { }
42              
43             number: 'sifuri' { 0 }
44             | 'moja' { 1 }
45             | 'mbili' { 2 }
46             | 'tatu' { 3 }
47             | 'nne' { 4 }
48             | 'tano' { 5 }
49             | 'sita' { 6 }
50             | 'saba' { 7 }
51             | 'nane' { 8 }
52             | 'tisa' { 9 }
53              
54             tens: 'ishirini' { 20 }
55             | 'thelathini' { 30 }
56             | 'arobaini' { 40 }
57             | 'hamsini' { 50 }
58             | 'sitini' { 60 }
59             | 'sabini' { 70 }
60             | 'themanini' { 80 }
61             | 'tisini' { 90 }
62              
63             deca: tens 'na' number { $item[1] + $item[3] }
64             | 'kumi' 'na' number { 10 + $item[3] }
65             | tens
66             | 'kumi' { 10 }
67             | number
68              
69             simpledeca: 'kumi' 'na' number { 10 + $item[3] }
70             | tens
71             | 'kumi' { 10 }
72             | number
73              
74             hecto: 'mia' deca 'na' deca { $item[2] * 100 + $item[4] }
75             | 'mia' deca { $item[2] * 100 }
76             | 'mia' { 100 }
77              
78             hOd: hecto
79             | deca
80              
81             kilo: 'elfu' hOd 'na' hOd { $item[2] * 1000 + $item[4] }
82             | 'elfu' hOd { $item[2] * 1000 }
83             | 'elfu' { 1000 }
84              
85             kOhOd: kilo
86             | hOd
87              
88             mega: 'milioni' hOd 'elfu' 'mia' number 'na' simpledeca 'na' hOd /\Z/
89             { $item[2] * 1_000_000 + ($item[5] * 100 + $item[7]) * 1000 + $item[9] }
90             | 'milioni' hOd kOhOd { $item[2] * 1_000_000 + $item[3] }
91             | 'milioni' hOd { $item[2] * 1_000_000 }
92             });
93             }
94              
95             # }}}
96             # {{{ ordinal2cardinal convert ordinal text to cardinal text
97              
98             sub ordinal2cardinal :Export {
99 0   0 0 1   my $input = shift // return;
100              
101             # Inverse of Swahili ordinal morphology: restore cardinal from ordinal text.
102             # Swahili ordinals use noun-class prefixes (wa-, ya-, cha-, vya-, etc.)
103             # followed by a special ordinal stem (1-5, 8) or the cardinal itself (6,7,9,10+).
104             #
105             # Special stems: kwanza→moja (1), pili→mbili (2)
106             # Identical stems (3,4,5,8): tatu, nne, tano, nane — no change needed.
107             # For 6,7,9,10+: ordinal = prefix + cardinal — strip prefix.
108              
109             # Strip noun-class prefix: "wa kwanza" → "kwanza", "ya pili" → "pili"
110             # The prefix is everything up to the last space; the ordinal word is the last token.
111             # For numbers >= 6 (except 8), the ordinal word IS the cardinal multi-word form,
112             # so we must preserve all tokens after the single-word prefix.
113             # Swahili ordinal format:
114             # where prefix is a single noun-class marker (wa, ya, cha, ki, vi, etc.)
115 0           $input =~ s{\A\S+\s+}{}xms;
116              
117             # Special ordinal stems that differ from cardinal
118 0 0         $input =~ s{\Akwanza\z}{moja}xms and return $input;
119 0 0         $input =~ s{\Apili\z}{mbili}xms and return $input;
120              
121             # For 3,4,5,8 the ordinal stem IS the cardinal — return as-is
122 0 0         return $input if $input =~ m{\A (?: tatu | nne | tano | nane ) \z}xms;
123              
124             # For 6,7,9 and all 10+ the ordinal form equals the cardinal — return as-is
125 0           return $input;
126 1     1   604 }
  1         2  
  1         6  
127              
128             # }}}
129              
130             1;
131              
132             __END__