-
Notifications
You must be signed in to change notification settings - Fork 0
/
numbers.foma
355 lines (294 loc) · 10.9 KB
/
numbers.foma
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
# Copyright (C) 2023 Darko Milosevic <daremc86@gmail.com>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, version 3.0 of the License.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
define nogenderUnit
%0: нула |
3:три |
4:четири |
5:пет |
6:шест |
7:седам |
8:осам |
9:девет ;
define MascUnit
1:један | #, једна,једно
2:два | #, две, два
nogenderUnit;
define FemUnit
1:једна |
2:две |
nogenderUnit;
define MaleOrdUnit
1:први |
2:други |
3:трећи |
4:четврти |
5:пети |
6:шести |
7:седми |
8:осми |
9:девети ;
define FemaleOrdUnit
1:прва |
2:друга |
3:трећа |
4:четврта |
5:пета |
6:шеста |
7:седма |
8:осма |
9:девета ;
define NeuterOrdUnit
1:прво |
2:друго |
3:треће |
4:четврто |
5:пето |
6:шесто |
7:седмо |
8:осмо |
9:девето ;
define Teen
1:једанаест| #, једна,једно
2:дванаест | #, две, два
3:тринаест |
4:четрнаест |
5:петнаест |
6:шеснаест |
7:седамнаест |
8:осамнаест |
9:деветнаест;
define MaleOrdTeen
1:једанаести |
2:дванаести |
3:тринаести |
4:четрнаести |
5:петнаести |
6:шеснаести |
7:седамнаести |
8:осамнаести |
9:деветнаести ;
define FemaleOrdTeen
1:једанаеста |
2:дванаеста |
3:тринаеста |
4:четрнаеста |
5:петнаеста |
6:шеснаеста |
7:седамнаеста |
8:осамнаеста |
9:деветнаеста ;
define NeuterOrdTeen
1:једанаесто |
2:дванаессто |
3:тринаесто |
4:четрнаесто |
5:петнаесто |
6:шеснаесто |
7:седамнаесто |
8:осамнаесто |
9:деветнаесто ;
define Ten
1:десет |
2:двадесет |
3:тридесет |
4:четрдесет |
5:педесет |
6:шездесет |
7:седамдесет |
8:осамдесет |
9:деведесет ;
define MaleOrdTen
1:десети |
2:двадесети |
3:тридесети |
4:четрдесети |
5:педесети |
6:шездесети |
7:седамдесети |
8:осамдесети |
9:деведесети ;
define FemaleOrdTen
1:десета |
2:двадесета |
3:тридесета |
4:четрдесета |
5:педесета |
6:шездесета |
7:седамдесета |
8:осамдесета |
9:деведесета ;
define NeuterOrdTen
1:десето |
2:двадесето |
3:тридесето |
4:четрдесето |
5:педессето |
6:шездессето |
7:седамдесето |
8:осамдесето |
9:деведесето ;
define Hundred
1:сто |
2:двеста |
3:триста |
4:четиристо |
5:петсто |
6:шестсто |
7:седамсто |
8:осамсто |
9:деветсто ;
define MaleOrdHundred
1:стоти |
2:двестоти |
3:тристоти |
4:четиристоти |
5:петстоти |
6:шестстоти |
7:седамстоти |
8:осамстоти |
9:деветстоти ;
define FemaleOrdHundred
1:стота |
2:двестота |
3:тристота |
4:четиристота |
5:петстота |
6:шестстота |
7:седамстота |
8:осамстота |
9:деветстота ;
define NeuterOrdHundred
1:стото |
2:двестото |
3:тристото |
4:четиристото |
5:петстото |
6:шестстото |
7:седамстото |
8:осамстото |
9:деветстото ;
define TenOrHundredSymbol ten|hnd ;
# ----------------------------
define NZDigit 1|2|3|4|5|6|7|8|9 ;
define Digit %0|NZDigit ;
source Ordinals.foma
define UnformattedNumber %0 | [NZDigit Digit^<15] ;
define FormattedNumber NZDigit Digit^<3 [%. Digit^3]^{1,4} ;
define RegularDecimal [FormattedNumber|UnformattedNumber] %, Digit+; # 3.000.320(,022)
define ForeignDecimal UnformattedNumber %. [Digit^<3 | Digit^>3]; # foreign DP 1.02
define Ordinal [FormattedNumber|UnformattedNumber] OrdSuffix ; # number (has to be without commas) followed by ordinal marker
define ArabicNumber UnformattedNumber | FormattedNumber | RegularDecimal | ForeignDecimal | Ordinal;
# tag valid numbers
define tagNumberTypes
[FormattedNumber|UnformattedNumber] @-> ... wnum || .#. _ (%, Digit+) .#. ,, # 3.000.320(,022)
UnformattedNumber @-> ... wnum || .#. _ (%. Digit+) .#. ,, # foreign DP 1.02
UnformattedNumber @-> ... wnum || .#. _ (%. [Digit^{1,2} | Digit^>3]) .#. ,, # foreign DP 1.02
[FormattedNumber|UnformattedNumber] @-> ... wnum ord || .#. _ [%. | OrdSuffix] .#. ; # number (has to be without commas) followed by ordinal marker
# We expect this code to be protected from strings contain other than digits, commas and periods.
# We will, however, catch non-numbers which has slipped through, like 20.0.1 or 20,11,111
define tagCascade
[ [%,|%.] -> ... dp || wnum _ Digit+ .#. ] # place decimal point after whole numbers
.o. [ [%.]:0 -> || _ ?* wnum ] # get rid of the thousands dividers
.o. [ Digit -> ... dec || dp Digit* _ .#. ] # mark decimal
.o. [ dec -> wnum || dp NZDigit Digit^<3 _ .#. ] # See (1) below, "Un-Decimalize"
.o. [ Digit-> ... wnum || [.#. | \Digit] Digit* _ [ .#. | %. | %, ]]; # not a whole number, or decimal
# (1) Un-Decimalize For decimal parts, we want any sequence without a leading zero, up to three places, to be read as a whole
# number rather than a list of digits
# by now we have wnum tags for numbers which should be read as whole numbers, dec for those which should be treated differently,# ord tag after wnum, and periods and commas dotted about.
define tagRules tagNumberTypes .o. tagCascade;
# For whole numbers change the markers for singles
define preTranslate
[1 thns] -> [1 thn] || _ ,,
[2 thns] -> [2 thnss] || _ ,,
[3 thns] -> [3 thnss] || _ ,,
[4 thns] -> [4 thnss] || _ ,,
[1 mlns] -> [1 mln] || _ ,,
[1 blns] -> [1 bln] || _ ,,
[2 blns] -> [2 blnss] || _ ,,
[3 blns] -> [3 blnss] || _ ,,
[4 blns] -> [4 blnss] || _ ,,
[1 tlns] -> [1 tln] || _ ;
#----------------------------
define PowerOfThousandSymbol thns|mlns|blns|tlns|thn|thnss|mln|bln|blnss|tln ;
define PowerOfTenSymbol TenOrHundredSymbol|PowerOfThousandSymbol ;
# define SeparatePowerOfThousands(s) [..] -> s || Digit _ Digit^3 wnum ;
define SeparatePowerOfThousand(s) [..] -> s || Digit _ Digit^3 [\dec & \Digit] ;
define PowerOfThousandSymbolsToSingular
[mlns:mln|blns:bln|tlns:tln] -> || [[PowerOfThousandSymbol ]|wnum] 1 _ ;
define RemoveSilentGroups
%0^3 (PowerOfThousandSymbol) @-> 0 || _ ?* wnum ;
define SeparateHundreds
[..] -> hnd || Digit _ Digit^2 ?* wnum;
define Mark100s
hnd -> hnd0 || 1 _ {00} ;
define SeparateTens
[..] -> ten || Digit _ Digit ?* wnum;
define RemoveZeros
%0 (TenOrHundredSymbol) @-> 0 || _ ?* wnum;
define MarkTeens
[[1 ten]:0] NZDigit [0:[teen %0]] -> ;
define RemoveOnes
1 -> 0 || .#. _ thn ;
define processOrdinals
# first the indefs, then the defs. Because we need to output whole words as symbols, we cannot build up these forms using syntactical rules. Ironic.
MaleOrdUnit -> || _ wnum ord MaleOrdSuffix .#. ,,
FemaleOrdUnit -> || _ wnum ord FemaleOrdSuffix .#. ,,
NeuterOrdUnit -> || _ wnum ord NeuterOrdSuffix .#. ,,
[MaleOrdTeen teen:0]-> || _ wnum ord MaleOrdSuffix .#. ,,
[FemaleOrdTeen teen:0] -> || _ wnum ord FemaleOrdSuffix .#. ,,
[NeuterOrdTeen teen:0] -> || _ wnum ord NeuterOrdSuffix .#. ,,
[MaleOrdTen ten:0] -> || _ wnum ord MaleOrdSuffix .#. ,,
[FemaleOrdTen ten:0] -> || _ wnum ord FemaleOrdSuffix .#. ,,
[NeuterOrdTen ten:0] -> || _ wnum ord NeuterOrdSuffix .#. ,,
[MaleOrdHundred [hnd|hnds]:0] -> || _ wnum ord MaleOrdSuffix .#. ,,
[FemaleOrdHundred [hnd|hnds]:0] -> || _ wnum ord FemaleOrdSuffix .#. ,,
[NeuterOrdHundred [hnd|hnds]:0] -> || _ wnum ord NeuterOrdSuffix .#. ;
define Translate
[
MascUnit -> || _ wnum | dec | [PowerOfThousandSymbol - thn - thns - thnss - bln - blns - blnss] ,,
FemUnit -> || _ [thn | thns | thnss | bln | blns | blnss] ,,
MascUnit -> || dp Digit* _ Digit* dec ,, # right of decimal point
Teen [teen:0] -> || _ ,,
Ten [ten:0] -> || _ ,,
Hundred [hnd:0] -> || _ ,,
%, -> запета || _ ?+ .#. ,,
%. -> тачка || _ ?+ .#. ,,
[[thns|thnss|thn]:хиљадити|[mlns|mln]:милионити|[blns|blnss|bln]:милијардити|[tlns|tln]:билионити] @-> || _ wnum ord MaleOrdSuffix ,,
[[thns|thnss|thn]:хиљадита|[mlns|mln]:милионита|[blns|blnss|bln]:милијардита|[tlns|tln]:билионита] @-> || _ wnum ord FemaleOrdSuffix ,,
[[thns|thnss|thn]:хиљадито|[mlns|mln]:милионито|[blns|blnss|bln]:милијардито|[tlns|tln]:билионито] @-> || _ wnum ord NeuterOrdSuffix
]
.o. [
[thn:хиљаду | mln:милион | bln:милијарда | tln:билион] -> || _ ,,
[thns:хиљада | thnss:хиљаде | mlns:милиона | blns:милијарди | blnss:милијарде | tlns:билиона] -> || _
];
define NumberRules
SeparatePowerOfThousand(thns) .o.
SeparatePowerOfThousand(mlns) .o.
SeparatePowerOfThousand(blns) .o.
SeparatePowerOfThousand(tlns) .o.
RemoveSilentGroups .o.
SeparateHundreds .o.
SeparateTens .o.
#MarkOrdPowerOfThousand .o.
MarkTeens .o.
RemoveZeros .o.
PowerOfThousandSymbolsToSingular .o.
preTranslate .o.
RemoveOnes .o.
processOrdinals
.o. [%.|%,|wnum] -> нула ... || .#. _ # hack to replace lost zero in front of dec. point
.o. Translate .o. [ [ord OrdSuffix]:0 -> || wnum _ .#. ]
.o. [dp:0|dec:0|wnum:0] -> || _;
# Thousand should be replaced with thousands after 21, 31, etc
define replaceOneThousand
[једна хиљаду] -> [једна хиљада] || _ ;
source romans.foma
regex ConvertRomanToDecimal .o. ArabicNumber .o. tagRules .o. NumberRules .o. replaceOneThousand ;