File Coverage

blib/lib/Lingua/TUR/Word2Num.pm
Criterion Covered Total %
statement 23 41 56.1
branch 0 6 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::TUR::Word2Num;
3             # ABSTRACT: Word to number conversion in Turkish
4              
5 1     1   131326 use 5.16.0;
  1         5  
6 1     1   7 use utf8;
  1         2  
  1         16  
7 1     1   39 use warnings;
  1         2  
  1         81  
8              
9             # {{{ use block
10              
11 1     1   747 use Export::Attrs;
  1         13394  
  1         9  
12 1     1   1507 use Parse::RecDescent;
  1         52336  
  1         10  
13              
14             # }}}
15             # {{{ var block
16             our $VERSION = '0.2603300';
17             my $parser = tur_numerals();
18              
19             # }}}
20              
21             # {{{ w2n convert text to number
22              
23             sub w2n :Export {
24 2   100 2 1 164951 my $input = shift // return;
25              
26 1         15 return $parser->numeral($input);
27 1     1   159 }
  1         3  
  1         9  
28              
29             # }}}
30             # {{{ tur_numerals create parser for turkish numerals
31              
32             sub tur_numerals {
33 1     1 1 6 return Parse::RecDescent->new(q{
34            
35              
36             numeral: mega
37             | kOhOd
38             | { }
39              
40             number: 'sıfır' { 0 }
41             | 'bir' { 1 }
42             | 'iki' { 2 }
43             | 'üç' { 3 }
44             | 'dört' { 4 }
45             | 'beş' { 5 }
46             | 'altı' { 6 }
47             | 'yedi' { 7 }
48             | 'sekiz' { 8 }
49             | 'dokuz' { 9 }
50              
51             tens: 'on' { 10 }
52             | 'yirmi' { 20 }
53             | 'otuz' { 30 }
54             | 'kırk' { 40 }
55             | 'elli' { 50 }
56             | 'altmış' { 60 }
57             | 'yetmiş' { 70 }
58             | 'seksen' { 80 }
59             | 'doksan' { 90 }
60              
61             deca: tens number { $item[1] + $item[2] }
62             | tens
63             | number
64              
65             hecto: number 'yüz' deca { $item[1] * 100 + $item[3] }
66             | number 'yüz' { $item[1] * 100 }
67             | 'yüz' deca { 100 + $item[2] }
68             | 'yüz' { 100 }
69              
70             hOd: hecto
71             | deca
72              
73             kilo: hOd 'bin' hOd { $item[1] * 1000 + $item[3] }
74             | hOd 'bin' { $item[1] * 1000 }
75             | 'bin' hOd { 1000 + $item[2] }
76             | 'bin' { 1000 }
77              
78             kOhOd: kilo
79             | hOd
80              
81             mega: hOd 'milyon' kOhOd { $item[1] * 1_000_000 + $item[3] }
82             | hOd 'milyon' { $item[1] * 1_000_000 }
83             });
84             }
85              
86             # }}}
87             # {{{ ordinal2cardinal convert ordinal text to cardinal text
88              
89             sub ordinal2cardinal :Export {
90 0   0 0 1   my $input = shift // return;
91              
92             # Known cardinal words (from parser vocabulary).
93 0           state $cardinals = { map { $_ => 1 } qw(
  0            
94             sıfır bir iki üç dört beş altı yedi sekiz dokuz
95             on yirmi otuz kırk elli altmış yetmiş seksen doksan
96             yüz bin milyon
97             )};
98              
99             # Turkish ordinal suffixes (vowel harmony).
100             # After vowel-final stem: -ncı -nci -ncu -ncü
101             # After consonant-final stem: -ıncı -inci -uncu -üncü
102             # For compound numerals the suffix attaches to the last word only.
103 0           my @harmony = (
104             [ 'ncı', 'ıncı' ],
105             [ 'nci', 'inci' ],
106             [ 'ncu', 'uncu' ],
107             [ 'ncü', 'üncü' ],
108             );
109              
110 0           for my $pair (@harmony) {
111 0           my ($short, $long) = @{$pair};
  0            
112              
113 0           for my $suffix ($long, $short) {
114 0 0         next unless $input =~ /\Q$suffix\E\z/xms;
115 0           my $candidate = $input =~ s/\Q$suffix\E\z//xmsr;
116 0 0         next unless length $candidate;
117              
118             # For compounds, extract the last word for validation
119 0           my ($last_word) = $candidate =~ /(\S+)\z/xms;
120              
121             # Reverse consonant softening before lookup
122 0           my $lookup = $last_word;
123 0           $lookup =~ s/dörd\z/dört/xms;
124              
125 0 0         if ( exists $cardinals->{$lookup} ) {
126 0           $candidate =~ s/dörd\z/dört/xms;
127 0           return $candidate;
128             }
129             }
130             }
131              
132 0           return; # not an ordinal
133 1     1   788 }
  1         2  
  1         8  
134              
135             # }}}
136              
137             1;
138              
139             __END__