summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2018-09-10 16:56:05 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2018-09-10 16:56:05 +0000
commitead869df267c16632109f2a9120d67f91a38504a (patch)
tree66c0c9d9f3b97b9b5de23265e03675189e0e3620
parentInitial commit. (diff)
downloadlibnumbertext-ead869df267c16632109f2a9120d67f91a38504a.zip
libnumbertext-ead869df267c16632109f2a9120d67f91a38504a.tar.xz
Adding upstream version 1.0~beta2.upstream/1.0_beta2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
-rw-r--r--AUTHORS222
-rw-r--r--CalcAddIn.xcu141
-rw-r--r--ChangeLog470
-rw-r--r--META-INF/manifest.xml14
-rw-r--r--Makefile.am8
-rw-r--r--Makefile.orig25
-rw-r--r--NEWS206
-rw-r--r--README154
-rw-r--r--THANKS5
-rw-r--r--VERSION1
-rw-r--r--bin/Convert.py7
-rw-r--r--bin/ConvertTitles.py15
-rw-r--r--bin/locales.py5
-rwxr-xr-xbin/places.sh5
-rwxr-xr-xbin/shellhtml8
-rw-r--r--configure.ac85
-rw-r--r--data/Hung.sor44
-rw-r--r--data/Makefile.am3
-rw-r--r--data/Roman.sor38
-rw-r--r--data/Suzhou.sor39
-rw-r--r--data/af.sor111
-rw-r--r--data/ca.sor189
-rw-r--r--data/cs.sor137
-rw-r--r--data/da.sor120
-rw-r--r--data/de.sor103
-rw-r--r--data/el.sor218
-rw-r--r--data/en.sor210
-rw-r--r--data/eo.sor73
-rw-r--r--data/es.sor203
-rw-r--r--data/fi.sor146
-rw-r--r--data/fr.sor162
-rw-r--r--data/he.sor214
-rw-r--r--data/hr.sor186
-rw-r--r--data/hu.sor175
-rw-r--r--data/id.sor122
-rw-r--r--data/it.sor148
-rw-r--r--data/ja.sor98
-rw-r--r--data/ko.sor55
-rw-r--r--data/lb.sor118
-rw-r--r--data/lt.sor171
-rw-r--r--data/lv.sor121
-rw-r--r--data/ms.sor122
-rw-r--r--data/nl.sor103
-rw-r--r--data/pl.sor141
-rw-r--r--data/pt.sor193
-rw-r--r--data/ro.sor126
-rw-r--r--data/ru.sor112
-rw-r--r--data/sh.sor108
-rw-r--r--data/sl.sor98
-rw-r--r--data/sr.sor108
-rw-r--r--data/sv.sor144
-rw-r--r--data/th.sor73
-rw-r--r--data/tr.sor138
-rw-r--r--data/vi.sor43
-rw-r--r--data/zh.sor171
-rw-r--r--description.xml.in27
-rw-r--r--doc/Tutorial_1.sor116
-rw-r--r--doc/Tutorial_2.sor193
-rw-r--r--doc/Tutorial_3.sor94
-rw-r--r--doc/Tutorial_4.sor191
-rw-r--r--doc/Tutorial_5.sor378
-rw-r--r--doc/addnewlocale.txt21
-rw-r--r--doc/format.txt7
-rw-r--r--doc/numbertext.odtbin0 -> 31043 bytes
-rw-r--r--doc/numbertext.pdfbin0 -> 105654 bytes
-rw-r--r--doc/sorosspec.odtbin0 -> 30610 bytes
-rw-r--r--doc/sorosspec.pdfbin0 -> 112182 bytes
-rw-r--r--idl/XNumberText.idl28
-rw-r--r--idl/XNumberText.urdbin0 -> 8192 bytes
-rwxr-xr-xidl/buildrdb.sh7
-rw-r--r--java/Makefile10
-rw-r--r--java/Manifest.txt3
-rw-r--r--java/org/numbertext/Numbertext.java101
-rw-r--r--java/org/numbertext/Soros.java127
-rw-r--r--libnumbertext.pc.in15
-rw-r--r--m4/boost.m41574
-rw-r--r--pkg-desc/pkg-description.txt16
-rw-r--r--pythonpath/Makefile22
-rw-r--r--pythonpath/org/Numbertext/__init__.py129
-rw-r--r--pythonpath/org/__init__.py0
-rw-r--r--rdb/sample.rdbbin0 -> 8192 bytes
-rw-r--r--reg.uno.py14
-rw-r--r--src/Makefile.am20
-rw-r--r--src/Numbertext.cxx110
-rw-r--r--src/Numbertext.hxx29
-rw-r--r--src/Soros.cxx212
-rw-r--r--src/Soros.hxx48
-rw-r--r--src/Soros.js131
-rw-r--r--src/Soros.py119
-rw-r--r--src/numbertext-version.h.in9
-rw-r--r--src/places.py121
-rw-r--r--src/soroside.py55
-rw-r--r--src/spellout.cxx118
-rw-r--r--test/Makefile5
-rwxr-xr-xtest/test12
-rw-r--r--test/test.py23
-rwxr-xr-xtest/test.sh12
-rwxr-xr-xtest/test0.test13
-rw-r--r--test/test1.in24
-rw-r--r--test/test1.out24
-rw-r--r--test/test1.sor39
-rwxr-xr-xtest/test1.test4
-rw-r--r--test/test2.in2
-rw-r--r--test/test2.out2
-rw-r--r--test/test2.sor2
-rwxr-xr-xtest/test2.test4
-rw-r--r--test/test3.in7
-rw-r--r--test/test3.out7
-rw-r--r--test/test3.sor43
-rwxr-xr-xtest/test3.test4
-rw-r--r--test/test4.in3
-rw-r--r--test/test4.out3
-rw-r--r--test/test4.sor11
-rwxr-xr-xtest/test4.test4
-rw-r--r--test/test5.in2
-rw-r--r--test/test5.out2
-rw-r--r--test/test5.sor7
-rwxr-xr-xtest/test5.test4
-rw-r--r--test/test6.in1
-rw-r--r--test/test6.out1
-rw-r--r--test/test6.sor3
-rwxr-xr-xtest/test6.test4
-rw-r--r--test/test7.in4
-rw-r--r--test/test7.out4
-rw-r--r--test/test7.sor16
-rwxr-xr-xtest/test7.test4
-rw-r--r--test/thaicheck.odsbin0 -> 55380 bytes
-rw-r--r--web/AUTHORS.html.in16
-rw-r--r--web/Makefile8
-rw-r--r--web/Soros.html.in129
-rw-r--r--web/index.html.in482
-rw-r--r--web/webroot/css/numbertext.css108
-rw-r--r--web/webroot/favicon.icobin0 -> 1406 bytes
-rw-r--r--web/webroot/fonts/fonts/Hung.ttfbin0 -> 4324 bytes
134 files changed, 11343 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..b460109
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,222 @@
+Authors and contributors of NUMBERTEXT/MONEYTEXT development
+
+= Developer =
+
+László Németh (nemeth at numbertext dot org):
+
+ - Soros programming language and its interpreters
+
+ - several language modules
+
+= Language module developers =
+
+Alex Bodnaru (alexbodn at 012 dot net dot il):
+
+ - author of Hebrew module (he_IL)
+
+Eduardo Moreno (emoreno at tokonhu dot com):
+
+ - author of the first version of the Portuguese module (pt-PT)
+
+ - bug reports about Spanish module and short language code "es"
+
+Eko Prasetiyo (ekoprasetiyo at gmail):
+ - author of Indonesian module
+
+Goran Rakić (grakic at devbase dot net):
+
+ - author of Serbian modules (sh-RS, sr-RS)
+
+Randem:
+ - author of Turkish module (tr)
+
+Olivier Ronez:
+
+ - patches for French language module (fr-FR):
+
+ - Spelling mistakes in the French file (https://bugs.launchpad.net/numbertext/+bug/419718)
+ - 81 in French (https://bugs.launchpad.net/numbertext/+bug/419729)
+ - milliard etc. instead of *milliarde (https://bugs.launchpad.net/numbertext/+bug/419718)
+
+ - author of Belgian and Swiss French modules (fr-BE and fr-CH):
+
+ - French numbers in Belgium (https://bugs.launchpad.net/numbertext/+bug/419731)
+ - French numbers in Switzerland (https://bugs.launchpad.net/numbertext/+bug/419734)
+
+Mihovil Stanić (mihovil dot stanic at gmail dot com):
+
+ - author of Croation module (hr)
+
+Michel Weimerskirch (michel at weimerskirch dot net):
+
+ - author of Luxembourgish module (lb-LU)
+
+= Contributors =
+
+Liudas Ališauskas (liudas dot alisauskas at gmail dot com):
+ - fix Lithuanian money handling
+
+Mushtaque Asghar:
+
+ - bug report about missing XLS portability in
+ http://extensions.services.openoffice.org/project/numbertext
+
+Asterisks at OOo Wiki:
+
+ - Latvian module
+
+Attilafdd at launchpad dot net:
+
+ - fix Italian comma in it_IT module ("virgula" instead of "komma").
+
+Ruud Baars:
+
+ - bug reports about Dutch module
+
+Claudio Colombo (claudio underline c77 at yahoo dot it):
+
+ - it_IT bug report ("*unocento")
+
+Dániel Darabos:
+
+ - suggested __import__ for simple lazy loading in PyUNO implementation
+ of OpenOffice.org NUMBERTEXT extension
+
+Susana Sotelo Docío:
+
+ - fix for numbers containing the string "ientos" (doscientos/as,
+ quinientos/as, novecientos/as, etc) in Spanish module
+
+Sophie Gautier:
+
+ - bug report for French: milliard etc. instead of *milliarde
+
+georgepyh at OOo extension:
+
+ - bug report for Russian
+
+Lucian Adrian Grijincu (lucian dot grijincu at gmail):
+
+ - reported missing gender support in Romanian MONEYTEXT implementation:
+ https://bugs.launchpad.net/bugs/421309)
+
+Jmzambon at OOO Wiki:
+
+ - patch for French un/une handling for currencies
+
+Kent Karlsson:
+
+ - reported Swedish gender problem with currencies in sv_SE.sor.
+
+Mantas Kriaučiūnas at Launchpad.net:
+
+ - hints for Lithuanian module
+
+mike8p at launchpad.net:
+
+ - Spanish module: bug report for y dos cents -> con dos céntimos
+
+Marcin Miłkowski (milek_pl at o2 dot pl):
+
+ - patch for Polish: https://bugs.launchpad.net/numbertext/+bug/421031:
+ - correct special affixation of number names after 2, 3 and 4
+
+Petr Mladek:
+
+ - bug report about document language detection in OOo 3.2
+
+Joan Montané (jmontane at openoffice dot org):
+
+ - patch for Catalan (http://wiki.services.openoffice.org/wiki/Talk:NUMBERTEXT/MONEYTEXT_development#Some_fixes_on_Catalan_definition):
+ - "amb" instead of "und"
+ - "cèntim" instead of (euro)cent
+ - "menys" for negative
+
+ - reported missing gender support for Catalan and Spanish (http://wiki.services.openoffice.org/wiki/Talk:NUMBERTEXT/MONEYTEXT_development#Some_languages_need_male.2Ffemale_option_for_number_to_text)
+
+ - various fixes and extensions for Catalan
+
+Julien2412 (serval2412 at yahoo dot fr):
+
+ - bug report and initial patches in Python 3 port (tabulator inconsistency, terminating white spaces)
+
+Bernard Marcelly (bmarcelly at openoffice dot org):
+
+ - bug report for French (http://wiki.services.openoffice.org/wiki/Talk:NUMBERTEXT/MONEYTEXT_development#French_numbering_remarks):
+ - syntax of decimals
+ - cent instead of un cent
+ - milliard etc. instead of *milliarde
+ - "et" instead of "y"
+ - virgule instead of comma
+ - point instead of comma in fr-CH
+ - "moins" instead of "négatif de"
+
+ - bug report about missing conversion beetween 0 and 1
+
+Jerzy Moruś (morchat at o2 dot pl):
+
+ - Polish translation of NUMBERTEXT/MONEYTEXT
+
+mrw at OOo Extension site:
+
+ - bug report about document language detection in OOo 3.2
+
+Stephan Nilsson (Stephan at Nilsson dot tf):
+ - sv_SE bug report: the Swedish 7 is "sju", not *sjo
+
+Nicolas Pagni (Nicolas dot Pagni at npagni dot it):
+
+ - bug report about the bad conversion of 1 eurocent in the Italian module
+
+Gwenaël Quenette (g_quenette at yahoo dot fr):
+
+ - bug report for the Portuguese module: cientos -> centos
+
+Eike Rathke (er at OpenOffice dot org):
+
+ - suggested new namespace and compatibility name usage.
+
+rogerclc at OOo extesion site:
+
+ - bug report about Russian MONEYTEXT conversion (russian grammar)
+
+Johanna Sørensen:
+
+ - bug report about "Dansk" language name on Numbertext.org home page
+
+Marcin Stępniak:
+
+ - patch to set default UTF-8 encoding in numbertext.jar
+
+Supapong at OOo Wiki:
+
+ - bug report about Thai numbers ending with "01" (Excel BAHTTEXT bug)
+
+Kálmán Szalai (Kami):
+
+ - ooo-build integration of Numbertext OpenOffice.org extension
+
+Tantai Thanakanok (tantai osdev co th):
+
+ - patch for extended Thai decimal support (1 and more than 2 digits with currencies)
+
+xhydrogene at launchpad dot net:
+
+ - bug reports for French (fr_FR) module:
+
+ - "comma" must be translated in french "virgule" (https://bugs.launchpad.net/numbertext/+bug/421148)
+ - "y" must be translated in french "et" (https://bugs.launchpad.net/numbertext/+bug/421151)
+ - "un mille" must be writed only "mille" in french (https://bugs.launchpad.net/numbertext/+bug/421164)
+
+Laimonas Vėbra (laimis) at LaunchPad:
+
+ - hints for Lithuanian module
+
+wasow at extensions openoffice org:
+
+ - bug report and patch (+UAH) to the Russian module
+
+Friedel Wolff (friedel at translate dot org dot za):
+
+ - bug report for Africaans module
+
diff --git a/CalcAddIn.xcu b/CalcAddIn.xcu
new file mode 100644
index 0000000..be61a3a
--- /dev/null
+++ b/CalcAddIn.xcu
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<oor:component-data xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" oor:name="CalcAddIns" oor:package="org.openoffice.Office">
+<node oor:name="AddInInfo">
+<node oor:name="org.numbertext" oor:op="replace">
+<node oor:name="AddInFunctions">
+ <node oor:name="numbertext" oor:op="replace">
+ <prop oor:name="DisplayName"><value xml:lang="en">NUMBERTEXT</value></prop>
+ <prop oor:name="Description">
+ <value xml:lang="en">Converts number to number name.</value>
+ <value xml:lang="pl">Przekształca liczbę na postać słowną. Część ułamkowa wymieniana jest jako kolejne cyfry.</value>
+ <value xml:lang="fr">Convertit un nombre en texte.</value>
+ <value xml:lang="hu">Számot számnévvé alakít.</value>
+ <value xml:lang="sr">Исписује број словима.</value>
+ <value xml:lang="sh">Ispisuje broj slovima.</value>
+ <value xml:lang="he">ממיר מספר לייצוגו במילים.</value>
+ </prop>
+ <prop oor:name="Category"><value>Add-In</value></prop>
+ <prop oor:name="CompatibilityName"><value xml:lang="en">org.NUMBERTEXT.numbertext</value></prop>
+ <node oor:name="Parameters">
+ <node oor:name="num" oor:op="replace">
+ <prop oor:name="DisplayName">
+ <value xml:lang="en">Number</value>
+ <value xml:lang="pl">Liczba</value>
+ <value xml:lang="fr">Nombre</value>
+ <value xml:lang="hu">Szám</value>
+ <value xml:lang="sr">Број</value>
+ <value xml:lang="sh">Broj</value>
+ <value xml:lang="he">מספר</value>
+ </prop>
+ <prop oor:name="Description">
+ <value xml:lang="en">Value.</value>
+ <value xml:lang="pl">Wartość.</value>
+ <value xml:lang="fr">Valeur.</value>
+ <value xml:lang="hu">Az átalakítandó szám.</value>
+ <value xml:lang="sr">Вредност.</value>
+ <value xml:lang="sh">Vrednost.</value>
+ <value xml:lang="sh">ערך קלט.</value>
+ </prop>
+ </node>
+ <node oor:name="lang" oor:op="replace">
+ <prop oor:name="DisplayName">
+ <value xml:lang="en">Language</value>
+ <value xml:lang="pl">Język</value>
+ <value xml:lang="fr">Langue</value>
+ <value xml:lang="hu">Nyelv</value>
+ <value xml:lang="sr">Језик</value>
+ <value xml:lang="sh">Jezik</value>
+ <value xml:lang="he">שפה</value>
+ </prop>
+ <prop oor:name="Description">
+ <value xml:lang="en">Language code (eg. en-US).</value>
+ <value xml:lang="pl">Kod języka w jakim ma być podany rezultat (np. pl - polski, en - angielski, ru - rosyjski).</value>
+ <value xml:lang="fr">Code langue (exemple fr-BE).</value>
+ <value xml:lang="hu">Nyelvkód (pl. hu-HU).</value>
+ <value xml:lang="sr">Код језика (нпр. sr или sh).</value>
+ <value xml:lang="sh">Kod jezika (npr. sr ili sh).</value>
+ <value xml:lang="he">קוד שפה (כגון he-IL).</value>
+ </prop>
+ </node>
+ </node>
+ </node>
+ <node oor:name="moneytext" oor:op="replace">
+ <prop oor:name="DisplayName"><value xml:lang="en">MONEYTEXT</value></prop>
+ <prop oor:name="Description">
+ <value xml:lang="en">Converts a number to text with the given currency.</value>
+ <value xml:lang="pl">Przekształca liczbę na postac słowną z podaniem waluty. Uwzględnia dwa miejsca po przecinku po zaokrągleniu.</value>
+ <value xml:lang="fr">Convertit un nombre en texte avec la devise indiquée.</value>
+ <value xml:lang="hu">Számot számnévvé alakít a megadott pénznemmel.</value>
+ <value xml:lang="sr">Исписује број словима уз истицање ознаке валуте.</value>
+ <value xml:lang="sh">Ispisuje broj slovima uz isticanje oznake valute.</value>
+ <value xml:lang="he">ממיר מספר לייצוגו במילים עם המטבע הנתון.</value>
+ </prop>
+ <prop oor:name="Category"><value>Add-In</value></prop>
+ <prop oor:name="CompatibilityName"><value xml:lang="en">org.NUMBERTEXT.moneytext</value></prop>
+ <node oor:name="Parameters">
+ <node oor:name="num" oor:op="replace">
+ <prop oor:name="DisplayName">
+ <value xml:lang="en">Number</value>
+ <value xml:lang="pl">Liczba</value>
+ <value xml:lang="fr">Nombre</value>
+ <value xml:lang="hu">Szám</value>
+ <value xml:lang="sr">Број</value>
+ <value xml:lang="sh">Broj</value>
+ <value xml:lang="he">מספר</value>
+ </prop>
+ <prop oor:name="Description">
+ <value xml:lang="en">Input value.</value>
+ <value xml:lang="pl">Wartość przekształcana.</value>
+ <value xml:lang="fr">Valeur.</value>
+ <value xml:lang="hu">Az átalakítandó szám.</value>
+ <value xml:lang="sr">Улазна вредност.</value>
+ <value xml:lang="sh">Ulazna vrednost.</value>
+ <value xml:lang="sh">ערך קלט.</value>
+ </prop>
+ </node>
+ <node oor:name="currency" oor:op="replace">
+ <prop oor:name="DisplayName">
+ <value xml:lang="en">Currency/function</value>
+ <value xml:lang="pl">Waluta</value>
+ <value xml:lang="fr">Devise</value>
+ <value xml:lang="hu">Pénznem/függvény</value>
+ <value xml:lang="sr">Валута</value>
+ <value xml:lang="sh">Valuta</value>
+ <value xml:lang="he">מטבע</value>
+ </prop>
+ <prop oor:name="Description">
+ <value xml:lang="en">ISO 4217 code (eg. USD) or Numbertext function (eg. ord = ordinal number).</value>
+ <value xml:lang="pl">Kod waluty wg ISO 4217 zapisany wersalikami (tak jak w bankach, PLN - dla Polski, XXX - bez waluty).</value>
+ <value xml:lang="fr">Code ISO 4217 (exemple EUR).</value>
+ <value xml:lang="hu">ISO 4217 kód (pl. HUF) vagy Numbertext függvény (pl. ord = sorszám).</value>
+ <value xml:lang="sr">ISO 4217 код (нпр. RSD).</value>
+ <value xml:lang="sh">ISO 4217 kod (npr. RSD).</value>
+ <value xml:lang="he">קוד ISO 4217 (כגון ILS).</value>
+ </prop>
+ </node>
+ <node oor:name="lang" oor:op="replace">
+ <prop oor:name="DisplayName">
+ <value xml:lang="en">Language</value>
+ <value xml:lang="pl">Język</value>
+ <value xml:lang="fr">Langue</value>
+ <value xml:lang="hu">Nyelv</value>
+ <value xml:lang="sr">Језик</value>
+ <value xml:lang="sh">Jezik</value>
+ <value xml:lang="he">שפה</value>
+ </prop>
+ <prop oor:name="Description">
+ <value xml:lang="en">Language code (eg. en-US).</value>
+ <value xml:lang="pl">Kod języka w jakim ma być podany rezultat (np. pl - polski, en - angielski, ru - rosyjski).</value>
+ <value xml:lang="fr">Code langue (exemple fr-BE).</value>
+ <value xml:lang="hu">Nyelvkód (pl. hu-HU).</value>
+ <value xml:lang="sr">Код језика (нпр. sr или sh).</value>
+ <value xml:lang="sh">Kod jezika (npr. sr ili sh).</value>
+ <value xml:lang="he">קוד שפה (כגון he-IL).</value>
+ </prop>
+ </node>
+ </node>
+ </node>
+</node>
+</node>
+</node>
+</oor:component-data>
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..a903535
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,470 @@
+2018-04-26: László Németh (nemeth numbertext org):
+ * rename numbertext executable to spellout,
+ add default data path: /usr/share/numbertext
+ and support environmental variable NUMBERTEXTPATH
+ * fix platform incompabilities
+ * Greek cardinal and ordinal genders
+
+2018-04-19: László Németh (nemeth numbertext org):
+ * Soros programming language: revised draft:
+ - conditional text, prefix macros, language
+ variant program lines
+ * improved interpreters
+ * C++11 port
+ * language data:
+ - More functions:
+ ordinal numbers (prefix: ordinal)
+ ordinal indicator (prefix: ordinal-number)
+ year (prefix: year)
+ gender variants and other functions
+ - list all functions of a module with the input "help"
+ (in Calc: =NUMBERTEXT("help"), but enlarge the
+ row height to see every line of the help text)
+ - new Malaysian and Swiss Standard German
+ - compressed language modules:
+ - instead of hu_HU_2, ja_JP_2, zh_ZH_2,
+ "formal" prefix allows formal number names here.
+ For example, MONEYTEXT(1200;"money HUF";"hu")
+ results "egyezerkettőszáz forint" instead of
+ "ezerkétszáz forint",
+ MONEYTEXT(123;"formal";"ja") results "参百弐拾壱"
+ instead of "三百二十一"
+ - instead of en_US_2, use "money" prefix combined
+ with currencies, eg. MONEYTEXT(1.01;"money USD")
+ results "one and 1/100 U.S. dollar" in LibreOffice
+ instead of "one U.S. dollar and one cent".
+
+2016-05-24: Liudas Ališauskas
+ * Fix Lithuanian module
+
+2014-05-10: Mihovil Stanić (mihovil.stanic gmail com):
+ * new Croatian module
+
+2013-03-16: Jerzy Moruś
+ * Polish translation of LibO extension resource data
+
+2012-12-06: László Németh (nemeth numbertext org):
+ * src/Soros.py, soroside.py, __init__.py, test.py:
+ Python 3 port (back compatible with Python 2)
+ * reg.uno.py, bin/*.py: initial patches for tabulator
+ inconsistency and terminating whitespaces in Python 3
+ reported by Julien2412 at libreoffice-dev.
+
+2012-10-09: László Németh (nemeth numbertext org):
+ * data/lt_LT.sor: Lithuanian module (hints by Mantas Kriaučiūnas
+ and Laimonas Vėbra (laimis) at LaunchPad #936205)
+
+ * data/fr_*: fix un/une + currency, based on the patch by
+ Jmzambon at OOO Wiki
+
+ * data/es_ES.sor: euro: y dos cents -> con dos céntimos, reported by
+ mike8p at launchpad.net
+
+ * data/pt_*.sor: ciento(s) -> cento(s), reported by Gwenaël Quenette
+ (sent by Zoltán Reizinger and Andrea Pescetti).
+
+ * java/: sources of the Java jar distribution
+
+2012-03-17: Asterisks at OOo Wiki:
+ * data/lv_LV.sor: Latvian module
+
+2010-11-03: László Németh (nemeth numbertext org):
+ * data/vi_VN.sor: new Vietnamese module
+ * data/ru_RU.sor:
+ - fix for 2 (subunits of EUR, GBP, USD),
+ - add currency UAH, reports and patch by wasow at extensions ooo
+
+2010-08-03: László Németh (nemeth numbertext org):
+ * pythonpath/org/Numbertext/__init__.py: fix rounding differences
+ between Calc and Numbertext functions: rounding by Calc round()
+ in Python code of Numbertext. The problem was reported by
+ Bernard Marcelly on Numbertext OOo Wiki page.
+
+ * data/{el,en,es,fr,pt,tr}*.sor, : remove "zero cents" etc. from
+ Moneytext output, reported by Bernard Marcelly.
+
+ * data/{af,sv,tr}*.sor: add missing zero to Moneytext (eg. "nul rand")
+
+2010-08-03: Eko Prasetiyo (ekoprasetiyo at gmail):
+ * data/id_ID.sor: Indonesian module
+
+2010-06-07: László Németh (nemeth numbertext org):
+ * data/ru_RU.sor: fix bad back references in Russian rules. Missing
+ conversion reported by Birioukoff at OOo Extension site.
+
+2010-05-28: László Németh (nemeth numbertext org):
+ * data/en_IN.sor: Indian numbering system. Lakh = 100.000, crore =
+ 10.000.000 (requested by Dhandip at OOo Extensions site).
+
+ * data/ca_ES.sor: fix Catalan MONEYTEXT in Calc Numbertext extension
+ (Launchpad bug 585782 reported by Bernard Marcelly).
+
+ * data/en_US.sor, hu_HU.sor: fix 0th
+
+ * data/sv_SE.sor: fix 0th, 100th, 1000th
+
+ * data/fr_*.sor: fix ordinal numbers
+
+ * doc/*odt: modifications: DollarText/BAHTTEXT field formatters of
+ MS Office and ECMA-376, Unicode CLDR, corrections for RBNF,
+ BSD license for example Python and Java interpreters
+
+2010-05-20: László Németh (nemeth numbertext org):
+ * data/sv_SE.sor:
+ - fix 30 (trettio)
+ - reference implementation with grammar and year support,
+ also with gender parameters for currencies. Gender problem
+ with currencies reported by Kent Karlsson in CLDR ticket 2783
+
+ * data/Roman.sor:
+ - replaced with the more compact Roman_2.sor
+ - replace "(" and ")" with "\(" and "\)" (parenthesized numerals)
+
+ * data/Roman_2.sor:
+ - variant with overline and bars
+ - extra functions: historical with the special Unicode characters for
+ 1000, 5000 and 10000
+
+ * src/Soros.js:
+ - fix character encoding for \(, \) etc.
+
+2010-04-26: László Németh (nemeth numbertext org):
+ * data/fr_*: ordf and ordm instead of ord-fem and ord-mas
+
+ * data/ru_RU.sor: fix bugs reported by georgepyh on OOo Extension site
+
+ * description.xml, CalcAddIn.xcu: add French translation by
+ Bernard Marcelly.
+
+ * data/he_IL.sor: [^0] -> [1-9], modify function names for MONEYTEXT
+
+ * src/soroside.py: rename soros.py, suggested by Alex Bodnaru
+
+2010-04-26: Alex Bodnaru (alexbodn at 012 dot net dot il):
+ * data/he_IL.sor:
+ - add ordinal numbers (ord, ordf, ordm functions)
+ - restructuring currencies, etc.
+
+2010-04-22: László Németh (nemeth numbertext org):
+ * data/sv_SE.sor: fix Swedish 11000 (elvatusen instead of elvausen)
+
+ * data/{he_IL,pl_PL,ru_RU}.sor: replace the complementer bracket
+ expressions (eg. [^1]) to non-complementers (eg. [02-9]). The
+ problem with the Polish Moneytext reported by geo78 at OOo Extensions.
+
+ * src/soros.py: extended syntax: range with steps by tilde (0-100~10)
+
+ * data/fr_FR.sor: add ordinal numbers (ord, ord-fem, ord-mas):
+ =MONEYTEXT(5;"ord";"fr") -> cinquième
+ =MONEYTEXT(1;"ord-fem";"fr") -> première
+ =MONEYTEXT(1;"ord-mas";"fr") -> premier
+
+ * data/th_TH.sor: add ordinal numbers (ord)
+
+2010-04-19: László Németh (nemeth numbertext org):
+ * pythonpath/org/__init__.py:
+ - remove Asian and CTL lang. detection temporarily (problems with
+ document language detection in OOo 3.0 reported by Petr Mladek and
+ mrw at OOo Extension site);
+
+ - now MONEYTEXT handles unknown currency codes/new function names.
+
+ Example:
+
+ = MONEYTEXT(num, "ord", "en") -> ordinal names
+ = MONEYTEXT(num, "ord2", "en") -> ordinal abbreviations (1st, 2nd etc.)
+
+ Problems with unknown currency codes reported by Bernard Marcelly.
+
+ * src/Soros.{py,js}: fix broken $n|$ = $n||$ equivalence (it worked only
+ for parenthesized form: $(...)|$... = $(...)||$...)
+
+ * src/Soros.py: fix output encoding of \$, \(, \), \|
+
+ * data/{de_DE, hu_HU, hu_HU_2}.sor:
+ - function ord for ordinal numbers
+ - function help for help
+
+ * data/{en_US, en_US_2}.sor:
+ - function ord for ordinal numbers
+ - function ord2 for ordinal abbreaviations (1st, 2nd, 3rd, 4th etc.)
+ - function help for help
+
+ * data/hu_HU_2.sor: formal Hungarian rules (eg. egyezeregyszáz)
+
+ * data/ru_RU.sor: grammatical fixes for Russian money amounts
+ (problems reported by rogerclc on OOo extension site):
+ – for numbers ending in 1 that are not 'teens':
+ (1, 21, 31, 41, 101, 121, etc.): roubles = рубль; kopeks = копейка
+ – for all numbers ending in 1 in the kopeks column (.01, .21, etc):
+ one = одна, eg.
+ 21.00 = двадцать один *рубль*
+ 21.01 = двадцать один *рубль одна* копейка
+ 21.21 = двадцать один *рубль* двадцать *одна копейка*
+
+ * data/th_TH.sor: fix number 1 in 201, 5001 etc.
+ 1 is เอ็ด in all numbers greater than 1 (หนึ่ง).
+ This is an old Excel bug revived in OOo, too (see OOo Issue 83490),
+ reported by Supapong at OOo Numbertext Wiki.
+
+ * data/fr_*.sor: add XPF (franc Pacifique), missing monetary
+ unit reported by Bernard Marcelly.
+
+ * src/places.py: add RON, problem with the new Romanian monetary unit
+ reported by Bernard Marcelly.
+
+2010-04-13: Alex Bodnaru (alexbodn at 012 dot net dot il):
+ * data/he_IL.sor: Hebrew module
+
+ * Makefile(s): add better clean
+
+2009-11-13: László Németh (nemeth numbertext org):
+ * data/{af_ZA,it_IT,nl_NL}.sor: fix bad conversion of
+ 1 subunit of currencies. The bug in the Italian module reported by
+ Nicolas Pagni (Nicolas dot Pagni at npagni dot it)
+
+ * data/sv_SE.sor: the Swedish 7 is "sju", not *sjo,
+ reported by Stephan Nilsson (Stephan at Nilsson dot tf)
+
+2009-11-11: Tantai Thanakanok (tantai osdev co th):
+ * data/th_TH.sor: extended Thai decimal support for 1 and
+ more than 2 digits with currencies
+
+2009-11-10: László Németh (nemeth numbertext org):
+ * data/da_DK.sor: new Danish module
+
+ * data/ca_ES.sor, es_ES.sor, fr_*.sor: 0 euro (without plural),
+ reported by Bernard Marcelly
+
+ * data/sv_SE.sor: fix bad language code (*sv_SV.sor) and missing
+ plural form of krone. Reported by Bernard Marcelly.
+
+ * data/fr_*.sor: "moins" for negative. Reported by Bernard
+ Marcelly.
+
+ * data/tr_TR.sor: add space removing, fix large numbers
+
+ * src/Soros.{py,js}: replace bad [^0] pattern with [1-9] in the
+ __numbertext__ directive implementation. Missing decimals leading by
+ zero reported by Bernard Marcelly.
+ * doc/sorosspec.odt: replace bad [^0] pattern with [1-9].
+
+2009-09-25: Susana Sotelo Docío (Roebek at OpenOffice.org Wiki):
+ * data/es_ES.sor: gender fix for numbers containing the string "ientos"
+ (doscientos/as, quinientos/as, novecientos/as, etc)
+
+2009-09-12: Ramdem at OpenOffice.org Wiki:
+ * data/tr_TR.sor: new Turkish module
+
+2009-09-06: Joan Montané:
+ * data/ca_ES.sor: fixes
+ - "1000-1999" must be spelled only "mil ...", it can't be spelled "un mil" (the same fixed French bug)
+ - decimal units for EUR changed from "cent" to "cèntim", as it's usual and accepted
+ - decimal units for USD changed form "cent" to "centau", as it's usual and accepted
+ - millions are spelled as in French:
+ EUR 1000000 --> un milió d'euros (note the " de/d' " preposition")
+ EUR 1000001 --> un milió un euros (it lacks " de/d' " preposition).
+ EUR 1000000,xx --> un milió d'euros amb xx cèntims
+ EUR 1000001,xx --> un milió un euros amb xx cèntims
+
+ Improvements:
+ - Added all the currencies replaced by EUR
+ - Added all the actives code beginning by A (I'm working in B-Z)
+ - Added some actives codes beginning by X
+
+2009-09-04: László Németh (nemeth numbertext org):
+ * data/en_US*: fix English decimal conversion by replacing bad [^0]
+ (matched decimal separators, too) with "[1-9]", reported by
+ Bernard Marcelly (bmarcelly at openoffice dot org).
+
+2009-09-03: László Németh (nemeth numbertext org):
+ * pythonpath/org/Numbertext/__init__.py: add short language name support:
+ now module names works without country code or with bad or non-available
+ country and variant codes, too. The missing support of short languages
+ was reported by Eduardo Moreno, too.
+
+ * Makefile: target "ooo" for OOo extensions, first used in ooo-build
+ integration by Kálmán Szalai.
+
+ * ca_ES.sor, es_ES.sor, pt_PT.sor, pt_BR.sor, ro_RO.sor: add gender
+ support,
+ - ca_ES and es_ES bug fixes, reported by Joan Montané
+ - ro_RO bug fixes, reported by Lucian Adrian Grijincu
+
+ * data/af_ZA.sor, nl_NL.sor: extended decimal support, reported by
+ Friedel Wolff (friedel at translate dot org dot za)
+
+ * data/fr_FR.sor: bug fixes:
+
+ - extended and fixed decimal support, reported by
+ Bernard Marcelly (bmarcelly at openoffice dot org)
+
+ - using "et" instead of "y", reported by Bernard Marcelly and xhydrogene
+ at launchpad dot net (https://bugs.launchpad.net/numbertext/+bug/421151)
+
+ - virgule instead of comma, reported by Bernand Marcelly and xhydrogene
+ at launchpad dot net: https://bugs.launchpad.net/numbertext/+bug/421148,
+ also patch by Olivier Ronez
+
+ - cent and mille instead of un cent and un mille, reported by Bernand Marcelly and xhydrogene
+ at launchpad dot net: https://bugs.launchpad.net/numbertext/+bug/421164,
+ also patch by Olivier Ronez
+
+ * data/fr_CH.sor: decimal point instead of comma, reported by
+ Bernard Marcelly (bmarcelly at openoffice dot org)
+
+ * data/pl_PL.sor: add affix function and portable regexes, fix
+ regex problem reported by Marcin Miłkowski
+
+2009-08-30: Michel Weimerskirch (michel at weimerskirch dot net):
+ * data/lb_LU.sor: new Luxembourgish module
+
+2009-08-29 Marcin Miłkowski (milek_pl at o2 dot pl):
+ * data/pl_PL.sor: patch for Polish
+ https://bugs.launchpad.net/numbertext/+bug/421031
+
+2009-08-28: Goran Rakić (grakic at devbase dot net):
+ * CalcAddIn.xcu, description.xml: add Serbian localizations
+
+ * data/sh_RS.sor, data/sr_RS: new Serbian modules
+
+2009-08-27: Olivier Ronez:
+
+ * data/fr_BE.sor, data/fr_CH: patches for new modules
+
+ * data/fr_FR.aff: other patches:
+ - milliarde -> milliards (reported by Sophie Gautier and
+ Bernand Marcelly, too)
+ - fix for 81
+
+2009-08-27: Joan Montané (jmontane at openoffice dot org):
+
+ - data/ca_ES.sor: fixes
+
+ http://wiki.services.openoffice.org/wiki/Talk:NUMBERTEXT/MONEYTEXT_development#Some_fixes_on_Catalan_definition):
+ - "amb" instead of "und"
+ - "cèntim" instead of (euro)cent
+ - "menys" for negative
+
+2009-08-20: László Németh (nemeth numbertext org):
+ * data/ko*, ja*, Hang.sor: Korean, Japanese and Old Hungarian modules.
+
+ * data/en_US.*, hu_HU.sor: optimized by separator functions.
+
+ * web/webroot/Hung.ttf: TrueType font with Old Hungarian numbers and
+ some letters for the native name of the script (ROVÁSÍRÁS)
+
+ * web/*: new section (old number systems)
+
+ * data/it_IT.sor: Using "virgola" for comma, reported by
+ Attilafdd at launchpad.net.
+
+2009-08-10: László Németh (nemeth numbertext org):
+ * pythonpath/org/Numbertext/__init__.py: add missing Numbertext module
+
+ * bin/locales.py: fix registration of the first language module
+
+ * data/af_ZA.py: fix helper functions (space handling)
+
+2009-08-09: László Németh (nemeth numbertext org):
+ * numbertext.py: new namespace (incompatible with previous versions):
+ ORG.NUMBERTEXT.NUMBERTEXT() and ORG.NUMBERTEXT.MONEYTEXT(),
+ suggested by Eike Rathke (er at OOo).
+
+ * CalcAddIn.xcu: standard resource files for settings and
+ localizations (see Jan Holst Jensen's excellent Add-in example and
+ documentation: http://biochemfusion.com/doc/Calc_addin_howto.html)
+
+ * CalcAddIn.xcu: add compatibility names: working XLS export-import
+ (XLS portability bug reported by Mushtaque Asghar).
+
+ * numbertext.py: now NUMBERTEXT() has no default rounding:
+
+ =NUMBERTEXT(4.12345) -> four dot one two three four five
+ =NUMBERTEXT(4.00) -> four
+ =NUMBERTEXT("4.00") -> four dot zero zero
+
+ * numbertext.py: MONEYTEXT() supports not integer decimal places:
+ =MONEYTEXT(1.8, "MGA") -> one ariary and *four* iraimbilanja
+
+ * src/places.py: add MGA, MRO with decimal place 0.7
+ (eg. one ariary = 5 iraimbilanja, decimal places = 0.7 in places.py)
+
+ * doc/numbertext.odt: NUMBERTEXT specification 1.1:
+ - remove decimal place argument
+
+ * doc/sorosspec.odt:
+ - add number to Devanagari number example to the Soros specification;
+ - add Python implementation
+
+ * data/pt_PT.sor: Portuguese
+ - initial version from Eduardo Moreno (emoreno tokonhu com):
+ "Nombres en portugues de los números, con ayuda de Flavia Viegas".
+ - extension:
+ - simplification
+ - long scale support
+ - syntax of "e" based on Portuguese test data of PERL::Lingua Words2Nums
+ - extended with currency names of Portuguese speaking countries
+
+ * data/pt_BR.sor: Brazilian Portuguese
+ - based on pt-PT, but Brazilian Portuguese uses short scale numbers
+ and different ortography (number 16, 17, 19).
+
+ * data/af_ZA.sor: Africaans
+ - the orthography based on Bruce C. Donaldson: A grammar of Africaans,
+ MOUTON DE GRUYTER, 1993
+
+ * data/zh_ZH_2.sor: Simplified financial Chinese module.
+
+ * data/fr_FR.sor, data/en_US*.sor, data/es_ES.sor:
+
+ - extended currency names for English, French and Spanish modules
+
+ * data/*: - fixes for language data:
+
+ - Romanian, Swedish, Slovenian, Czech, etc.: fix decimals (.0n)
+
+ - Greek: removing unnecessary "de"
+
+ - Spanish: 21 (veintidós) -> 22, negativa - -> menos,
+ reported by Eduardo Moreno (emoreno tokonhu com).
+
+ - Italian: unucento -> cento, reported also by Claudio Colombo.
+
+ - Esperanto: unudek -> dek, unucent -> cent, miliono -> unu miliono.
+
+ * tests/test0*: test number 1-1000 in all languages (see make check).
+
+ * web/*: fix for IE, etc.
+
+2009-07-25: László Németh (nemeth numbertext org):
+ * data/*.sor: 11 new languages (see README)
+ - syntax and orthography based mostly on Wikipedia articles
+ - for Greek numerals, see Harry Foundalis' excellent introduction
+ (http://www.foundalis.com/lan/grknum.htm)
+
+ * numbertext.py: handling language variants (eg. en-US-2
+ for USD 20.25 -> twenty and 25/100 dollars)
+
+ * doc/sorosspec.odt: improved Soros language specification.
+
+ * Soros.js, pythonpath/Soros.py: standard Soros modules
+ in Python and JavaScript
+
+ * bin/*.py: new conversion utilities and more readable format using
+ standard Python doc string of the numbertext language modules.
+
+ * numbertext.py: fix for language codes without country ("eo", "Roman")
+
+ * data/*.sor: add function-like currency handling for language modules
+
+ * es_ES.sor: fix for Spanish "... y uno mil" -> "... y un mil".
+ The bug reported by Eduardo Moreno (emoreno tokonhu com).
+
+ * Roman*.sor: handle arbitrary large Roman numbers: 1000000000 -> ((M))
+
+ * test/*: testing environment and tests
+
+ * web/: web pages of http://numbertext.org
+
+ * bin/shellhtml: preprocessor tool for HTML, XML data
diff --git a/META-INF/manifest.xml b/META-INF/manifest.xml
new file mode 100644
index 0000000..679a9a5
--- /dev/null
+++ b/META-INF/manifest.xml
@@ -0,0 +1,14 @@
+<manifest:manifest>
+<manifest:file-entry
+ manifest:media-type="application/vnd.sun.star.uno-typelibrary;type=RDB"
+ manifest:full-path="rdb/sample.rdb"/>
+<manifest:file-entry
+ manifest:full-path="pkg-desc/pkg-description.txt"
+ manifest:media-type="application/vnd.sun.star.package-bundle-description"/>
+<manifest:file-entry
+ manifest:media-type="application/vnd.sun.star.configuration-data"
+ manifest:full-path="CalcAddIn.xcu"/>
+<manifest:file-entry
+ manifest:media-type="application/vnd.sun.star.uno-component;type=Python"
+ manifest:full-path="reg.uno.py"/>
+</manifest:manifest> \ No newline at end of file
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..27e570a
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,8 @@
+ACLOCAL_AMFLAGS = -I m4
+
+SUBDIRS = src data
+
+pkgconfdir = $(libdir)/pkgconfig
+pkgconf_DATA = libnumbertext.pc
+
+EXTRA_DIST = README data AUTHORS
diff --git a/Makefile.orig b/Makefile.orig
new file mode 100644
index 0000000..6dcbe31
--- /dev/null
+++ b/Makefile.orig
@@ -0,0 +1,25 @@
+all:
+ cd pythonpath; make
+ cat description.xml.in | bin/shellhtml >description.xml
+ cd web; make
+ cp src/Soros.py web/webroot
+ cp src/Soros.js web/webroot
+ cp doc/*.pdf web/webroot
+
+distx:
+ cd web; make clean
+ cd test; make clean
+ tar c . | gzip > ../numbertext-`head -1 VERSION`.tar.gz
+
+lo:
+ make -f Makefile.orig
+ zip -r numbertext-`head -1 VERSION`.oxt META-INF rdb idl pythonpath pkg-desc *.xcu *py *xml README
+
+check:
+ cd test; make
+
+clean:
+ rm -f *.oxt description.xml
+ cd pythonpath; make clean
+ cd web; make clean
+ rm -f *~ */*~
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..2fde7fd
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,206 @@
+2012-12-06: version 0.9.5 release 2
+ - Python 3 port of the OpenOffice.org/LibreOffice extension for LibreOffice 4.0
+
+2012-10-09: version 0.9.5
+ - new modules: Latvian, Lithuanian
+ - bug fixes: Spanish, French, Portuguese
+ - Java sources
+
+2010-11-03: version 0.9.4
+ - data/vi_VN.sor: new Vietnamese module
+
+ - numbertext.jar: patch to set default UTF-8 encoding by Marcin Stępniak
+
+ - Russian module:
+ - fix for 2 (subunits of EUR, GBP, USD),
+ - add currency UAH, reports and patch by wasow at extensions ooo
+
+2010-08-03: version 0.9.3
+ - fix rounding difference of Calc and Numbertext functions
+ - Indonesian module by Eko Prasetiyo
+ - remove "zero subunit" from Moneytext outputs of Greek, English,
+ French, Spanish, Portuguese and Turkish modules.
+ - fix missing zero in Afrikaans, Swedish and Turkish Moneytext
+ descriptions.
+
+2010-06-07: version 0.9.2
+ - fix Russian module
+
+2010-05-28: version 0.9.1
+ - new module: English with Indian numbering system (en-IN)
+ (lakh = 100.000, crore = 10.000.000)
+
+ - other fixes (see Changelog)
+
+2010-05-20: version 0.9
+ - reference implementation for Swedish:
+ - cardinal and ordinal numbers with gender
+ - ordinal abbreviations with gender
+ - year
+ - gender parameters at currencies
+
+ - reference implementation for Roman numerals:
+ Roman_2.sor: overlined with bars, also historical forms:
+
+ $ python soroside.py ../data/Roman_2.sor 38000
+
+ X̅X̅X̅V̅I̅I̅I̅
+
+ $ python soroside.py ../data/Roman_2.sor 30000000
+
+ |C̅C̅C̅|
+
+ $ python soroside.py ../data/Roman_2.sor -p historical 38000
+
+ ↂↂↂↁↀↀↀ
+
+2010-04-26: version 0.8.2
+ - fixes for Russian
+ - ordinal number support in Hebrew
+ - French translation
+
+2010-04-22: version 0.8.1
+ - bug fixes in Hebrew, Polish, Russian and Swedish modules
+
+ - ordinal numbers in French and Thai
+
+ - extended syntax in src/soroside.py tool (ranges with different steps):
+
+ $ python src/soroside.py data/en_US.sor 0-10~5
+ zero
+ five
+ ten
+
+2010-04-19: version 0.8
+ - new modules: he_HE from Alex Bodnaru, and hu_HU_2 (formal Hungarian)
+
+ - ordinal number functions in en_US, de_DE and hu_HU modules
+
+ - module fixes: th_TH, ru_RU
+
+ - new command line tool "soros.py", features:
+
+ - convert numbers and ranges:
+ $ python src/soroside.py data/en_US.sor 1 5-7 10
+ one
+ five
+ six
+ seven
+ ten
+
+ - prefix (function) support:
+ $ python src/soroside.py -p ord2 data/en_US.sor 1-4
+ 1st
+ 2nd
+ 3rd
+ 4th
+
+ - file output:
+ $ python src/soroside.py -o nums data/en_US.sor 100-200
+ $ head -3 nums
+ one hundred
+ one hundred and one
+ one hundred and two
+
+ - new convention: "help" item in some modules:
+ $ python src/soroside.py -o nums data/en_US.sor help
+ Functions:
+ ord (ordinal numbers, eg. "first")
+ ord2 (ordinal abbreviations, eg. "1st")
+ Extra modules:
+ en_US_2 (subunit as decimal fraction: "USD 20.25" -> twenty and 25/100 dollars)
+
+ - bug fixes:
+ - default Western language in calls without language parameter in OOo
+ - fix output conversion of \$, \(, \) and \|
+ - fix boundary recognition in $n|$() (only $()|$() was good in the
+ last versions)
+ - etc. (see ChangeLog)
+
+2009-11-13: version 0.7.1
+ - bug fixes (af_ZA, it_IT, nl_NL, th_TH), see ChangeLog
+
+2009-11-10: version 0.7
+ - new modules:
+ da-DK Danish from László Németh
+ tr-TR Turkish from Ramdem at OpenOffice.org Wiki
+
+ - bug fixes (see Changelog)
+
+2009-09-04: version 0.6.1
+ - fix English decimals
+
+2009-09-03: version 0.6
+ - new modules:
+ fr-BE Belgian French from Olivier Ronez
+ fr-CH Swiss French from Olivier Ronez
+ lb-LU Luxenbourgish from Michel Weimerskirch
+ sh-RS Serbian (Latin) from Goran Rakić
+ sr-RS Serbian (Cyrillic) from Goran Rakić
+
+ - short language code (language code without country code) support
+ in language code argument of NUMBERTEXT and MONEYTEXT functions
+
+ - using short language code (and an available module in the same
+ language) for missing language modules specified by long
+ language codes (language code + country code + optional variant name)
+
+ - fixes (see ChangeLog)
+
+2009-08-20: version 0.5
+ - new modules:
+ ja-JP Japanese
+ ja-JP-2 Japanese (formal)
+ ko-KP North-Korean
+ ko-KR South-Korean
+ Hung Old Hungarian Script
+
+ - web: add new modules and Chinese Suzhou numerals
+
+ - fixes
+
+2009-08-10: version 0.4
+ - fixes
+
+2009-08-09: version 0.3
+ - NUMBERTEXT and MONEYTEXT specification 1.1
+
+ - new language modules:
+
+ - Africaans
+ - financial Chinese (simplified)
+ - Portuguese
+ - Brazilian Portuguese
+
+ - extended currency support for English, French and Spanish
+
+ - Improved OpenOffice.org extension:
+
+ - MS Excel (XLS) export-import support
+ - standard XCU resource file for localization
+
+ - fixes
+
+2009-07-25: version 0.2
+
+ - 11 new languages: Catalan, Czech, Finnish, French, Greek,
+ Polish, Romanian, Russian, Slovenian, Spanish, Swedish.
+
+ - improved currency handling for all language modules
+
+ - new home page: http://NUMBERTEXT.org
+
+ - improved Soros language specification:
+ - left zero deletion, trimming and removing double spaces
+ switched on only by the new __numbertext__ directive
+ - nested recursive calls
+ - escaped metacharacters
+ - optional semicolon, as command separator
+ - in-line comments
+
+ - new Python and JavaScript Soros interpreters, testing environment
+
+ - NOTE: the syntax of the NUMBERTEXT and MONEYTEXT will be changed
+ in the next version, according to the new NUMBERTEXT/MONEYTEXT
+ specification (a new second argument, the number of the decimal places
+ will be added). See in OpenOffice.org Issue 103746.
diff --git a/README b/README
new file mode 100644
index 0000000..19aa212
--- /dev/null
+++ b/README
@@ -0,0 +1,154 @@
+Soros interpreters for C++11, Java, JavaScript and Python
+
+Language-neutral NUMBERTEXT and MONEYTEXT functions for LibreOffice Calc
+
+version 1.0 beta 2 (2018-04-26)
+
+Numbertext LibreOffice extension,
+Soros programming language specification (draft) and IDE*,
+Soros interpreter in Python: pythonpath/Soros.py,
+Soros interpreter in JavaScript: Soros.js*
+Soros interpreter in Java: see NUMBERTEXT.org
+
+* Not in LibreOffice Numbertext extension, see http://NUMBERTEXT.org.
+
+License: LGPL/BSD dual-license, 2009-2018 (C) László Németh (nemeth at numbertext dot org)
+
+Numbertext language data (Soros programs):
+
+LGPL/BSD dual-license, 2009-2018 (C) László Németh et al. (see AUTHORS)
+
+Serbian modules:
+
+CC/LGPL/BSD tri-license, 2009 (C) Goran Rakić (grakic at devbase dot net)
+
+* Note: for full distribution with specifications, IDE and JavaScript
+ implementation, see http://NUMBERTEXT.org
+
+Software distributed under the License is distributed on an "AS IS" basis,
+WITHOUT WARRANTY OF ANY KIND, either express or implied.
+
+= Supported languages in this version =
+
+af Africaans
+ca Catalan
+cs Czech
+da Danish
+de German
+de-CH Swiss Standard German orthography (dreissig instead of dreißig)
+de-LI Swiss Standard German orthography (dreissig instead of dreißig)
+el Greek
+en English (one hundred one)
+en-AU English (one hundred and one)
+en-GB English (one hundred and one)
+en-IE English (one hundred and one)
+en-IN English with Indian numbering system (lakh = 100.000, crore = 10^7)
+en-NZ English (one hundred and one)
+eo Esperanto
+es Spanish
+fi Finnish
+fr French
+fr-BE Belgian French
+fr-CH Swiss French
+he Hebrew
+hr Croatian
+hu Hungarian
+id Indonesian
+it Italian
+ja Japanese
+ko South-Korean
+ko-KP North-Korean
+lb Luxembourgish
+lt Lithuanian
+lv Latvian
+ms Malaysian
+nl Dutch
+pl Polish
+pt Brazilian Portuguese
+pt-PT Portuguese
+ro Romanian
+ru Russian
+sh Serbian (Latin)
+sl Slovenian
+sr Serbian (Cyrillic)
+sv Swedish
+th Thai
+tr Turkish
+vi Vietnamese
+zh Chinese (simplified)
+
+Old number systems:
+
+Hung Old Hungarian Script
+Roman Roman numbers
+Roman-large Roman numbers for very large numbers
+ using parenthesized syntax
+Suzhou Chinese Suzhou numerals
+
+= Build C++11 =
+
+autoreconf -i
+./configure
+make
+
+# test it
+
+src/spellout -l en 123
+
+= Build Java jar =
+
+cd java
+make
+
+= Build and using LibreOffice Extension =
+
+make -f Makefile lo
+
+and install the *.oxt package by
+Tools->Extension Manager->Add of LibreOffice.
+
+After restarting OpenOffice.org/LibreOffice, there are
+two new Calc functions,
+NUMBERTEXT() and MONEYTEXT().
+
+Examples:
+
+=NUMBERTEXT(25)
+=NUMBERTEXT(25;"th-TH")
+=MONEYTEXT(25)
+=MONEYTEXT(25;"USD")
+=MONEYTEXT(25;"CNY";"zh-ZH")
+
+Module Help (enlarge the row to see all lines), containing
+available prefix functions of the module:
+
+= NUMBERTEXT("help")
+= NUMBERTEXT("help";"de")
+
+= Development =
+
+See doc/addnewlocale.txt and doc/sorosspec.odt
+
+For general Calc and (portable Excel) Add-In developments, see
+Jan Holst Jensen's excellent Add-in example and documentation:
+
+http://biochemfusion.com/doc/Calc_addin_howto.html
+
+== Integrated development environment ==
+
+There is a JavaScript/HTML IDE in this distribution.
+
+Use the online version: http://numbertext.org/Soros.html or
+build it with
+
+make -f Makefile.orig
+
+and open web/webroot/Soros.html in a JavaScript capable browser,
+
+= Test =
+
+make -f Makefile.orig check
+
+test/thaicheck.ods is a simple test of the equivalence of
+the Soros implementation of Thai number to number name conversion
+and BAHTTEXT function.
diff --git a/THANKS b/THANKS
new file mode 100644
index 0000000..e817d08
--- /dev/null
+++ b/THANKS
@@ -0,0 +1,5 @@
+Thanks to NLnet Foundation, Nederland and FSF.hu Foundation, Hungary
+for their donation and support.
+
+Thanks to the contributors (see AUTHORS) and authors of Wikipedia
+and other articles and books about numerals
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..3ef69b3
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+1.0b2
diff --git a/bin/Convert.py b/bin/Convert.py
new file mode 100644
index 0000000..1aac6c5
--- /dev/null
+++ b/bin/Convert.py
@@ -0,0 +1,7 @@
+import sys
+f = open(sys.argv[1],'r')
+print ("# -*- encoding: UTF-8 -*-")
+print ("r\"\"\"")
+sys.stdout.writelines([i.strip() + '\n' for i in f.readlines()])
+print ("\"\"\"")
+print ("from __future__ import unicode_literals")
diff --git a/bin/ConvertTitles.py b/bin/ConvertTitles.py
new file mode 100644
index 0000000..d0a3e21
--- /dev/null
+++ b/bin/ConvertTitles.py
@@ -0,0 +1,15 @@
+import sys
+import re
+try:
+ unicode
+except:
+ unicode = lambda i, j: i
+
+f = open(sys.argv[1],'r')
+m = {}
+r2 = re.compile('"')
+for i in f.readlines():
+ a = unicode(i.strip(), "UTF-8").split("|", 1)
+ m[a[0]] = re.sub(r2, "", a[1])
+f.close()
+print ("titles = " + str(m))
diff --git a/bin/locales.py b/bin/locales.py
new file mode 100644
index 0000000..c92e66f
--- /dev/null
+++ b/bin/locales.py
@@ -0,0 +1,5 @@
+import sys
+print ("locales = \"\"\"")
+for i in sys.argv[1:]:
+ print i
+print ("\"\"\".strip().split(\"\\n\")")
diff --git a/bin/places.sh b/bin/places.sh
new file mode 100755
index 0000000..594ae93
--- /dev/null
+++ b/bin/places.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+# Extract language data for default decimal places from OpenOffice.org language resources
+$OODIR=$1
+#############
+cat `ls $OODIR/i18npool/source/localedata/data/*.xml | sort` | awk '/<Currency .*default/{if($0~/default=.true/)def=1;else def=0}{if(match($0,"<(CurrencyID|DecimalPlaces)>([^<]*)<",a)){b[a[1]]=a[2];if(a[1]=="DecimalPlaces")print "\"" b["CurrencyID"]"\":" a[2]}}' | sort | uniq | awk 'NR==1{printf "places = { %s", $0; next}{print ","; printf "%s", $0}END{print "}"}'>src/places.py
diff --git a/bin/shellhtml b/bin/shellhtml
new file mode 100755
index 0000000..ab530ee
--- /dev/null
+++ b/bin/shellhtml
@@ -0,0 +1,8 @@
+#!/bin/bash
+# HTML shell preprocessor
+# syntax: shell code in a HTML comment with leading exclamation mark
+# (in a new line, without leading and trailing whitespaces)
+# will be executed by the shell, and the result replaced with it.
+# For example, insert calendar:
+# <!--!cal-->
+awk '/^<!--!/{system(substr($0,6,length($0)-8)); next}{print}'
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..653fd00
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,85 @@
+m4_define([numbertext_version_major],[1])
+m4_define([numbertext_version_minor],[0])
+m4_define([numbertext_version_micro],[1])
+m4_define([numbertext_version],[numbertext_version_major.numbertext_version_minor.numbertext_version_micro-3])
+
+AC_PREREQ([2.68])
+
+AC_INIT([libnumbertext],[numbertext_version])
+AC_CONFIG_MACRO_DIR([m4])
+
+AM_INIT_AUTOMAKE([1.11 foreign dist-xz dist-bzip2])
+AM_MAINTAINER_MODE
+AC_CONFIG_HEADERS([src/config.h])
+AM_SILENT_RULES([yes])
+
+dnl Checks for programs.
+AC_PROG_CXX
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_LIBTOOL
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_LANG([C++])
+CXXFLAGS='-Wall -std=c++11'
+
+AC_CHECK_HEADERS([codecvt regex])
+
+#AS_IF([test "x$with_boost" != x], [
+# AC_DEFINE([BOOST_ALL_NO_LIB], [], [Disable boost autolink.])
+# BOOST_REQUIRE
+# BOOST_LOCALE
+# BOOST_REGEX
+#])
+
+AS_IF([test "x$ac_cv_header_codecvt" != xyes -o "x$ac_cv_header_regex" != xyes],
+ [
+# AS_IF([test "x$with_boost" == x], [
+ AC_MSG_ERROR([Missing std::codecvt or std::regex support, use GCC 4.9 (or greater) or --with-boost.])
+# ])
+])
+
+dnl Checks for functions
+
+# ================
+# Check for cflags
+# ================
+AC_ARG_ENABLE([werror],
+ [AS_HELP_STRING([--disable-werror], [Treat all warnings as errors, useful for development])],
+ [enable_werror="$enableval"],
+ [enable_werror=yes]
+)
+AS_IF([test x"$enable_werror" != "xno"], [
+ CFLAGS="$CFLAGS -Werror"
+ CXXFLAGS="$CXXFLAGS -Werror"
+])
+AS_IF([test x"$GCC" = xyes], [
+ # Be tough with warnings and produce less careless code
+ CFLAGS="$CFLAGS -Wall -pedantic"
+ CXXFLAGS="$CXXFLAGS -Wall -pedantic"
+])
+
+AC_SUBST([NUMBERTEXT_MAJOR_VERSION],[numbertext_version_major])
+AC_SUBST([NUMBERTEXT_MINOR_VERSION],[numbertext_version_minor])
+AC_SUBST([NUMBERTEXT_MICRO_VERSION],[numbertext_version_micro])
+AC_SUBST([NUMBERTEXT_VERSION],[numbertext_version])
+
+AC_CONFIG_FILES([
+libnumbertext.pc
+Makefile
+data/Makefile
+src/Makefile
+src/numbertext-version.h
+])
+AC_OUTPUT
+
+# ==============================================
+# Display final informations about configuration
+# ==============================================
+AC_MSG_NOTICE([
+==============================================================================
+Build configuration:
+ werror: ${enable_werror}
+==============================================================================
+])
diff --git a/data/Hung.sor b/data/Hung.sor
new file mode 100644
index 0000000..a72c6b1
--- /dev/null
+++ b/data/Hung.sor
@@ -0,0 +1,44 @@
+# Szekler-Hungarian Rovásírás (Old Hungarian, ISO 15924: Hung)
+1:(.*):(.*) \1
+2:(.*):(.*) \1\1
+3:(.*):(.*) \1\1\1
+4:(.*):(.*) \1\1\1\1
+5:(.*):(.*) \2
+6:(.*):(.*) \1\2
+7:(.*):(.*) \1\1\2
+8:(.*):(.*) \1\1\1\2
+9:(.*):(.*) \1\1\1\1\2
+
+(\d) $(\1:𐳺:𐳻)
+(\d)(\d) $2$(\1:𐳼:𐳽)
+1(\d\d) $1𐳾
+(\d)(\d\d) $2𐳾$1
+1(\d\d\d)$ $1𐳿
+(\d{1,3})(\d\d\d) $2𐳿$1
+1(\d{6})$ $1𐳿𐳿
+(\d{1,3})(\d{6}) $2𐳿𐳿$1
+1(\d{9})$ $1𐳿𐳿𐳿
+(\d{1,3})(\d{9}) $2𐳿𐳿𐳿$1
+
+== left-to-right ==
+
+1:(.*):(.*) \1
+2:(.*):(.*) \1\1
+3:(.*):(.*) \1\1\1
+4:(.*):(.*) \1\1\1\1
+5:(.*):(.*) \2
+6:(.*):(.*) \2\1
+7:(.*):(.*) \2\1\1
+8:(.*):(.*) \2\1\1\1
+9:(.*):(.*) \2\1\1\1\1
+
+(\d) $(left-to-right \1:𐳺:𐳻)
+(\d)(\d) $(left-to-right \1:𐳼:𐳽)$(left-to-right \2)
+1(\d\d) 𐳾$(left-to-right \1)
+(\d)(\d\d) $(left-to-right \1)𐳾$(left-to-right \2)
+1(\d\d\d)$ 𐳿$(left-to-right \1)
+(\d{1,3})(\d\d\d) $(left-to-right \1)𐳿$(left-to-right \2)
+1(\d{6})$ 𐳿𐳿$(left-to-right \1)
+(\d{1,3})(\d{6}) $(left-to-right \1)𐳿𐳿$(left-to-right \2)
+1(\d{9})$ 𐳿𐳿𐳿$(left-to-right \1)
+(\d{1,3})(\d{9}) $(left-to-right \1)𐳿𐳿𐳿$(left-to-right \2)
diff --git a/data/Makefile.am b/data/Makefile.am
new file mode 100644
index 0000000..5cd832c
--- /dev/null
+++ b/data/Makefile.am
@@ -0,0 +1,3 @@
+EXTRA_DIST = ${wildcard *.sor}
+
+pkgdata_DATA = ${wildcard *.sor}
diff --git a/data/Roman.sor b/data/Roman.sor
new file mode 100644
index 0000000..75b6096
--- /dev/null
+++ b/data/Roman.sor
@@ -0,0 +1,38 @@
+# Roman numbers
+1:(.)(.)(.) \1
+2:(.)(.)(.) \1\1
+3:(.)(.)(.) \1\1\1
+4:(.)(.)(.) \1\2
+5:(.)(.)(.) \2
+6:(.)(.)(.) \2\1
+7:(.)(.)(.) \2\1\1
+8:(.)(.)(.) \2\1\1\1
+9:(.)(.)(.) \1\3
+
+(\d) $(\1:IVX)
+(\d)(\d) $(\1:XLC)$2
+(\d)(\d\d) $(\1:CDM)$2
+
+([123])(\d\d\d) $(\1:Mxx)$2 # [:Roman-large:]
+(\d+)(\d\d\d) \($1\)$2 # [:Roman-large:]
+
+([123])(\d\d\d) $(\1:M--)$2
+([123]\d{3})(\d\d\d) $(overline $1)$2 # overline: ×1000
+(\d{1,3})(\d\d\d) $(overline $1)$2 # overline: ×1000
+([123]\d{3})(\d{5}) \|$(overline $1)\|$2 # bar: ×100
+(\d{1,3})(\d{5}) \|$(overline $1)\|$2
+(\d+) \1
+
+== overline ==
+
+(.*)(.) $(overline \1)\2̅ # recursive overline
+
+== historical ==
+
+(\d)(\d\d\d) $(\1:ↀↁↂ)$2
+([123])(\d\d\d\d) $(\1:ↂ--)$(historical \2)
+(.*) $1
+
+== help ==
+
+help Modules\nRoman-large (language code): multiple parenthesized form\nRoman: overline (×1000) with bar (×100)\nFunctions: historical – with special Unicode characters for 1000, 5000 and 10000
diff --git a/data/Suzhou.sor b/data/Suzhou.sor
new file mode 100644
index 0000000..141b5b6
--- /dev/null
+++ b/data/Suzhou.sor
@@ -0,0 +1,39 @@
+# Chinese Suzhou numbers, see Wikipedia
+(\d+)[.,](\d+) $(\1\2::)\n$(:\1:)
+(\d+) $(\1::)\n$(:\1:)
+(\d+)0:: $(\1::)
+(\d+):: $(\1:)
+
+0: 〇
+^1: 〡
+^2: 〢
+^3: 〣
+1: 一
+2: 二
+3: 三
+4: 〤
+5: 〥
+6: 〦
+7: 〧
+8: 〨
+9: 〩
+:\d{2}: 拾
+:\d{3}: 百
+:\d{4}: 千
+:\d{5}: 萬
+:\d{6}: 拾萬
+:\d{7}: 百萬
+:\d{8}: 千萬
+:\d{9}: 億
+:\d{10}: 拾億
+:\d{11}: 百億
+:\d{12}: 千億
+
+(\d+)0: $(\1:)〇
+(\d+)0([1-9]\d*): $(\1:)〇|$(\2:)
+^([123])(\d+): $(\1:)$(\2:)
+(\d)(\d+): $(\1:)|$(\2:)
+
+"\D\D\D (\d[.,\d]*)" $1元
+
+# formal currency: 圆
diff --git a/data/af.sor b/data/af.sor
new file mode 100644
index 0000000..4ed31c8
--- /dev/null
+++ b/data/af.sor
@@ -0,0 +1,111 @@
+^0$ nul
+1 een
+2 twee
+3 drie
+4 vier
+5 vyf
+6 ses
+7 sewe
+8 agt
+9 nege
+
+10 tien
+11 elf
+12 twaalf
+13 dertien
+14 veertien
+17 sewentien
+18 agtien
+19 negentien
+1(\d) $1|tien
+
+20 twintig
+30 dertig
+40 veertig
+70 sewentig
+80 tagtig
+90 negentig
+(\d)0 $1tig
+(\d)(\d) $2-en-$(\10)
+
+# function a
+a:0* " " # eenhonderd
+a:0*1?\d -en- # eenhonderd-en-een
+a:0*\d0 -en- # eenhonderd-en-twintig
+a:\d+ " " # eenhonderd een-en-twintig
+
+# function b
+b:0*1?\d # negentienduisend
+b:0*\d0 # twintigduisend
+b:\d+ " " # een-en-twintig duisend
+
+^1(\d\d) honderd$(a:\1)$1
+(\d)(\d\d) $1honderd$(a:\2)$2
+
+^1(\d{3}) duisend$(a:\1)$1
+(\d{1,3})(\d{3}) $1$(b:\1)duisend$(a:\2)$2
+
+(\d{1,3})(\d{6}) $1$(b:\1)miljoen$(a:\2)$2
+(\d{1,3})(\d{9}) $1$(b:\1)miljard$(a:\2)$2
+(\d{1,3})(\d{12}) $1$(b:\1)biljoen$(a:\2)$2
+(\d{1,3})(\d{15}) $1$(b:\1)biljard$(a:\2)$2
+(\d{1,3})(\d{18}) $1$(b:\1)triljoen$(a:\2)$2
+(\d{1,3})(\d{21}) $1$(b:\1)triljard$(a:\2)$2
+
+# negative number
+
+[-−](\d+) min |$1
+
+# decimals
+
+([-−]?\d+)[.,] $1| komma
+([-−]?\d+[.,]\d*)(\d) $1| |$2
+
+# currencies
+
+# unit/subunit
+
+u:([^,]*),([^,]*),([^,]*) \1
+s:([^,]*),([^,]*),([^,]*) \2
+p:([^,]*),([^,]*),([^,]*) \3
+
+CHF:(.) $(\1: Zwitserse franc, centime, centimes)
+CNY:(.) $(\1: renminbi yuan, fen, fen)
+EUR:(.) $(\1: euro, cent, cent)
+GBP:(.) $(\1: pond sterling, penny, pence)
+JPY:(.) $(\1: yen, sen, sen)
+USD:(.) $(\1: Amerikaanse dollar, sent, sent)
+ZAR:(.) $(\1: rand, sent, sent)
+
+"(JPY [-−]?\d+)[.,](\d\d)0" $1
+"(JPY [-−]?\d+[.,]\d\d)(\d)" $1 $2 rin
+
+"([A-Z]{3}) ([-−]?0)([.,]00?)?" nul$(\1:u)
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $2$(\1:u)
+
+"(CNY [-−]?\d+)[.,](\d)0?" $1 $2 jiao
+"(CNY [-−]?\d+[.,]\d)(\d)" $1 $2 fen
+
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1 een$(\2:s)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 $(\30)$(\2:p)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 $3$(\2:p)
+
+== ordinal ==
+
+([-−]?([24-6]|\d*1\d|\d+0[24-6])) $1|de
+([-−]?([79]|\d+0[79])) $1|nde
+([-−]?\d+) $(ordinal |$1)
+
+(.*)een \1eerste
+(.*)drie \1derde
+(.*) \1ste
+
+== ordinal-number ==
+
+([-−]?([2-79]|\d*1\d|\d+0[2-79])) \1de
+([-−]?\d+) \1ste
+
+== help ==
+
+"" $(1), $(2), $(3)\n$(help ordinal)$(help ordinal-number)
+(ordinal(-number)?) \1: $(\1 1), $(\1 2), $(\1 3)\n
diff --git a/data/ca.sor b/data/ca.sor
new file mode 100644
index 0000000..98f0590
--- /dev/null
+++ b/data/ca.sor
@@ -0,0 +1,189 @@
+^0 zero
+1$ u
+1 un
+2 dos
+3 tres
+4 quatre
+5 cinc
+6 sis
+7 set
+8 vuit
+9 nou
+10 deu
+11 onze
+12 dotze
+13 tretze
+14 catorze
+15 quinze
+16 setze
+17 disset
+1(\d) di$1
+20 vint
+2(\d) vint-i-$1
+30 trenta
+40 quaranta
+50 cinquanta
+60 seixanta
+70 setanta
+80 vuitanta
+90 noranta
+(\d)(\d) $(\10)-$2
+1(\d\d) cent[ $1]
+(\d)(\d\d) $1-cents[ $2]
+1(\d{3}) mil[ $1]
+(\d{1,3})(\d{3}) $1 mil[ $2]
+1(\d{6}) un milió[ $1]
+(\d{1,6})(\d{6}) $1 milions[ $2]
+1(\d{9}) mil milions[ $1]
+1(\d{12}) un bilió[ $1]
+(\d{1,6})(\d{12}) $1 bilions[ $2]
+1(\d{18}) un trilió[ $1]
+(\d{1,6})(\d{18}) $1 trilions[ $2]
+1(\d{24}) un quadrilió[ $1]
+(\d{1,6})(\d{24}) $1 quadrilions[ $2]
+
+# negative number
+
+[-−](\d+) menys |$1
+
+# decimals
+
+"([-−]?\d+)[.,]" |$1| coma
+"([-−]?\d+[.,]\d*)(\d)" $1| |$2
+
+# currency
+
+# convert masculine to feminine
+
+f:(.*ili)(.*) \1$(f:\2) # convert only <1000000
+f:(.*u)n([^a].*|$) $(f:\1na\2) # un -> una
+f:(.*d)o(s.*) $(f:\1ue\2) # dos -> dues
+f:(.*cent)(s.*) $(f:\1e\2) # cents -> centes
+.:(.*) \1
+
+# unit/subunit singular/plural
+
+# million or greater part of the number name separated by "ili" pattern
+# before masculine to feminine conversion
+
+us(.).:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) $(\1:\7) \2
+up(.).:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) $(\1:\7) \3
+ud(.).:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) $(\1:\7) \4
+ss.(.):([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) $(\1:\7) \5
+sp.(.):([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) $(\1:\7) \6
+
+# "mm" means masculine unit and masculine subunit
+
+# Usually used by Catalan users
+CHF:(.+),(.+) $(\2mm: franc suís, francs suïssos, de francs suïssos, cèntim, cèntims, \1)
+EUR:(.+),(.+) $(\2mm: euro, euros, d'euros, cèntim, cèntims, \1)
+GBP:(.+),(.+) $(\2fm: lliura esterlina, lliures esterlines, de lliures esterlines, penic, penics, \1)
+JPY:(.+),(.+) $(\2mm: ien, iens, de iens, sen, sen, \1)
+USD:(.+),(.+) $(\2mm: dòlar EUA, dòlars EUA, de dòlars EUA, centau, centaus, \1)
+
+# ACTIVE ISO 4217 CODES--A--
+AED:(.+),(.+) $(\2mm: dírham dels Emirats Àrabs Units, dírhams dels Emirats Àrabs Units, de dírhams dels Emirats Àrabs Units, fils, fulús, \1)
+AFN:(.+),(.+) $(\2mm: afgani, afganis, d'afganis, puli, puli, \1)
+ALL:(.+),(.+) $(\2mm: lek, lekë, de lekë, qindarka, qindarka, \1)
+AMD:(.+),(.+) $(\2mm: dram, drams, de drams, luma, luma, \1)
+ANG:(.+),(.+) $(\2mm: florí de les Antilles Neerlandeses, florins de les Antilles Neerlandeses, de florins de les Antilles Neerlandeses, cèntim, cèntims, \1)
+AOA:(.+),(.+) $(\2fm: kwanza, kwanzes, de kwanzes, cèntim cèntims, \1)
+ARS:(.+),(.+) $(\2mm: peso argentí, pesos argentins, de pesos argentins, centau, centaus, \1)
+AUD(.+),(.+) $(\2mm: dòlar australià, dòlars australians, de dòlars australians, centau, centaus, \1)
+AWG:(.+),(.+) $(\2mm: florí d'Aruba, florins d'Aruba, de florins d'Aruba, cèntim, cèntims, \1)
+AZN:(.+),(.+) $(\2mm: manat azerbaidjanès, manats azerbaidjanesos, de manats azerbaidjanesos, qəpik, qəpik, \1)
+
+# ACTIVE ISO 4217 CODES --X--
+#XAF Franc CFA emès pel BEAC (Banc dels Estats de l'Àfrica Central)
+XAG:(.+),(.+) $(\2fm: unça de plata, unces de plata, d'unces de plata, cèntim, cèntims, \1)
+XAU:(.+),(.+) $(\2fm: unça d'or, unces d'or, d'unces d'or, cèntim, cèntims, \1)
+#XBA Unitat compensatòria europea (EURCO) (unitat per al mercat d'obligacions)
+#XBB Unitat monetària europea (EMU-6) (unitat per al mercat d'obligacions)
+#XBC Unitat de compte europea 9 (EUA-9) (unitat per al mercat d'obligacions)
+#XBD Unitat de compte europea 17 (EUA-17) (unitat per al mercat d'obligacions)
+#XCD Dòlar del Carib Oriental
+#XDR Drets especials de gir (del Fons Monetari Internacional)
+#XFU Franc UIC (divisa especial)
+#XOF Franc CFA emès pel BCEAO (Banc Central dels Estats de l'Àfrica Occidental)
+XPD:(.+),(.+) $(\2fm: unça de pal·ladi, unces de pal·ladi, d'unces de pal·ladi, cèntim, cèntims, \1)
+#XPF Franc CFP (per als territoris francesos del Pacífic)
+XPT:(.+),(.+) $(\2fm: unça de platí, unces de platí, d'unces de platí, cèntim, cèntims, \1)
+#XTS Codi reservat per a proves
+#XXX Sense moneda, sense transacció monetària
+
+# OBSOLETE ISO 4217 CODES --Replaced by EUR--
+ADF:(.+),(.+) $(\2mm: franc andorrà, francs andorrans, de francs andorrans, cèntim, cèntims, \1)
+ADP:(.+),(.+) $(\2fm: pesseta andorrana, pessetes andorranes, de pessetes andorranes, cèntim, cèntims, \1)
+ATS:(.+),(.+) $(\2mm: xíling austríac, xílings austríacs, de xílings austríacs, groschen, groschen, \1)
+BEF:(.+),(.+) $(\2mm: franc belga, francs belgues, de francs belgues, cèntim, cèntims, \1)
+CYP:(.+),(.+) $(\2mm: lliura xipriota, lliures xipriotes, de lliures xipriotes, cèntim, cèntims, \1)
+DEM:(.+),(.+) $(\2mm: marc alemany, marcs alemanys, de marcs alemanys, penic, penics, \1)
+ESP:(.+),(.+) $(\2fm: pesseta, pessetes, de pessetes, cèntim, cèntims, \1)
+FIM:(.+),(.+) $(\2mm: marc finlandès, marcs finlandesos, de marcs finlandesos, penic, penics, \1)
+FRF:(.+),(.+) $(\2mm: franc francès, francs francesos, de francs francesos, cèntim, cèntims, \1)
+GRD:(.+),(.+) $(\2fm: dracma grega, dracmes gregues, leptó, leptà, \1)
+IEP:(.+),(.+) $(\2fm: lliura irlandesa, lliures irlandeses, de lliures irlandeses, penic, penics, \1)
+ITL:(.+),(.+) $(\2fm: lira italiana, lires italianes, de lires italianes, cèntim, cèntims, \1)
+LUF:(.+),(.+) $(\2mm: franc luxemburguès, francs luxemburguesos, de francs luxemburguesos, cèntim, cèntims, \1)
+MCF:(.+),(.+) $(\2mm: franc monegasc, francs monegascs, de francs monegascs, cèntim, cèntims, \1)
+MTL:(.+),(.+) $(\2fm: lira maltesa, lires malteses, de lires malteses, cèntim, cèntims, \1)
+NLG:(.+),(.+) $(\2mm: florí neerlandès, florins neerlandesos, de florins neerlandesos, cèntim, cèntims, \1)
+PTE:(.+),(.+) $(\2mm: escut portuguès, escuts portuguesos, de escuts portuguesos, centau, centaus, \1)
+SIT:(.+),(.+) $(\2mm: tolar eslovè, tolars eslovens, de tolars eslovens, stotin, stotinov, \1)
+SKK:(.+),(.+) $(\2fm: corona eslovaca, corones eslovaques, de corones eslovaques, halier, halierov, \1)
+SML:(.+),(.+) $(\2fm: lira de San Marino, lires de San Marino, de lires de San Marino, cèntim, cèntims, \1)
+VAL:(.+),(.+) $(\2fm: lira vaticana, lires vaticanes, de lires vaticanes, cèntim, cèntims, \1)
+XEU:(.+),(.+) $(\2mm: ecu, ecus, d'ecus, cèntim, cèntims, \1)
+
+"([A-Z]{3}) ([-−]?[01])([.,]00?)?"$(\1:|$2,us)
+"([A-Z]{3}) ([-−]?\d+0{6,})([.,]00?)?"$(\1:|$2,ud)
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?"$(\1:|$2,up)
+
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1 amb$(\2:un,ss)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 amb$(\2:|$(\30),sp)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 amb$(\2:|$3,sp)
+
+== feminine ==
+
+1 una
+(.*) $(f:|$1)
+
+== masculine ==
+
+1 un
+(.*) $1
+
+== ordinal(-masculine)? ==
+
+1 primer
+2 segon
+([-−]?\d+) $(ordinal |$2)
+
+(.*)nou \2novè
+(.*)deu \2desè
+(.*-)u(na?)? \2unè
+"(.* )u(na?)?" \2 primer
+"(.* )dos" \2segon
+"(.* t|t)res" \2ercer
+"(.* q|q)uatre" \2uart
+(.*)cinc \2cinquè
+(.*)[ae] \2è
+(.*(cent|mil|ion))s? \2è
+(.*li)ó \2onè
+(.*) \2è
+
+== ordinal-feminine ==
+
+([-−]?\d+) $(ordinal-feminine $(ordinal-masculine \1))
+(.*)è \1ena
+(.*) \1a
+
+== (ordinal)-number-(feminine|masculine) ==
+
+([-−]?\d+) \3$(ordinal-number $(\1-\2 \3))
+.*(.) \1
+
+== help ==
+
+"" $(1)|, $(2), $(3)\n$(help feminine)$(help masculine)$(help ordinal-number-masculine)$(help ordinal-number-feminine)$(help ordinal-feminine)$(help ordinal-masculine)
+(feminine|masculine|ordinal(-number)?(-feminine|-masculine)?) \1: $(\1 1), $(\1 2), $(\1 3)\n
diff --git a/data/cs.sor b/data/cs.sor
new file mode 100644
index 0000000..652b3e3
--- /dev/null
+++ b/data/cs.sor
@@ -0,0 +1,137 @@
+^0 nula
+^1$ jedno
+1 jeden
+^2$ dvě
+2 dva
+3 tři
+4 čtyři
+5 pět
+6 šest
+7 sedm
+8 osm
+9 devět
+10 deset
+11 jedenáct
+14 čtrnáct
+15 patnáct
+19 devatenáct
+1(\d) $1náct
+([234])(\d) $1cet[ $2]
+5(\d) padesát[ $1]
+6(\d) šedesát[ $1]
+9(\d) devadesát[ $1]
+(\d)(\d) $1desát[ $2]
+1(\d\d) sto[ $1]
+2(\d\d) dvě stě[ $1]
+([34])(\d\d) $1 sta[ $2]
+(\d)(\d\d) $1 set[ $2]
+1(\d\d\d) tisíc[ $1]
+([234])(\d\d\d) $1 tisíce[ $2]
+(\d{1,3})(\d\d\d) $1 tisíce[ $2]
+1(\d{6}) milión[ $1]
+([234])(\d{6}) $1 milióny[ $2]
+(\d{1,3})(\d{6}) $1 miliónů[ $2]
+1(\d{9}) miliarda[ $1]
+([234])(\d{9}) $1 miliardy[ $2]
+(\d{1,3})(\d{9}) $1 miliard[ $2]
+1(\d{12}) bilión[ $1]
+([234])(\d{12}) $1 bilióny[ $2]
+(\d{1,3})(\d{12}) $1 biliónů[ $2]
+1(\d{15}) biliarda[ $1]
+([234])(\d{15}) $1 biliardy[ $2]
+(\d{1,3})(\d{15}) $1 biliard[ $2]
+1(\d{18}) trilion[ $1]
+([234])(\d{18}) $1 trilióny[ $2]
+(\d{1,3})(\d{18}) $1 triliónů[ $2]
+1(\d{21}) triliarda[ $1]
+([234])(\d{21}) $1 triliardy[ $2]
+(\d{1,3})(\d{21}) $1 triliard[ $2]
+1(\d{24}) kvadrilión[ $1]
+([234])(\d{24}) $1 kvadrilióny[ $2]
+(\d{1,3})(\d{24}) $1 kvadriliónů[ $2]
+
+# negative number
+
+[-−](\d+) minus |$1
+
+# decimals
+
+([-−]?\d+)[.,] $1| čárka
+([-−]?\d+[.,])([^0]\d) $1| |$2
+([-−]?\d+[.,])(\d)(\d)(\d) $1| |$2 |$3 |$4
+([-−]?\d+[.,]\d*)(\d) $1| |$2
+
+# currency
+
+# unit/subunit singular/plural
+
+us:([^,]*),([^,]*),([^,]*),([^,]*) \1
+up:([^,]*),([^,]*),([^,]*),([^,]*) \2
+ss:([^,]*),([^,]*),([^,]*),([^,]*) \3
+sp:([^,]*),([^,]*),([^,]*),([^,]*) \4
+
+CHF:(\D+) $(\1: švýcarský frank, švýcarských franků, centim, centimů)
+CNY:(\D+) $(\1: juan renminbi, juan renminbi, fen, fen)
+CZK:(\D+) $(\1: koruna česká, korun českých, haléř, haléřů)
+EUR:(\D+) $(\1: euro, euro, cent, centů)
+GBP:(\D+) $(\1: libra šterlinků, libra šterlinků, penny, pence)
+JPY:(\D+) $(\1: jen, jenů, sen, sen)
+USD:(\D+) $(\1: americký dolar, amerických dolarů, cent, centů)
+
+"([A-Z]{3}) ([-−]?1)([.,]00?)?" $2$(\1:us)
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $2$(\1:up)
+
+"(CNY [-−]?\d+)[.,]10?" $1 $2 jiao
+"(CNY [-−]?\d+)[.,](\d)0?" $1 $2 jiao
+"(CNY [-−]?\d+[.,]\d)1" $1 $2 fen
+"(CNY [-−]?\d+[.,]\d)(\d)" $1 $2 fen
+
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1 $(1)$(\2:ss)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 $(\30)$(\2:sp)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 $3$(\2:sp)
+
+== cardinal-neuter ==
+
+(.*) $1
+
+== cardinal-feminine ==
+
+1 jedna
+(.*) $1
+
+== cardinal-masculine ==
+
+1 jeden
+2 dva
+(.*) $1
+
+== ordinal ==
+
+([-−]?\d+) $(ordinal |$1)
+
+(.*)(jedno|jeden) \1první
+(.*)(dvě|dva) \1druhý
+(.*)tři \1třetí
+(.*)čtyři \1čtvrtý
+(.*)pět \1pátý
+(.*)(šest|sedm|osm|desát|náct|sát) \1\2ý
+(.*)devět \1devátý
+"(.*)[^ ](c|s)et" \1\2átý
+(.*)sto \1stý
+"(.*)dvě stě" \1dvoustý
+"(.*)tři sta" \1třístý
+"(.*)čtyři sta" \1čtyřstý
+"(.*)(pět|šest|sedm|osm) set" \1\2istý
+"(.*)devět set" \1devítistý
+(.*)tisíce? \1tisící
+(.*)milión[yů] \1milióntý
+(.*)miliard[ay]? \1miliardtý
+
+== ordinal-number ==
+
+(\d+) \1.
+
+== help ==
+
+"" |$(1)|, |$(2)|, |$(3)|\n$(help cardinal-neuter)$(help cardinal-feminine)$(help cardinal-masculine)$(help ordinal)$(help ordinal-number)
+(.*) \1: |$(\1 1)|, |$(\1 2)|, |$(\1 3)|\n
diff --git a/data/da.sor b/data/da.sor
new file mode 100644
index 0000000..3f3e4dc
--- /dev/null
+++ b/data/da.sor
@@ -0,0 +1,120 @@
+^0 nul
+1$ en
+1 et
+2 to
+3 tre
+4 fire
+5 fem
+6 seks
+7 syv
+8 otte
+9 ni
+10 ti
+
+11 elleve
+12 tolv
+13 tretten
+14 fjorten
+15 femten
+16 seksten
+17 sytten
+18 atten
+19 nitten
+
+20 tyve
+30 tredive
+40 fyrre
+50 halvtreds
+60 tres
+70 halvfjerds
+80 firs
+90 halvfems
+
+(\d)(\d) $2|og$(\10)
+
+:0+
+:(\d+) og $1
+
+(\d)(\d\d) $1 hundrede $(:\2)
+(\d{1,3})(\d{3}) $1 tusind $(:\2)
+
+a:1,0+
+a:\d+,0+ er
+a:1,(\d+) " og $1"
+a:\d+,(\d+) "er og $1"
+
+(\d{1,3})(\d{6}) $1 million$(a:\1,\2)
+(\d{1,3})(\d{9}) $1 milliard$(a:\1,\2)
+(\d{1,3})(\d{12}) $1 billion$(a:\1,\2)
+(\d{1,3})(\d{15}) $1 billiard$(a:\1,\2)
+(\d{1,3})(\d{18}) $1 trillion$(a:\1,\2)
+(\d{1,3})(\d{21}) $1 trilliard$(a:\1,\2)
+(\d{1,3})(\d{24}) $1 kvadrillion$(a:\1,\2)
+
+# negative number
+
+[-−](\d+) minus |$1
+
+# decimals
+
+([-−]?\d+)[.,] $1| komma
+"([-−]?\d+[.,]0*)(\d+)" $1 |$2
+([-−]?\d+[.,]\d*)(\d) $1| |$2
+
+# currency
+
+# unit/subunit singular/plural
+
+us:([^,]*),([^,]*),([^,]*),([^,]*) \1
+up:([^,]*),([^,]*),([^,]*),([^,]*) \2
+ss:([^,]*),([^,]*),([^,]*),([^,]*) \3
+sp:([^,]*),([^,]*),([^,]*),([^,]*) \4
+
+CHF:(\D+) $(\1: schweizisk franc, schweizisk franc, centime, centimes)
+CNY:(\D+) $(\1: renminbi yuan, renminbi yuan, fen, fen)
+DKK:(\D+) $(\1: dansk krone, danske kroner, øre, øre)
+EUR:(\D+) $(\1: euro, euro, cent, cent)
+GBP:(\D+) $(\1: pund sterling, pund sterling, penny, pence)
+ISK:(\D+) $(\1: islandsk krone, islandske kroner, eyrir, aurar)
+JPY:(\D+) $(\1: yen, yen, sen, sen)
+SEK:(\D+) $(\1: svensk krone, svenske kroner, öre, öre)
+USD:(\D+) $(\1: US dollar, US dollar, cent, cent)
+
+"([A-Z]{3}) ([-−]?1)([.,]00?)?" $2$(\1:us)
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $2$(\1:up)
+
+"(CNY [-−]?\d+)[.,]10?" $1 $2 jiao
+"(CNY [-−]?\d+)[.,](\d)0?" $1 $2 jiao
+"(CNY [-−]?\d+[.,]\d)1" $1 $2 fen
+"(CNY [-−]?\d+[.,]\d)(\d)" $1 $2 fen
+
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1 |$(1)$(\2:ss)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 |$(\30)$(\2:sp)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 |$3$(\2:sp)
+
+== ordinal ==
+
+([-−]?\d+) $(ordinal |$1)
+
+nul nulte # 0
+en først # 1
+"(.*) en" \1 først # 1
+(.*)to \1anden # 2
+(.*)tre \1tredje # 3
+(.*)fire \1fjerde # 4
+(.*(fem|ellev|tolv|ard|on))(e|er)? \1te # 5, 11, 12, 10^6, 10^9 etc.
+(.*)seks \1sjette # 6
+(.*)tres \1tressende # 60
+(.*(syv|ott|ni|ti|tyv|trediv|fyrr|s))e? \1ende # 7, 8, 9, 10, 20, 30, 40, 50, 70, 80, 90
+(.*en) \1de # 13-19
+(.*tusind) \1e # 1000 etc.
+(.*) \1 # 100, etc.
+
+== ordinal-number ==
+
+(\d+) \1.
+
+== help ==
+
+"" |$(1)|, |$(2)|, |$(3)|\n$(help ordinal)$(help ordinal-number)
+(ordinal(-number)?) \1: |$(\1 1)|, |$(\1 2)|, |$(\1 3)|\n
diff --git a/data/de.sor b/data/de.sor
new file mode 100644
index 0000000..d4ee851
--- /dev/null
+++ b/data/de.sor
@@ -0,0 +1,103 @@
+^0$ null
+1$ eins
+1 ein
+2 zwei
+3 drei
+4 vier
+5 fünf
+6 sechs
+7 sieben
+8 acht
+9 neun
+10 zehn
+11 elf
+12 zwölf
+16 sechzehn
+17 siebzehn
+1(\d) $1zehn
+2(\d) [$1und]zwanzig
+3(\d) [$1und]dreissig # [:de-CH:] [:de-LI:]
+3(\d) [$1und]dreißig
+6(\d) [$1und]sechzig
+7(\d) [$1und]siebzig
+(\d)(\d) [$2und]$1zig
+(\d)(\d\d) $1hundert$2
+(\d{1,3})(\d{3}) $1tausend$2
+1(\d{6}) eine Million[ $1]
+(\d{1,3})(\d{6}) $1 Millionen[ $2]
+1(\d{9}) eine Milliarde[ $1]
+(\d{1,3})(\d{9}) $1 Milliarden[ $2]
+1(\d{12}) eine Billion[ $1]
+(\d{1,3})(\d{12}) $1 Billionen[ $2]
+1(\d{15}) eine Billiarde[ $1]
+(\d{1,3})(\d{15}) $1 Billiarden[ $2]
+1(\d{18}) eine Trillion[ $1]
+(\d{1,3})(\d{18}) $1 Trillionen[ $2]
+1(\d{21}) eine Trilliarde[ $1]
+(\d{1,3})(\d{21}) $1 Trilliarden[ $2]
+
+# negative number
+
+[-−](\d+) minus |$1
+
+# decimals
+
+"([-−]?\d+)[.,]" $1| Komma
+"([-−]?\d+[.,]\d*)(\d)" $1| |$2
+
+# currency
+
+# unit/subunit singular/plural
+
+us:([^,]*),([^,]*),([^,]*),([^,]*) \1
+up:([^,]*),([^,]*),([^,]*),([^,]*) \2
+ss:([^,]*),([^,]*),([^,]*),([^,]*) \3
+sp:([^,]*),([^,]*),([^,]*),([^,]*) \4
+
+CHF:(\D+) $(\1: Schweizer Franken, Schweizer Franken, Rappen, Rappen)
+CNY:(\D+) $(\1: Yuan, Yuan, Fen, Fen)
+EUR:(\D+) $(\1: Euro, Euro, Cent, Cent)
+GBP:(\D+) $(\1: Pfund Sterling, Pfund Sterling, Penny, Pence)
+USD:(\D+) $(\1: US-Dollar, US-Dollar, Cent, Cents)
+
+"JPY ([-−]?\d+([.,]\d+)?)" $1 Yen
+
+"([A-Z]{3}) ([-−]?1)([.,]00?)?" $2$(\1:us)
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $2$(\1:up)
+
+"(CNY [-−]?\d+)[.,]10?" $1 $2 Jiao
+"(CNY [-−]?\d+)[.,](\d)0?" $1 $2 Jiao
+"(CNY [-−]?\d+[.,]\d)1" $1 $2 Fen
+"(CNY [-−]?\d+[.,]\d)(\d)" $1 $2 Fen
+
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1 und $(1)$(\2:ss)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 und $(\30)$(\2:sp)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 und $3$(\2:sp)
+
+== ordinal ==
+
+([-−]?[024569]) $1te
+([-−]?\d*0[24569]) $1te
+([-−]?\d*1\d) $1te
+([-−]?\d+) $(ordinal $1)
+
+(.*)eins \1erste
+(.*)drei \1dritte
+(.*)sieben \1siebte
+(.*)acht \1achte
+"(.*)eine Milli(on|ard)e?" \1einmilli\2ste
+"(.*)eine Billi(on|ard)e?" \1einbilli\2ste
+"(.*)eine Trilli(on|ard)e?" \1eintrilli\2ste
+"(.*) Milli(on|ard)en" \1milli\2ste
+"(.*) Billi(on|ard)en" \1billi\2ste
+"(.*) Trilli(on|ard)en" \1trilli\2ste
+(.*) \1ste
+
+== ordinal-number ==
+
+(\d+) \1.
+
+== help ==
+
+"" |$(1)|, |$(2)|, |$(3)|\n$(help ordinal)$(help ordinal-number)
+(ordinal(-number)?) \1: |$(\1 1)|, |$(\1 2)|, |$(\1 3)|\n
diff --git a/data/el.sor b/data/el.sor
new file mode 100644
index 0000000..bcead31
--- /dev/null
+++ b/data/el.sor
@@ -0,0 +1,218 @@
+^0$ μηδέν
+1 ένα
+2 δύο
+3 τρία
+4 τέσσερα
+5 πέντε
+6 έξι
+7 επτά
+8 οκτώ
+9 εννέα
+10 δέκα
+11 έντεκα
+12 δώδεκα
+1(\d) δεκα$1
+2(\d) είκοσι[ $1]
+3(\d) τριάντα[ $1]
+4(\d) σαράντα[ $1]
+5(\d) πενήντα[ $1]
+6(\d) εξήντα$1
+7(\d) εβδομήντα[ $1]
+8(\d) ογδόντα[ $1]
+9(\d) ενενήντα[ $1]
+1(\d\d) εκατό[v $1]
+2(\d\d) διακόσια[ $1]
+3(\d\d) τριακόσια[ $1]
+4(\d\d) τετρακόσια[ $1]
+5(\d\d) πεντακόσια[ $1]
+6(\d\d) εξακόσια[ $1]
+7(\d\d) επτακόσια[ $1]
+8(\d\d) οκτακόσια[ $1]
+9(\d\d) εννιακόσια[ $1]
+1(\d{3}) χίλια[ $1]
+(\d{1,3})(\d{3}) $(cardinal-feminine \1) χιλιάδες[ $2]
+1(\d{6}) ένα εκατομμύριο[ $1]
+(\d{1,3})(\d{6}) $1 εκατομμύρια[ $2]
+1(\d{9}) ένα δισεκατομμύριο[ $1]
+(\d{1,3})(\d{9}) $1 δισεκατομμύρια[ $2]
+1(\d{12}) ένα τρισεκατομμύριο[ $1]
+(\d{1,3})(\d{12}) $1 τρισεκατομμύρια[ $2]
+1(\d{15}) ένα τετράκις εκατομμύριο[ $1]
+(\d{1,3})(\d{15}) $1 τετράκις εκατομμύρια[ $2]
+1(\d{18}) ένα πεντάκις εκατομμύριο[ $1]
+(\d{1,3})(\d{18}) $1 πεντάκις εκατομμύρια[ $2]
+1(\d{21}) ένα εξάκις εκατομμύριο[ $1]
+(\d{1,3})(\d{21}) $1 εξάκις εκατομμύρια[ $2]
+1(\d{24}) ένα επτάκις εκατομμύριο[ $1]
+(\d{1,3})(\d{24}) $1 επτάκις εκατομμύρια[ $2]
+
+# negative number
+
+[-−](\d+) μείον |$1
+
+# decimals
+
+"([-−]?\d+)[.,]" "$1| κόμμα"
+"([-−]?\d+[.,]\d*)(\d)" $1| |$2
+
+# currency
+
+# unit/subunit singular/plural
+
+us:([^,]*),([^,]*),([^,]*),([^,]*) \1
+up:([^,]*),([^,]*),([^,]*),([^,]*) \2
+ss:([^,]*),([^,]*),([^,]*),([^,]*) \3
+sp:([^,]*),([^,]*),([^,]*),([^,]*) \4
+
+CHF:(\D+) $(\1: ελβετικό φράγκο, ελβετικό φράγκο, σαντίμ, σαντίμ)
+GBP:(\D+) $(\1: λίρα στερλίνα, λίρα στερλίνα, πέννα, πένες)
+JPY:(\D+) $(\1: γιεν, γιεν, σεν, σεν)
+EUR:(\D+) $(\1: ευρώ, ευρώ, λεπτό, λεπτά)
+USD:(\D+) $(\1: δολάριο ΗΠΑ, δολαρίων ΗΠΑ, σεντ, σεντς)
+
+"([A-Z]{3}) ([-−]?1)([.,]00?)?" $2$(\1:us)
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $2$(\1:up)
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1 y |$(1)$(\2:ss)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 y |$(\30)$(\2:sp)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 y |$3$(\2:sp)
+
+== cardinal-neuter ==
+
+(\d+) $1
+
+== cardinal-feminine ==
+
+1 μια
+3 τρεις
+4 τέσσερις
+(\d) $1
+1([34]) $(10)$(cardinal-feminine \2)
+(\d)([34]) $(\10) $(cardinal-feminine \2)
+(\d\d) $1
+1(\d\d) $(100)[ $(cardinal-feminine \1)]
+2(\d\d) διακόσιες[ $(cardinal-feminine \1)]
+3(\d\d) τριακόσιες[ $(cardinal-feminine \1)]
+4(\d\d) τετρακόσιες[ $(cardinal-feminine \1)]
+5(\d\d) πεντακόσιες[ $(cardinal-feminine \1)]
+6(\d\d) εξακόσιες[ $(cardinal-feminine \1)]
+7(\d\d) επτακόσιες[ $(cardinal-feminine \1)]
+8(\d\d) οκτακόσιες[ $(cardinal-feminine \1)]
+9(\d\d) εννιακόσιες[ $(cardinal-feminine \1)]
+1(\d{3}) χίλιες[ $(cardinal-feminine \1)]
+(\d{1,3})(\d{3}) $(cardinal-feminine \1) χίλιάδες[ $(cardinal-feminine \2)]
+(\d+000)(\d{3}) $(\1000)[ $(cardinal-feminine \2)]
+(\d+)(\d{6}) $(\1000000)[ $(cardinal-feminine \2)]
+
+== cardinal-masculine ==
+
+1 ένας
+3 τρεις
+4 τέσσερα
+(\d) $1
+1([34]) $(10)$(cardinal-masculine \2)
+(\d)([34]) $(\10) $(cardinal-masculine \2)
+(\d\d) $1
+1(\d\d) εκατό[ν $(cardinal-masculine \1)]
+2(\d\d) διακόσιοι[ $(cardinal-masculine \1)]
+3(\d\d) τριακόσιοι[ $(cardinal-masculine \1)]
+4(\d\d) τετρακόσιοι[ $(cardinal-masculine \1)]
+5(\d\d) πεντακόσιοι[ $(cardinal-masculine \1)]
+6(\d\d) εξακόσιοι[ $(cardinal-masculine \1)]
+7(\d\d) επτακόσιοι[ $(cardinal-masculine \1)]
+8(\d\d) οκτακόσιοι[ $(cardinal-masculine \1)]
+9(\d\d) εννιακόσιοι[ $(cardinal-masculine \1)]
+1(\d{3}) χίλιοι[ $(cardinal-masculine \1)]
+(\d{1,3})(\d{3}) $(cardinal-feminine \1000)[ $(cardinal-masculine \2)]
+(\d+000)(\d{3}) $(\1000)[ $(cardinal-masculine \2)]
+(\d+)(\d{6}) $(\1000000)[ $(cardinal-masculine \2)]
+
+== to-feminine ==
+
+(.*)ος(.*) $(to-feminine \1η\2)
+(.*)ός(.*) $(to-feminine \1ή\2)
+(.*) \1
+
+== to-neuter ==
+
+(.*)ος(.*) $(to-neuter \1ο\2)
+(.*)ός(.*) $(to-neuter \1ό\2)
+(.*) \1
+
+== ordinal(-masculine)? ==
+
+^0 μηδενικός
+1 πρώτος
+2 δεύτερος
+3 τρίτος
+4 τέταρτος
+5 πέμπτος
+6 έκτος
+7 έβδομος
+8 όγδοος
+9 ένατος
+10 δέκατος
+11 ενδέκατος
+12 δωδέκατος
+1(\d) δέκατος $(ordinal \2)
+2(\d) εικοστός[ $(ordinal \2)]
+3(\d) τριακοστός[ $(ordinal \2)]
+4(\d) τεσσαρακοστός[ $(ordinal \2)]
+5(\d) πεντηκοστός[ $(ordinal \2)]
+6(\d) εξηκοστός[ $(ordinal \2)]
+7(\d) εβδομηκοστός[ $(ordinal \2)]
+8(\d) ογδοηκοστός[ $(ordinal \2)]
+9(\d) εννενηκοστός[ $(ordinal \2)]
+1(\d\d) εκατοστός[ $(ordinal \2)]
+2(\d\d) διακοσιοστός[ $(ordinal \2)]
+3(\d\d) τριακοσιοστός[ $(ordinal \2)]
+4(\d\d) τετρακοσιοστός[ $(ordinal \2)]
+5(\d\d) πεντακοσιοστός[ $(ordinal \2)]
+6(\d\d) εξακοσιοστός[ $(ordinal \2)]
+7(\d\d) επτακοσιοστός[ $(ordinal \2)]
+8(\d\d) οκτακοσιοστός[ $(ordinal \2)]
+9(\d\d) εννεακοσιοστός[ $(ordinal \2)]
+1(\d{3}) χιλιοστός[ $(ordinal \2)]
+2(\d{3}) δισχιλιοστός[ $(ordinal \2)]
+3(\d{3}) τρισχιλιοστός[ $(ordinal \2)]
+4(\d{3}) τετράκις χιλιοστός[ $(ordinal \2)]
+5(\d{3}) πεντάκις χιλιοστός[ $(ordinal \2)]
+6(\d{3}) εξάκις χιλιοστός[ $(ordinal \2)]
+7(\d{3}) επτάκις χιλιοστός[ $(ordinal \2)]
+8(\d{3}) οκτάκις χιλιοστός[ $(ordinal \2)]
+9(\d{3}) εννεάκις χιλιοστός[ $(ordinal \2)]
+(\d)?10(\d{3}) [$(\200) ]δεκάκις χιλιοστός[ $(ordinal \3)]
+(\d{1,3})(\d{3}) $2 χιλιοστός[ $(ordinal \3)]
+(\d{1,3})(\d{6}) $2 εκατομμυριοστός[ $(ordinal \3)]
+(\d{1,3})(\d{9}) $2 δισεκατομμυριοστός[ $(ordinal \3)]
+(\d{1,3})(\d{12}) $2 τρισεκατομμυριοστός[ $(ordinal \3)]
+(\d{1,3})(\d{15}) $2 τετράκις εκατομμυριοστός[ $(ordinal \3)]
+(\d{1,3})(\d{18}) $2 πεντάκις εκατομμυριοστός[ $(ordinal \3)]
+(\d{1,3})(\d{21}) $2 εξάκις εκατομμυριοστός[ $(ordinal \3)]
+(\d{1,3})(\d{24}) $2 επτάκις εκατομμυριοστός[ $(ordinal \3)]
+
+== ordinal-feminine ==
+
+(\d+) $(to-feminine $(ordinal \1))
+
+== ordinal-neuter ==
+
+(\d+) $(to-neuter $(ordinal \1))
+
+== ordinal-number(-masculine)? ==
+
+(\d*10) \2ος
+(\d*0) \2ός
+(\d+) \2ος
+
+== ordinal-number-feminine ==
+
+(\d+) $(to-feminine $(ordinal-number \1))
+
+== ordinal-number-neuter ==
+
+(\d+) $(to-neuter $(ordinal-number \1))
+
+== help ==
+
+"" |$(1)|, |$(2)|, |$(3)|\n$(help cardinal-neuter)$(help cardinal-feminine)$(help cardinal-masculine)$(help ordinal)$(help ordinal-neuter)$(help ordinal-feminine)$(help ordinal-masculine)$(help ordinal-number)$(help ordinal-number-neuter)$(help ordinal-number-feminine)$(help ordinal-number-masculine)
+(.*) \1: |$(\1 1)|, |$(\1 2)|, |$(\1 3)|\n
diff --git a/data/en.sor b/data/en.sor
new file mode 100644
index 0000000..e6ee769
--- /dev/null
+++ b/data/en.sor
@@ -0,0 +1,210 @@
+^0 zero
+1 one
+2 two
+3 three
+4 four
+5 five
+6 six
+7 seven
+8 eight
+9 nine
+10 ten
+11 eleven
+12 twelve
+13 thirteen
+15 fifteen
+18 eighteen
+1(\d) $1teen
+2(\d) twenty[-$1]
+3(\d) thirty[-$1]
+4(\d) forty[-$1]
+5(\d) fifty[-$1]
+8(\d) eighty[-$1]
+(\d)(\d) $1ty[-$2]
+
+# separator function
+:0+ # one million
+:0*\d?\d " and " # one million and twenty-two
+:\d+ ", " # one million, one thousand
+
+(\d)(\d\d) $1 hundred[ and $2] # one hundred and one [:en-AU:] [:en-GB:] [:en-IE:] [:en-NZ:]
+(\d)(\d\d) $1 hundred[ $2] # default: one hundred one
+(\d{1,2})([1-9]\d\d) $1 thousand[ $2] # ten thousand two hundred
+
+(\d{1,2})(\d{3}) $1 thousand$(:\2)$2 # [:en-IN:] one hundred thousand, two hundred
+(\d{1,2})(000\d\d) $1 lakh$(:\2)$2 # [:en-IN:] one lakh and two
+(\d{1,2})(\d{5}) $1 lakh[ $2] # [:en-IN:] one lakh two hundred
+(\d{1,4})(\d{7}) $1 crore$(:\2)$2 # [:en-IN:]
+
+(\d{1,3})(\d{3}) $1 thousand$(:\2)$2 # one hundred thousand, two hundred
+(\d{1,3})(\d{6}) $1 million$(:\2)$2
+(\d{1,3})(\d{9}) $1 billion$(:\2)$2
+(\d{1,3})(\d{12}) $1 trillion$(:\2)$2
+(\d{1,3})(\d{15}) $1 quadrillion$(:\2)$2
+(\d{1,3})(\d{18}) $1 quintillion$(:\2)$2
+(\d{1,3})(\d{21}) $1 sextillion$(:\2)$2
+(\d{1,3})(\d{24}) $1 septillion$(:\2)$2
+(\d{1,3})(\d{27}) $1 octillion$(:\2)$2
+(\d{1,3})(\d{30}) $1 nonillion$(:\2)$2
+(\d{1,3})(\d{33}) $1 decillion$(:\2)$2
+(\d{1,3})(\d{36}) $1 undecillion$(:\2)$2
+(\d{1,3})(\d{39}) $1 duodecillion$(:\2)$2
+(\d{1,3})(\d{42}) $1 tredecillion$(:\2)$2
+
+# negative number
+
+[-−](\d+) negative |$1
+
+# decimals
+
+0[.,] point
+([-−]?\d+)[.,] $1| point
+([-−]?\d+[.,]\d*)(\d) $1| |$2
+
+# currency
+
+# unit/subunit singular/plural
+
+us:([^,]*),([^,]*),([^,]*),([^,]*) \1
+up:([^,]*),([^,]*),([^,]*),([^,]*) \2
+ss:([^,]*),([^,]*),([^,]*),([^,]*) \3
+sp:([^,]*),([^,]*),([^,]*),([^,]*) \4
+
+AUD:(\D+) $(\1: Australian dollar, Australian dollars, cent, cents)
+BGN:(\D+) $(\1: lev, leva, stotinka, stotinki)
+BWP:(\D+) $(\1: pula, pula, thebe, thebe)
+CAD:(\D+) $(\1: Canadian dollar, Canadian dollars, cent, cents)
+CHF:(\D+) $(\1: Swiss franc, Swiss francs, centime, centimes)
+CNY:(\D+) $(\1: Chinese yuan, Chinese yuan, fen, fen)
+CZK:(\D+) $(\1: Czech koruna, Czech koruny, halér, halére)
+EEK:(\D+) $(\1: kroon, kroonid, sent, senti)
+EUR:(\D+) $(\1: euro, euro, cent, cents)
+GBP:(\D+) $(\1: pound sterling, pounds sterling, penny, pence)
+GHS:(\D+) $(\1: Ghana cedi, Ghana cedis, pesewa, pesewas)
+GMD:(\D+) $(\1: dalasi, dalasi, butut, bututs)
+HKD:(\D+) $(\1: Hong Kong dollar, Hong Kong dollars, cent, cents)
+HRK:(\D+) $(\1: kuna, kuna, lipa, lipa)
+HUF:(\D+) $(\1: forint, forint, fillér, fillér)
+INR:(\D+) $(\1: Indian rupee, Indian rupees, paisa, paise)
+JMD:(\D+) $(\1: Jamaica dollar, Jamaica dollars, cent, cents)
+JPY:(\D+) $(\1: Japanese yen, Japanese yen, sen, sen)
+KES:(\D+) $(\1: Kenyan shilling, Kenyan shillings, cent, cents)
+LRD:(\D+) $(\1: Liberian dollar, Liberian dollars, cent, cents)
+LSL:(\D+) $(\1: loti, maloti, sente, lisente)
+LTL:(\D+) $(\1: litas, litai, centas, centai)
+LVL:(\D+) $(\1: lats, lati, santims, santimi)
+MGA:(\D+) $(\1: ariary, ariaries, iraimbilanja, iraimbilanja)
+MUR:(\D+) $(\1: Mauritian rupee, Mauritian rupees, cent, cents)
+MXN:(\D+) $(\1: Mexican peso, Mexican pesos, centavo, centavos)
+MWK:(\D+) $(\1: Malawian kwacha, Malawian kwacha, tambala, tambala)
+NAD:(\D+) $(\1: Namibian dollar, Namibian dollars, cent, cents)
+NGN:(\D+) $(\1: naira, naira, kobo, kobo)
+NZD:(\D+) $(\1: New Zealand dollar, New Zealand dollars, cent, cents)
+PGK:(\D+) $(\1: kina, kina, toea, toea)
+PHP:(\D+) $(\1: Philippine peso, Philippine pesos, centavo, centavos)
+PKR:(\D+) $(\1: Pakistani rupee, Pakistani rupees, paisa, paise)
+PLN:(\D+) $(\1: zloty, zlotys, grosz, groszy)
+RON:(\D+) $(\1: Romanian leu, Romanian lei, ban, bani)
+RSD:(\D+) $(\1: Serbian dinar, Serbian dinars, para, para)
+RUB:(\D+) $(\1: Russian ruble, Russian rubles, kopek, kopeks)
+RWF:(\D+) $(\1: Rwandese franc, Rwandese francs, centime, centimes)
+SDG:(\D+) $(\1: Sudanese pound, Sudanese pounds, piastre, piastres)
+SGD:(\D+) $(\1: Singapore dollar, Singapore dollars, cent, cents)
+SLL:(\D+) $(\1: leone, leones, cent, cents)
+SZL:(\D+) $(\1: lilangeni, emalangeni, cent, cents)
+THB:(\D+) $(\1: baht, baht, satang, satang)
+TRY:(\D+) $(\1: Turkish lira, Turkish lira, kurus, kurus)
+TTD:(\D+) $(\1: Trinidad and Tobago dollar, Trinidad and Tobago dollars, cent, cents)
+TZS:(\D+) $(\1: Tanzanian shilling, Tanzanian shillings, cent, cents)
+UAH:(\D+) $(\1: hryvnia, hryvnia, kopiyka, kopiyka)
+UGX:(\D+) $(\1: Uganda shilling, Uganda shillings, cent, cents)
+USD:(\D+) $(\1: U.S. dollar, U.S. dollars, cent, cents)
+X[AO]F:(\D+) $(\1: CFA franc, CFA francs, centime, centimes)
+ZAR:(\D+) $(\1: South African rand, South African rand, cent, cents)
+ZMK:(\D+) $(\1: Zambian kwacha, Zambian kwacha, ngwee, ngwee)
+ZWL:(\D+) $(\1: Zimbabwe dollar, Zimbabwe dollars, cent, cents)
+
+"(JPY [-−]?\d+)[.,](\d\d)0" $1
+"(JPY [-−]?\d+[.,]\d\d)(\d)" $1 $2 rin
+
+"([A-Z]{3}) ([-−]?1)([.,]00?)?" $2$(\1:us)
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $2$(\1:up)
+
+"(CNY [-−]?\d+)[.,](\d)0?" $1 $2 jiao
+"(CNY [-−]?\d+[.,]\d)(\d)" $1 $2 fen
+
+"((MGA|MRO) [-−]?\d+)[.,]0" $1
+"((MGA|MRO) [-−]?\d+)[.,]2" $1 and |$(1)$(\2:ss)
+"((MGA|MRO) [-−]?\d+)[.,]4" $1 and |$(2)$(\2:sp)
+"((MGA|MRO) [-−]?\d+)[.,]6" $1 and |$(3)$(\2:sp)
+"((MGA|MRO) [-−]?\d+)[.,]8" $1 and |$(4)$(\2:sp)
+
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1 and |$(1)$(\2:ss)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 and |$(\30)$(\2:sp)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 and |$3$(\2:sp)
+
+== money ==
+
+"(JPY [-−]?\d+)[.,](\d\d)0" $1
+"(JPY [-−]?\d+[.,]\d\d)(\d)" $1 $2 rin
+
+"([A-Z]{3}) ([-−]?1)([.,]00?)?" $2$(\1:us)
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $2$(\1:up)
+
+"(CNY [-−]?\d+)[.,](\d)0?" $1 $2 jiao
+"(CNY [-−]?\d+[.,]\d)(\d)" $1 $2 fen
+
+"(MGA|MRO) ([-−]?\d+)[.,]0" $2$(\1:us)
+"(MGA|MRO) ([-−]?\d+)[.,]2" $2 and 1/5$(\1:us)
+"(MGA|MRO) ([-−]?\d+)[.,]4" $2 and 2/5$(\1:up)
+"(MGA|MRO) ([-−]?\d+)[.,]6" $2 and 3/5$(\1:up)
+"(MGA|MRO) ([-−]?\d+)[.,]8" $2 and 4/5$(\1:up)
+
+"([A-Z]{3}) ([-−]?1)" $2$(\1:us)
+"([A-Z]{3}) ([-−]?\d+)" $2$(\1:up)
+"(([A-Z]{3}) ([-−]?\d+))[.,](01)" $3 and 1/100$(\2:us)
+"(([A-Z]{3}) ([-−]?\d+))[.,](\d)" $3 and \40/100$(\2:up)
+"(([A-Z]{3}) ([-−]?\d+))[.,](\d\d)" $3 and \4/100$(\2:up)
+"(([A-Z]{3}) ([-−]?\d+))[.,](\d\d\d)" $3 and \4/1000$(\2:up)
+
+== ordinal ==
+
+# convert to text, and recall to convert
+# cardinal names to ordinal ones
+
+([-−]?\d+) $(ordinal |$1)
+
+(.*)one \1first
+(.*)two \1second
+(.*)three \1third
+(.*)five \1fifth
+(.*)eight \1eighth
+(.*)nine \1ninth
+(.*)twelve \1twelfth
+(.*)y \1ieth
+(.*) \1th
+
+== ordinal-number ==
+
+(.*1\d) \1th
+(.*1) \1st
+(.*2) \1nd
+(.*3) \1rd
+(.*) \1th
+
+== year ==
+
+(1[1-9])00 $1 hundred
+(1[1-9])([0-9][0-9]) $1 $2
+(.*) $(year-remove-and $1)
+
+== year-remove-and ==
+
+"(.*) and (.*)" \1 \2
+(.*) \1
+
+== help ==
+
+"" $(1)|, $(2), $(3)\n$(\0 ordinal)$(\0 ordinal-number)year: $(year 1999), two thousand, $(year 2001)\ncurrency \(for example, USD\): $(USD 2.5)\nmoney USD: $(money USD 2.5)
+"(ordinal(-number)?|USD)" \1: $(\1 1), $(\1 2), $(\1 3)\n
+
diff --git a/data/eo.sor b/data/eo.sor
new file mode 100644
index 0000000..758be94
--- /dev/null
+++ b/data/eo.sor
@@ -0,0 +1,73 @@
+^0 nulo
+1 unu
+2 du
+3 tri
+4 kvar
+5 kvin
+6 ses
+7 sep
+8 ok
+9 naŭ
+1(\d) dek[ $1]
+(\d)(\d) $1dek[ $2]
+1(\d\d) cent[ $1]
+(\d)(\d\d) $1cent[ $2]
+1(\d{3}) mil[ $1]
+(\d{1,3})(\d{3}) $1 mil[ $2]
+1(\d{6}) unu miliono[ $1]
+(\d{1,3})(\d{6}) $1 milionoj[ $2]
+1(\d{9}) unu miliardo[ $1]
+(\d{1,3})(\d{9}) $1 miliardoj[ $2]
+1(\d{12}) unu duiliono[ $1]
+(\d{1,3})(\d{12}) $1 duilionoj[ $2]
+1(\d{15}) unu duiliardo[ $1]
+(\d{1,3})(\d{15}) $1 duiliardoj[ $2]
+1(\d{18}) unu triiliono[ $1]
+(\d{1,3})(\d{18}) $1 triilionoj[ $2]
+1(\d{21}) unu triiliardo[ $1]
+(\d{1,3})(\d{21}) $1 triiliardoj[ $2]
+
+# negative number
+
+[-−](\d+) negativa |$1
+
+# decimals
+
+"([-−]?\d+)[.,]" "$1| komo"
+"([-−]?\d+[.,]\d*)(\d)" $1| |$2
+
+# currency
+
+# unit/subunit singular/plural
+
+us:([^,]*),([^,]*),([^,]*),([^,]*) \1
+up:([^,]*),([^,]*),([^,]*),([^,]*) \2
+ss:([^,]*),([^,]*),([^,]*),([^,]*) \3
+sp:([^,]*),([^,]*),([^,]*),([^,]*) \4
+
+CHF:(\D+) $(\1: svisa franko, svisaj frankoj, centimo, centimoj)
+CNY:(\D+) $(\1: ĉina juano, ĉinaj juanoj, fen-o, fen-oj)
+EUR:(\D+) $(\1: eŭro, eŭroj, cendo, cendoj)
+GBP:(\D+) $(\1: sterlinga pundo, sterlingaj pundoj, penco, pencoj)
+JPY:(\D+) $(\1: japana eno, japanaj enoj, seno, senoj)
+USD:(\D+) $(\1: usona dolaro, usonaj dolaroj, cendo, cendoj)
+
+"([A-Z]{3}) ([-−]?1)" $2$(\1:us)
+"([A-Z]{3}) ([-−]?\d+)" $2$(\1:up)
+
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1 |$(1)$(\2:ss)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 |$(\30)$(\2:sp)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 |$3$(\2:sp)
+
+== ordinal ==
+
+([-−]?\d+) $1a
+
+== ordinal-number ==
+
+(\d+) \1.
+
+== help ==
+
+"" $(1), $(2), $(3)\n$(help ordinal)$(help ordinal-number)
+(ordinal(-number)?) \1: $(\1 1), $(\1 2), $(\1 3)\n
diff --git a/data/es.sor b/data/es.sor
new file mode 100644
index 0000000..82168ea
--- /dev/null
+++ b/data/es.sor
@@ -0,0 +1,203 @@
+^0 cero
+1$ uno
+1 un
+2 dos
+3 tres
+4 cuatro
+5 cinco
+6 seis
+7 siete
+8 ocho
+9 nueve
+10 diez
+11 once
+12 doce
+13 trece
+14 catorce
+15 quince
+16 dieciséis
+1(\d) dieci$1
+20 veinte
+22 veintidós
+23 veintitrés
+26 veintiséis
+2(\d) veinti$1
+30 treinta
+40 cuarenta
+50 cincuenta
+60 sesenta
+70 setenta
+80 ochenta
+90 noventa
+(\d)(\d) $(\10) y $2
+1(\d\d) cien[to $1]
+500 quinientos
+700 setecientos
+900 novecientos
+([579])(\d\d) $(\100) $2
+(\d)(\d\d) $1cientos[ $2]
+1(\d{3}) mil[ $1]
+(\d{1,3})(\d{3}) $1 mil[ $2]
+1(\d{6}) un millón[ $1]
+(\d{1,6})(\d{6}) $1 millones[ $2]
+1(\d{12}) un billón[ $1]
+(\d{1,6})(\d{12}) $1 billones[ $2]
+1(\d{18}) un trillón[ $1]
+(\d{1,6})(\d{18}) $1 trillones[ $2]
+1(\d{24}) un cuatrillón[ $1]
+(\d{1,6})(\d{24}) $1 cuatrillones[ $2]
+1(\d{30}) un quintillón[ $1]
+(\d{1,6})(\d{30}) $1 quintillones[ $2]
+
+# negative number
+
+[-−](\d+) menos |$1
+
+# decimals
+
+([-−]?\d+)[.] $1| punto
+([-−]?\d+)[,] $1| coma
+([-−]?\d+[.,])([^0]\d) $1| |$2
+([-−]?\d+[.,])(\d)(\d)(\d) |$1 |$2| |$3| |$4
+([-−]?\d+[.,]\d*)(\d) $1| |$2
+
+# currency
+
+# unit/subunit singular/plural
+
+us:([^,]*),([^,]*),([^,]*),([^,]*) \1
+up:([^,]*),([^,]*),([^,]*),([^,]*) \2
+ss:([^,]*),([^,]*),([^,]*),([^,]*) \3
+sp:([^,]*),([^,]*),([^,]*),([^,]*) \4
+
+ARS:(\D+) $(\1: peso argentino, pesos argentinos, centavo, centavos)
+BOB:(\D+) $(\1: boliviano, bolivianos, centavo, centavos)
+BZD:(\D+) $(\1: dólar beliceño, dólares beliceños, centavo, centavos)
+CEC:(\D+) $(\1: peso convertible, pesos convertibles, centavo, centavos)
+CHF:(\D+) $(\1: franco suizo, francos suizos, céntimo, céntimos)
+CLP:(\D+) $(\1: peso chileno, pesos chilenos, centavo, centavos)
+CNY:(\D+) $(\1: yuan renminbi, yuan renminbi, fen, fen)
+COP:(\D+) $(\1: peso colombiano, pesos colombianos, centavo, centavos)
+CRC:(\D+) $(\1: colón costarricense, colones costarricenses, céntimo, céntimos)
+DOP:(\D+) $(\1: peso dominicano, pesos dominicanos, centavo, centavos)
+ESP:(\D+) $(\1: peseta, pesetas, céntimo, céntimos)
+EUR:(\D+) $(\1: euro, euros, céntimo, céntimos)
+GBP:(\D+) $(\1: libra esterlina, libras esterlinas, penique, peniques)
+GTQ:(\D+) $(\1: quetzal, quetzales, centavo, centavos)
+HLN:(\D+) $(\1: lempira, lempiras, centavo, centavos)
+JPY:(\D+) $(\1: yen, yenes, sen, sen)
+MXN:(\D+) $(\1: peso mexicano, pesos mexicanos, centavo, centavos)
+NIO:(\D+) $(\1: córdoba, córdobas, centavo, centavos)
+PEN:(\D+) $(\1: sol, soles, centavo, centavos)
+PYG:(\D+) $(\1: guaraní, guaraníes, céntimo, céntimos)
+USD:(\D+) $(\1: dólar estadounidense, dólares estadounidenses, centavo, centavos)
+UYU:(\D+) $(\1: peso uruguayo, pesos uruguayos, centésimo, centésimos)
+VEF:(\D+) $(\1: bolívar fuerte, bolívares fuertes, céntimo, céntimos)
+
+# masculine to feminine conversion of "un" after millions,
+# if "as?$" matches currency name
+
+f:(.*ill)(.*),(.*) \1$(f:\2,\3) # don't modify un in millions
+f:(.*un)([^a].*,|,)(.*as?) $(f:\1a\2\3) # un libra -> una libra
+f:(.*ient)o(s.*),(.*as?) $(f:\1a\2,\3) # doscientos libra/libras -> doscientas
+f:(.*),(.*) \1\2
+
+"([A-Z]{3}) ([-−]?[01])([.,]00?)?"$(f:|$2,$(\1:us))
+"([A-Z]{3}) ([-−]?\d+0{6,})([.,]00?)?" $2 de$(\1:up)
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?"$(f:|$2,$(\1:up))
+
+"(CNY [-−]?\d+)[.,]10?" $1 $2 jiao
+"(CNY [-−]?\d+)[.,](\d)0?" $1 $2 jiao
+"(CNY [-−]?\d+[.,]\d)1" $1 $2 fen
+"(CNY [-−]?\d+[.,]\d)(\d)" $1 $2 fen
+
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1 con |$(1)$(\2:ss)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 con |$(\30)$(\2:sp)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 con |$3$(\2:sp)
+
+# ordinal
+
+feminine:(.*un)o \1a
+feminine:(.*) \1
+
+== feminine ==
+
+(.*) $(feminine:|$1|)
+
+== masculine ==
+
+1 un
+(.*) $1
+
+== ordinal-masculine ==
+
+(.*) $(ordinal \1)
+
+== ordinal ==
+
+1 primero
+2 segundo
+3 tercero
+4 cuarto
+5 quinto
+6 sexto
+7 séptimo
+8 octavo
+9 noveno
+10 décimo
+1([1-79]) decimo$(ordinal \1)
+18 decimoctavo
+20 vigésimo
+2(\d) vigesimo$(ordinal \1)
+30 trigésimo
+40 cuadragésimo
+50 quincuagésimo
+60 sexagésimo
+70 septuagésimo
+80 octogésimo
+90 nonagésimo
+(\d)(\d) $(ordinal \10) $(ordinal \2)
+100 centésimo
+200 ducentésimo
+300 tricentésimo
+400 cuadringentésimo
+500 quingentésimo
+600 sexcentésimo
+700 septingentésimo
+800 octingentésimo
+900 noningentésimo
+(\d)(\d\d) $(ordinal \100) $(ordinal \2)
+1(\d{3}) milésimo[ $(ordinal \1)]
+(\d{1,3})(\d{3}) $1 milésimo[ $(ordinal \2)]
+1(\d{6}) millonésimo[ $(ordinal \1)]
+(\d{1,3})(\d{6}) $1 millonésimo[ $(ordinal \2)]
+1(\d{9}) milmillonésimo[ $(ordinal \1)]
+(\d{1,3})(\d{9}) $1 milmillonésimo[ $(ordinal \2)]
+
+== ordinal-feminine ==
+
+([-−]?\d+) $(ordinal-feminine $(ordinal-masculine \1))
+(.*)o\b(.*) $(ordinal-feminine \1a\2)
+(.*) \1
+
+== ordinal-masculine-adjective ==
+
+([-−]?\d+) $(ordinal-masculine-adjective $(ordinal-masculine \1))
+(.*)decimoprimero \1undécimo
+(.*)decimosegundo \1duodécimo
+(.*(primer|tercer))o \1
+(.*) \1
+
+# ordinal abbreviation
+
+== (ordinal)-number-(feminine|masculine|masculine-adjective) ==
+
+([-−]?\d+) \3$(ordinal-number-feminine $(\1-\2 \3))
+.*er .ᵉʳ
+.*a .ª
+.*o .º
+
+== help ==
+
+"" $(1)|, $(2), $(3)\n$(\0 feminine)$(\0 masculine)$(\0 ordinal-number-masculine)$(\0 ordinal-number-masculine-adjective)$(\0 ordinal-number-feminine)$(\0 ordinal-feminine)$(\0 ordinal-masculine)$(\0 ordinal-masculine-adjective)
+(feminine|masculine|ordinal(-number)?(-feminine|-masculine)?(-adjective)?) \1: $(\1 1), $(\1 2), $(\1 3)\n
diff --git a/data/fi.sor b/data/fi.sor
new file mode 100644
index 0000000..98184d7
--- /dev/null
+++ b/data/fi.sor
@@ -0,0 +1,146 @@
+^0 nolla
+1 yksi
+2 kaksi
+3 kolme
+4 neljä
+5 viisi
+6 kuusi
+7 seitsemän
+8 kahdeksan
+9 yhdeksän
+10 kymmenen
+1(\d) $1toista
+(\d)(\d) $1kymmentä$2
+1(\d\d) sata$1
+(\d)(\d\d) $1sataa$2
+1(\d{3}) tuhat$1
+(\d)(\d{3}) $1tuhatta$2
+(\d{2,3})(\d{3}) $1tuhatta[ $2]
+1(\d{6}) miljoona[ $1]
+(\d{1,3})(\d{6}) $1 miljoonaa[ $2]
+1(\d{9}) miljardi[ $1]
+(\d{1,3})(\d{9}) $1 miljardia[ $2]
+1(\d{12}) biljoona[ $1]
+(\d{1,3})(\d{12}) $1 biljoonaa[ $2]
+1(\d{15}) tuhat biljoona[ $1]
+(\d{1,3})(\d{15}) $1 tuhat biljoonaa[ $2]
+1(\d{18}) triljoona[ $1]
+(\d{1,3})(\d{18}) $1 triljoonaa[ $2]
+1(\d{21}) tuhat triljoona[ $1]
+(\d{1,3})(\d{21}) $1 tuhat triljoonaa[ $2]
+1(\d{24}) kvadriljoona[ $1]
+(\d{1,3})(\d{24}) $1 kvadriljoonaa[ $2]
+
+# negative numbers
+
+[-−](\d+) miinus |$1
+
+# decimals
+
+([-−]?\d+)[.,]([01]) |$1| ja |$2 kymmenesosa
+([-−]?\d+)[.,](\d) |$1| ja |$2 kymmenesosaa
+([-−]?\d+)[.,]0([01]) |$1| ja |$2 sadasosa
+([-−]?\d+)[.,](\d\d) |$1| ja |$2 sadasosaa
+([-−]?\d+)[.,]00([01]) |$1| ja |$2 tuhannesosa
+([-−]?\d+)[.,](\d\d\d) |$1| ja |$2 tuhannesosaa
+"([-−]?\d+)[.,](\d)(\d)(\d)(\d)" |$1| ja |$2| |$3| |$4| |$5|
+"([-−]?\d+[.,]\d+)(\d)" $1 |$2|
+
+# currency
+
+# unit/subunit singular/singular partitive
+
+us:([^,]*),([^,]*),([^,]*),([^,]*) \1
+up:([^,]*),([^,]*),([^,]*),([^,]*) \2
+ss:([^,]*),([^,]*),([^,]*),([^,]*) \3
+sp:([^,]*),([^,]*),([^,]*),([^,]*) \4
+
+AUD:(\D+) $(\1: Australian dollari, Australian dollaria, sentti, senttiä)
+CAD:(\D+) $(\1: Kanadan dollari, Kanadan dollaria, sentti, senttiä)
+CHF:(\D+) $(\1: Sveitsin frangi, Sveitsin frangia, rappeni, rappenia)
+CNY:(\D+) $(\1: juan renminbi, juan renminbia, feni, feniä)
+CYP:(\D+) $(\1: Kyproksen punta, Kyproksen puntaa, sentti, senttiä)
+CZK:(\D+) $(\1: Tšekin kruunu, Tšekin kruunua, haléři, haléřia)
+DKK:(\D+) $(\1: Tanskan kruunu, Tanskan kruunua, äyri, äyriä)
+EEK:(\D+) $(\1: Viron kruunu, Viron kruunua, sentti, senttiä)
+EUR:(\D+) $(\1: euro, euroa, sentti, senttiä)
+GBP:(\D+) $(\1: Englannin punta, Englannin puntaa, penni, pennia)
+HKD:(\D+) $(\1: Hongkongin dollari, Hongkongin dollaria, sentti, senttiä)
+HRK:(\D+) $(\1: Kroatian kuna, Kroatian kunaa, lipa, lipaa)
+HUF:(\D+) $(\1: Unkarin forintti, Unkarin forinttia, filléri, fillériä)
+IDR:(\D+) $(\1: Indonesian rupia, Indonesian rupiaa, seni, seniä)
+ISK:(\D+) $(\1: Islannin kruunu, Islannin kruunua, äyri, äyriä)
+JPY:(\D+) $(\1: Japanin jeni, Japanin jenia, seni, seniä)
+KRW:(\D+) $(\1: Etelä-Korean won, Etelä-Korean won, chon, chonia)
+LTL:(\D+) $(\1: Liettuan lita, Liettuan litiä, centasi, centasia)
+LVL:(\D+) $(\1: Latvian lati, Latvian latia, santiimi, santiimia)
+MYR:(\D+) $(\1: Malesian ringgit, Malesian ringgit, sentti, senttiä)
+NZD:(\D+) $(\1: Uuden-Seelannin dollari, Uuden-Seelannin dollaria, sentti, senttiä)
+NOK:(\D+) $(\1: Norjan kruunu, Norjan kruunua, äyri, äyriä)
+PHP:(\D+) $(\1: Filippiinien peso, Filippiinien peso, centavo, centavoa)
+PLN:(\D+) $(\1: Puolan złoty, Puolan złotya, groszy, groszya)
+RON:(\D+) $(\1: Romanian leu, Romanian leu, bani, bania)
+RUB:(\D+) $(\1: Venäjän rupla, Venäjän ruplaa, kopeekka, kopeekkaa)
+SEK:(\D+) $(\1: Ruotsin kruunu, Norjan kruunua, äyri, äyriä)
+SGD:(\D+) $(\1: Singaporen dollari, Singaporen dollaria, sentti, senttiä)
+THB:(\D+) $(\1: Thaimaan baht, Thaimaan bahtia, satang, satangia)
+TRY:(\D+) $(\1: Turkin liira, Turkin liiraa, kuruşi, kuruşia)
+USD:(\D+) $(\1: USA:n dollari, USA:n dollaria, sentti, senttiä)
+
+"(JPY [-−]?\d+)[.,](\d\d)0" $1
+"(JPY [-−]?\d+[.,]\d\d)1" $1 $2 rini
+"(JPY [-−]?\d+[.,]\d\d)(\d)" $1 $2 riniä
+
+"([A-Z]{3}) ([-−]?1)([.,]00?)?" $2$(\1:us)
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $2$(\1:up)
+
+# chiao?
+"(CNY [-−]?\d+)[.,]10?" $1 $2 chiao
+"(CNY [-−]?\d+)[.,](\d)0?" $1 $2 chiaota
+"(CNY [-−]?\d+[.,]\d)1" $1 $2 feni
+"(CNY [-−]?\d+[.,]\d)(\d)" $1 $2 feniä
+
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1 $(1)$(\2:ss)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 $(\30)$(\2:sp)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 $3$(\2:sp)
+
+== ordinal ==
+
+^0 nolla
+1 ensimmäinen
+2$ toinen
+2 kahdes
+3 kolmas
+4 neljäs
+5 viides
+6 kuudes
+7 seitsemäs
+8 kahdeksas
+9 yhdeksäs
+10 kymmenes
+11 yhdestoista
+12 kahdestoista
+1(\d) $(ordinal \1)toista
+(\d)(\d) $(ordinal \1)kymmenes$(ordinal \2)
+1(\d\d) sadas$(ordinal \1)
+(\d)(\d\d) $(ordinal \1)sadas$(ordinal \2)
+1(\d{3}) tuhannes$(ordinal \1)
+(\d)(\d{3}) $(ordinal \1)tuhannes$(ordinal \2)
+(\d{2,3})(\d{3}) $(ordinal \1)|tuhannes[ $(ordinal \2)]
+(\d)(\d{6}) $(ordinal \1)miljoonas[ $(ordinal \2)]
+(\d{2,3})(\d{6}) $(ordinal \1)| miljoonas[ $(ordinal \2)]
+(\d)(\d{6}) $(ordinal \1)miljoonas[ $(ordinal \2)]
+(\d{2,3})(\d{6}) $(ordinal \1)| miljoonas[ $(ordinal \2)]
+(\d)(\d{9}) $(ordinal \1)miljardis[ $(ordinal \2)]
+(\d{2,3})(\d{9}) $(ordinal \1)| miljardis[ $(ordinal \2)]
+(\d)(\d{12}) $(ordinal \1)biljoonas[ $(ordinal \2)]
+(\d{2,3})(\d{12}) $(ordinal \1)| biljoonas[ $(ordinal \2)]
+
+== ordinal-number ==
+
+(\d+) \1.
+
+== help ==
+
+"" $(1), $(2), $(3)\n$(help ordinal)$(help ordinal-number)
+(ordinal(-number)?) \1: $(\1 1), $(\1 2), $(\1 3)\n
diff --git a/data/fr.sor b/data/fr.sor
new file mode 100644
index 0000000..4883c2c
--- /dev/null
+++ b/data/fr.sor
@@ -0,0 +1,162 @@
+^0 zéro
+1 un
+2 deux
+3 trois
+4 quatre
+5 cinq
+6 six
+7 sept
+8 huit
+9 neuf
+10 dix
+11 onze
+12 douze
+13 treize
+14 quatorze
+15 quinze
+16 seize
+20 vingt
+30 trente
+40 quarante
+50 cinquante
+60 soixante
+
+71 septante et un # [:fr-CH:] [:fr-BE:]
+7(\d) septante[-$1] # [:fr-CH:] [:fr-BE:]
+71 soixante et onze # default
+7(\d) soixante-$(1\1) # default
+
+81 huitante et un # [:fr-CH:]
+8(\d) huitante[-$1] # [:fr-CH:]
+80$ quatre-vingts # default
+80 quatre-vingt # default
+81 quatre-vingt-un # default
+
+91 nonante et un # [:fr-CH:] [:fr-BE:]
+9(\d) nonante[-$1] # [:fr-CH:] [:fr-BE:]
+9(\d) quatre-vingt-$(1\1) # default
+
+(\d)1 $(\10) et un
+(\d)(\d) $(\10)-$2
+
+1(\d\d) cent[ $1]
+(\d)00$ $1 cents
+(\d)(\d\d) $1 cent[ $2]
+1100 onze cents
+11(\d\d) onze cent[ $1]
+1(\d{3}) mille[ $1]
+(\d{1,3})(\d{3}) $1 mille[ $2]
+1(\d{6}) un million[ $1]
+(\d{1,3})(\d{6}) $1| millions[ $2]
+1(\d{9}) un milliard[ $1]
+(\d{1,3})(\d{9}) $1| milliards[ $2]
+1(\d{12}) un billion[ $1]
+(\d{1,3})(\d{12}) $1| billions[ $2]
+1(\d{15}) un billiard[ $1]
+(\d{1,3})(\d{15}) $1| billiards[ $2]
+1(\d{18}) un trillion[ $1]
+(\d{1,3})(\d{18}) $1| trillions[ $2]
+1(\d{21}) un trilliard[ $1]
+(\d{1,3})(\d{21}) $1| trilliards[ $2]
+1(\d{24}) un quadrillion[ $1]
+(\d{1,3})(\d{24}) $1| quadrillions[ $2]
+
+# negative number
+
+[-−](\d+) moins |$1
+
+# decimals
+
+"([-−]?\d+)[.,]" "$1| virgule"
+"([-−]?\d+[.,]0*)(\d+)" $1 |$2
+
+# currency
+
+# unit/subunit singular/plural
+
+us:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \1
+up:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \2
+ud:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \3
+ss:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \4
+sp:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \5
+
+# masculine/feminine
+
+mf:.*un(e?) \1
+
+BIF:(\D+) $(\1: franc burundais, francs burundais, de francs burundais, centime, centimes, un)
+CAD:(\D+) $(\1: dollar canadien, dollars canadiens, de dollars canadiens, cent, cents, un)
+CDF:(\D+) $(\1: franc congolais, francs congolais, de francs congolais, centime, centimes, un)
+CHF:(\D+) $(\1: franc suisse, francs suisses, de francs suisses, centime, centimes, un)
+DJF:(\D+) $(\1: franc de Djibouti, francs de Djibouti, de francs de Djibouti, centime, centimes, un)
+DZD:(\D+) $(\1: dinar algérien, dinars algériens, de dinars algériens, centime, centimes, un)
+EUR:(\D+) $(\1: euro, euros, d’euros, centime, centimes, un)
+GBP:(\D+) $(\1: livre sterling, livres sterling, de livres sterling, penny, pennies, une)
+GNF:(\D+) $(\1: franc guinéen, francs guinéens, de francs guinéens,,, un)
+HTF:(\D+) $(\1: gourde, gourde, de gourde, centime, centimes, une)
+KMF:(\D+) $(\1: franc des Comores, francs des Comores, de francs des Comores, centime, centimes, un)
+LBP:(\D+) $(\1: livre libanaise, livres libanaises, de livres libanaises,,, une)
+MAD:(\D+) $(\1: dirham marocain, dirhams marocains, de dirhams marocains, centime, centimes, un)
+MGA:(\D+) $(\1: ariary, ariarys, d’ariarys, iraimbilanja, iraimbilanja, un)
+MRO:(\D+) $(\1: ouguiya, ouguiya, d’ouguiya, khoum, khoums, un)
+MUR:(\D+) $(\1: roupie mauricienne, roupies mauriciennes, de roupies mauriciennes, cent, cents, une)
+RWF:(\D+) $(\1: franc rwandais, francs rwandais, de francs rwandais, centime, centimes, un)
+SCR:(\D+) $(\1: roupie seychelloise, roupies seychelloises, de roupies seychelloise, cent, cents, une)
+TND:(\D+) $(\1: dinar tunisien, dinars tunisiens, de dinars tunisiens, millime, millimes, un)
+USD:(\D+) $(\1: dollar américain, dollars américains, de dollars américains, cent, cents, un)
+VUV:(\D+) $(\1: vatu, vatus, de vatus,,, un)
+X[AO]F:(\D+) $(\1: franc CFA, francs CFA, de francs CFA, centime, centimes, un)
+XPF:(\D+) $(\1: franc Pacifique, francs Pacifique, de francs Pacifique, centime, centimes, un)
+
+"(GNF|LBP|VUV) ([-−]?[01](.0+)?)" $2$(\1:us)
+"(GNF|LBP|VUV) ([-−]?\d+0{6,})" $2$(\1:ud)
+"(GNF|LBP|VUV) ([-−]?\d+[.,]\d+)" $2$(\1:up)
+
+"([A-Z]{3}) ([-−]?1)([.,]00?)?" $2$(\1:mf)$(\1:us) # un/une
+"([A-Z]{3}) ([-−]?\d*[02-9]1)([.,]00?)?" $2$(\1:mf)$(\1:up) # cent un/une mais pas cent onze
+"([A-Z]{3}) ([-−]?[0])([.,]00?)?" $2$(\1:us)
+"([A-Z]{3}) ([-−]?\d+0{6,})([.,]00?)?" $2$(\1:ud)
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $2$(\1:up)
+
+"((MGA|MRO) [-−]?\d+)[.,]0" $1
+"((MGA|MRO) [-−]?\d+)[.,]2" $1 et |$(1)$(\2:ss)
+"((MGA|MRO) [-−]?\d+)[.,]4" $1 et |$(2)$(\2:sp)
+"((MGA|MRO) [-−]?\d+)[.,]6" $1 et |$(3)$(\2:sp)
+"((MGA|MRO) [-−]?\d+)[.,]8" $1 et |$(4)$(\2:sp)
+
+"((TND) [-−]?\d+)[.,](001)" $1 et |$(1)$(\2:ss)
+"((TND) [-−]?\d+)[.,](\d)" $1 et |$(\300)$(\2:sp)
+"((TND) [-−]?\d+)[.,](\d\d)" $1 et |$(\30)$(\2:sp)
+"((TND) [-−]?\d+)[.,](\d\d\d)" $1 et |$3$(\2:sp)
+
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1 et |$(1)$(\2:ss)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 et |$(\30)$(\2:sp)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 et |$3$(\2:sp)
+
+== ordinal-feminine ==
+
+1 première
+
+== ordinal(-feminine|-masculine)? ==
+
+1 premier
+([-−]?\d+) $(ordinal |$2)
+
+(.*)e \2ième # quatre etc.
+(.*)f \2vième # neuf
+(.*q) \2uième # cinq
+(.*) \2ième # others
+
+== ordinal-number-feminine ==
+
+1 1ʳᵉ
+
+== ordinal-number(-feminine|-masculine)? ==
+
+1 1ᵉʳ
+(\d+) \2ᵉ
+
+== help ==
+
+"" $(1), $(2), $(3)\n$(help ordinal)$(help ordinal-feminine)$(help ordinal-masculine)$(help ordinal-number-feminine)$(help ordinal-number-masculine)
+(ordinal(-feminine|-masculine|-number)?) \1: $(\1 1), $(\1 2), $(\1 3)\n
diff --git a/data/he.sor b/data/he.sor
new file mode 100644
index 0000000..000fb4f
--- /dev/null
+++ b/data/he.sor
@@ -0,0 +1,214 @@
+^0 אפס
+1 אחת
+2 שתיים
+3 שלוש
+4 ארבע
+5 חמש
+6 שש
+7 שבע
+8 שמונה
+9 תשע
+10 עשר
+12 שתים-עשרה
+1(\d) $1-עשרה
+
+20 עשרים
+50 חמישים
+60 שישים
+80 שמונים
+(\d)0 $1ים
+
+(\d)(\d) $(\10) ו$2
+
+# separator after 1-2 hundred(s)
+hs1:20 " ו" # מאה ועשרים
+hs1:(\d\d) $(hs:\1)
+
+# separator after 3+ hundreds
+hs:0+ # מאה
+hs:[01]\d " ו" # מאה ועשר
+hs:\d+ " " # מאה שלושים וחמש
+
+1(\d\d) מאה$(hs1:\1)$1
+2(\d\d) מאתיים$(hs1:\1)$1
+(\d)(\d\d) $(df:\1) מאות$(hs:\2)$2
+
+# separator after thousands+
+ts:0+ # אלף
+ts:0+\d\d " ו" # אלף ושלושים
+ts:\d+ " " # אלף מאה שלושים
+
+1(\d{3}) אלף$(ts:\1)$1
+2(\d{3}) אלפיים$(ts:\1)$1
+([3-9]|10)(\d{3}) $(dm2:\1) אלפים$(ts:\2)$2
+(\d{1,3})(\d{3}) $(m:$1) אלף$(ts:\2)$2
+
+1(\d{6}) מיליון$(ts:\1)$1
+2(\d{6}) שני מיליונים$(ts:\1)$1
+([3-9]|10)(\d{6}) $(m:$1) מיליונים$(ts:\2)$2
+(\d{1,3})(\d{6}) $(m:$1) מיליון$(ts:\2)$2
+
+1(\d{9}) מיליארד$(ts:\1)$1
+2(\d{9}) שני מיליארדים$(ts:\1)$1
+([3-9]|10)(\d{9}) $(m:$1) מיליארדים$(ts:\2)$2
+(\d{1,3})(\d{9}) $(m:$1) מיליארד$(ts:\2)$2
+
+1(\d{12}) טריליון$(ts:\1)$1
+2(\d{12}) שני טריליונים$(ts:\1)$1
+([3-9]|10)(\d{12}) $(m:$1) טריליונים$(ts:\2)$2
+(\d{1,3})(\d{12}) $(m:$1) טריליון$(ts:\2)$2
+
+1(\d{15}) קוודראליון$(ts:\1)$1
+2(\d{15}) שני קוודראליונים$(ts:\1)$1
+([3-9]|10)(\d{15}) $(m:$1) קוודראליונים$(ts:\2)$2
+(\d{1,3})(\d{15}) $(m:$1) קוואדראליון$(ts:\2)$2
+
+1(\d{18}) קווינטיליון$(ts:\1)$1
+2(\d{18}) שני קווינטיליונים$(ts:\1)$1
+([3-9]|10)(\d{18}) $(m:$1) קווינטיליונים$(ts:\2)$2
+(\d{1,3})(\d{18}) $(m:$1) קווינטיליון$(ts:\2)$2
+
+1(\d{21}) סקסטיליון$(ts:\1)$1
+2(\d{21}) שני סקסטיליונים$(ts:\1)$1
+([3-9]|10)(\d{21}) $(m:$1) סקסטיליונים$(ts:\2)$2
+(\d{1,3})(\d{21}) $(m:$1) סקסטיליון$(ts:\2)$2
+
+1(\d{24}) ספטיליון$(ts:\1)$1
+2(\d{24}) שני ספטיליונים$(ts:\1)$1
+([3-9]|10)(\d{24}) $(m:$1) ספטיליונים$(ts:\2)$2
+(\d{1,3})(\d{24}) $(m:$1) ספטיליון$(ts:\2)$2
+
+
+# negative number
+
+[-−](\d+) מינוס |$1
+
+# decimals
+
+"([-−]?\d+)[.,]" $1| נקודה
+"([-−]?\d+[.,])([1-9]\d)" $1| |$2
+"([-−]?\d+[.,])(\d)(\d)(\d)" $1| |$2 |$3 |$4
+"([-−]?\d+[.,]\d*)(\d)" $1| |$2
+
+# feminine->masculine correction, as all numbers are given for feminine gender
+
+m:(.*)אחת \1אחד
+m:(.*)שתיים \1שניים
+m:(.*)חמש \1חמישה
+m:(.*)שש \1שישה
+m:(.*)(שלוש|ארבע|שבע|תשע|עשר) \1\2ה
+
+m:(.*)אחת-עשרה \1אחד-עשר
+m:(.*)שתים-עשרה \1שנים-עשר
+m:(.*)חמש-עשרה \1חמישה-עשר
+m:(.*)שש-עשרה \1שישה-עשר
+m:(.*)(שלוש|ארבע|שבע|תשע)-עשרה \1\2ה-עשר
+
+[fm]:(.*) \1
+
+# numbers dependent on what they count
+
+df:(.*)2 $1שתי
+
+dm:1 אחד
+dm:2 שני
+
+# more rarely used
+dm2:8 שמונת
+dm2:(\d|10) $1ת
+dm2:(.*) $(dm:\1)
+
+d([fm]):(1(0{24}|0{21}|0{18}|0{15}|0{12}|0{9}|0{6}|0{3})) $(m:$2)
+d([fm]):20{24} שני ספטיליוני
+d([fm]):(\d{1,3})0{24} $(m:$2) ספטיליוני
+d([fm]):20{21} שני סקסטיליוני
+d([fm]):(\d{1,3})0{21} $(m:$2) סקסטיליוני
+d([fm]):20{18} שני קווינטיליוני
+d([fm]):(\d{1,3})0{18} $(m:$2) קווינטיליוני
+d([fm]):20{15} שני קוודראליוני
+d([fm]):(\d{1,3})0{15} $(m:$2) קוודראליוני
+d([fm]):20{12} שני טריליוני
+d([fm]):(\d{1,3})0{12} $(m:$2) טריליוני
+d([fm]):20{9} שני מיליארדי
+d([fm]):(\d{1,3})0{9} $(m:$2) מיליארדי
+d([fm]):20{6} שני מיליוני
+d([fm]):(\d{1,3})0{6} $(m:$2) מיליוני
+d([fm]):20{3} אלפיים
+d([fm]):(\d{1,3})0{3} $(dm2:\2) אלפים
+d([fm]):(.*) $(\1:$2)
+
+# numbers independent on what they count
+
+i([fm]):(.*)[.,](.*) $(\1:$2) נקודה
+i([fm]):(.*) $(\1:$2)
+
+
+# currency
+
+# gender unit, gender subunit, unit singular, unit, plural, subunit singular, subunit, plural
+
+us(.).:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \2 $(\1:\6)
+up(.).:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) $(\1:\6) \3
+ss.(.):([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \4 $(\1:\6)
+sp.(.):([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) $(\1:\6) \5
+
+# "mm" means masculine unit and masculine subunit
+
+CHF:(.+),(.+) $(\1mm:פרנק שוויצרי,פרנקים שוויצריים,סנט,סנטים,\2)
+CNY:(.+),(.+) $(\1mm:יואן,יואנים,פן,פנים,\2)
+EUR:(.+),(.+) $(\1mm:אירו,אירו,סנט,סנטים,\2)
+GBP:(.+),(.+) $(\1fm:לירה סטרלינג,לירות סטרלינג,פני,פנים,\2)
+ILS:(.+),(.+) $(\1mf:שקל,שקלים,אגורה,אגורות,\2)
+JPY:(.+),(.+) $(\1mm:יין,יינים,סן,סנים,\2)
+USD:(.+),(.+) $(\1mm:דולר ארה"ב,דולרים ארה"ב,סנט,סנטים,\2)
+
+"([A-Z]{3}) ([-−]?1)([.,]00?)?" $(\1:us,|$(dm:\2))
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $(\1:up,|$(dm:\2))
+
+"(CNY [-−]?\d+)[.,]10?" $1| ז'יאו אחד
+"(CNY [-−]?\d+)[.,](\d)0?" $1| $2| ז'יאו
+"(CNY [-−]?\d+[.,]\d)1" $1| $2| פן
+"(CNY [-−]?\d+[.,]\d)(\d)" $1| $2| פן
+
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1| ו$(\2:ss,$(1))
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1| ו$(\2:sp,$(\30))
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1| ו$(\2:sp,$3)
+
+# ordinal numbers: in hebrew, they depend on gender
+
+# transform a number to a feminine ordinal
+
+"ordinal-masculine (\d+)" $(ordm:\1)
+
+ordm:1 ראשון
+ordm:2 שני
+ordm:3 שלישי
+ordm:4 רביעי
+ordm:5 חמישי
+ordm:6 שישי
+ordm:7 שביעי
+ordm:8 שמיני
+ordm:9 תשיעי
+ordm:10 עשירי
+
+# transform a number to a masculine ordinal
+
+"ordinal-feminine (\d+)" $(ordf:\1)
+
+ordf:1 ראשונה
+ordf:2 שניה
+ordf:([3-9]|10) $(ordm:\1)ת
+
+# other numbers
+ord([fm]):(\d+) $(\1:$2)
+
+# from the end ;)
+"ordinal-(f|m)(eminine|asculine) [-−]?(\d+)" $(ord\1:\2) מהסוף
+
+# ordinal abbreviation: no such thing
+"ordinal-number(-feminine|-masculine)? ([-−]?\d+)" $(ordinal\1 \2)
+
+# masculine assumption
+"ordinal ([-−]?\d+)" $(ordinal-masculine \1)
+
+help פונקציות נוספות:\nord, ordm \(מספר סידורי זכר, כגון "ראשון"\)\nordf \(מספר סידורי נקבה, כגון "ראשונה"\)
diff --git a/data/hr.sor b/data/hr.sor
new file mode 100644
index 0000000..2909b51
--- /dev/null
+++ b/data/hr.sor
@@ -0,0 +1,186 @@
+#
+# Regular number to text transducer for Serbian (Cyrillic) written in Soros
+# Copyright (c) Goran Rakic <grakic@devbase.net> 2009.
+# Modified and translated for Croatian by Mihovil Stanic <mihovil.stanic@gmail.com> 2014.
+#
+# Released under Creative Commons 3.0 Attribution - Share Alike license
+# and relicensed under GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Visit http://numbertext.org for more info on Soros language and syntax
+#
+
+(\d{1,3})\.([\d.,]+) $(\1\2)
+
+^0 nula
+1 jedan
+2 dva
+3 tri
+4 četiri
+5 pet
+6 šest
+7 sedam
+8 osam
+9 devet
+10 deset
+
+11 jedanaest
+14 četrnaest
+16 šesnaest
+1(\d) $1naest
+
+4(\d) četrdeset[ $1]
+5(\d) pedeset[ $1]
+6(\d) šezdeset[ $1]
+9(\d) devedeset[ $1]
+(\d)(\d) $1deset[ $2]
+
+1(\d\d) sto[ $1]
+2(\d\d) dvjesto[ $1]
+3(\d\d) tristo[ $1]
+(\d)(\d\d) $1sto[ $2]
+
+1(\d\d\d) tisuću[ $1]
+2(\d\d\d) dvije tisuće[ $1]
+([34])(\d\d\d) $1 tisuće[ $2]
+(\d{0,1})1(\d)(\d\d\d) $(\11\2) tisuća[ $3]
+(\d{1,2})1(\d\d\d) $(\10) jedna tisuća[ $2]
+(\d{1,2})2(\d\d\d) $(\10) dvije tisuće[ $2]
+(\d{1,2})([34])(\d\d\d) $(\10) $2 tisuće[ $3]
+(\d{1,3})(\d\d\d) $1 tisuća[ $2]
+
+1(\d{6}) milion[ $1]
+(\d{0,4})1(\d)(\d{6}) $(\11\2) miliona[ $3]
+(\d{1,5})1(\d{6}) $(\10) jedan milion[ $2]
+(\d{1,3})(\d{6}) $1 miliona[ $2]
+
+1(\d{9}) milijarda[ $1]
+2(\d{9}) dvije milijarde[ $1]
+([34])(\d{9}) $1 milijarde[ $2]
+(\d{1,2})0(\d{9}) $(\10) milijardi[ $2]
+(\d{0,1})1(\d)(\d{9}) $(\11\2) milijardi[ $3]
+(\d{1,2})1(\d{9}) $(\10) jedna milijarda[ $2]
+(\d{1,2})2(\d{9}) $(\10) dvije milijarde[ $2]
+(\d{1,2})([34])(\d{9}) $(\10) $2 milijarde[ $3]
+(\d{1,3})(\d{9}) $1 milijarde[ $2]
+
+1(\d{12}) bilijun[ $1]
+(\d{0,4})1(\d)(\d{12}) $(\11\2) bilijuna[ $3]
+(\d{1,5})1(\d{12}) $(\10) jedan bilijun[ $2]
+(\d{1,6})(\d{12}) $1 bilijuna[ $2]
+
+1(\d{18}) trilijun[ $1]
+(\d{0,4})1(\d)(\d{18}) $(\11\2) trilijuna[ $3]
+(\d{1,5})1(\d{18}) $(\10) jedan trilijun[ $2]
+(\d{1,6})(\d{18}) $1 trilijuna[ $2]
+
+1(\d{24}) kvadrilijun[ $1]
+(\d{0,4})1(\d)(\d{24}) $(\11\2) kvadrilijuna[ $3]
+(\d{1,5})1(\d{24}) $(\10) jedan kvadrilijun[ $2]
+(\d{1,6})(\d{24}) $1 kvadrilijuna[ $2]
+
+1(\d{30}) kvintilijun[ $1]
+(\d{0,4})1(\d)(\d{30}) $(\11\2) kvintilijuna[ $3]
+(\d{1,5})1(\d{30}) $(\10) jedan kvintilijun[ $2]
+(\d{1,6})(\d{30}) $1 kvintilijuna[ $2]
+
+1(\d{36}) sekstilijun[ $1]
+(\d{0,4})1(\d)(\d{36}) $(\11\2) sekstilijuna[ $3]
+(\d{1,5})1(\d{36}) $(\10) jedan sekstilijun[ $2]
+(\d{1,6})(\d{36}) $1 sekstilijuna[ $2]
+
+# negative number
+
+[-−] minus
+[-−](\d+) minus |$1
+
+# Decimal code by https://twitter.com/_uranium_
+"([-−]?\d+)[.,]" $1| zarez
+"([-−]?\d+[.,])([^0]\d)" $1 $2
+"([-−]?\d+[.,]\d*[1-9]?)0+$" $1
+"([-−]?\d+[.,])(\d)(\d)(\d)" $1| |$2 |$3 |$4
+"([-−]?\d+[.,]\d*)(\d)" $1 |$2
+
+# currency
+
+# unit/subunit
+
+us:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \1
+up:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \2
+ug:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \3
+ss:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \4
+sp:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \5
+sg:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \6
+
+HRK:(\D+) $(\1: kuna, kune, kuna, lipa, lipe, lipa) #ff
+DKK:(\D+) $(\1: kruna, krune, kruna, ora, ore, ora) #ff
+SEK:(\D+) $(\1: kruna, krune, kruna, ora, ore, ora) #ff
+CZK:(\D+) $(\1: kruna, krune, kruna, haler, halera, halera) #fm
+HUF:(\D+) $(\1: forinta, forinte, forinti, filer, filera, filera) #fm
+GBP:(\D+) $(\1: funta, funte, funti, peni, penija, penija) #fm
+BAM:(\D+) $(\1: konvertibilna marka, konvertibilne marke, konvertibilnih marki, fening, feninga, feninga) #fm
+BGN:(\D+) $(\1: lev, leva, leva, stotinka, stotinke, stotinki) #mf
+RSD:(\D+) $(\1: dinar, dinara, dinara, para, pare, para) #mf
+RON:(\D+) $(\1: leu, leu, leu, ban, bana, bana) #mm
+CHF:(\D+) $(\1: franak, franka, franaka, centim, centima, centima) #mm
+EUR:(\D+) $(\1: euro, eura, eura, cent, centa, centa) #mm
+USD:(\D+) $(\1: dolar, dolara, dolara, cent, centa, centa) #mm
+PLN:(\D+) $(\1: zlot, zlota, zlota, groš, groša, groša) #mm
+
+# Covers cases where currency sign is after numbers or different position
+"(.*) kn" $(HRK \1)
+"(.*) €" $(EUR \1)
+"(.*)€" $(EUR \1)
+"€(.*)" $(EUR \1)
+"€ (.*)" $(EUR \1)
+"(.*) Ft" $(HUF \1)
+"(.*) din." $(RSD \1)
+"\$(.*)" $(USD \1)
+"\$ (.*)" $(USD \1)
+"(.*) \$" $(USD \1)
+"KM(.*)" $(BAM \1)
+"£(.*)" $(GBP \1)
+"(.*) HRK" $(HRK \1)
+"(.*) DKK" $(DKK \1)
+"(.*) SEK" $(SEK \1)
+"(.*) CZK" $(CZK \1)
+"(.*) HUF" $(HUF \1)
+"(.*) GBP" $(GBP \1)
+"(.*) BAM" $(BAM \1)
+"(.*) BGN" $(BGN \1)
+"(.*) RSD" $(RSD \1)
+"(.*) RON" $(RON \1)
+"(.*) CHF" $(CHF \1)
+"(.*) EUR" $(EUR \1)
+"(.*) USD" $(USD \1)
+"(.*) PLN" $(PLN \1)
+
+"(HRK|DKK|SEK|CZK|HUF|GBP|BAM) ([-−]?1)([.,]00?)?" jedna$(\1:us) #female, for 1
+"(HRK|DKK|SEK|CZK|HUF|GBP|BAM) ([-−]?2)([.,]00?)?" dvije$(\1:up) #female, for 2
+"(HRK|DKK|SEK|CZK|HUF|GBP|BAM) ([02-9])1([.,]00?)?" $(\20) jedna$(\1:us) #female, for numbers from 21-91 ending with 1
+"(HRK|DKK|SEK|CZK|HUF|GBP|BAM) ([02-9])2([.,]00?)?" $(\20) dvije$(\1:up) #female, for numbers from 22-92 ending with 2
+"(HRK|DKK|SEK|CZK|HUF|GBP|BAM) ([-−]?\d*)([02-9])1([.,]00?)?" $(\200) $(\30) jedna$(\1:us) #female, for numbers >100 ending with 1 but not 11
+"(HRK|DKK|SEK|CZK|HUF|GBP|BAM) ([-−]?\d*)([02-9])2([.,]00?)?" $(\200) $(\30) dvije$(\1:up) #female, for numbers >100 ending with 2 but not 12
+"([A-Z]{3}) ([-−]?1)([.,]00?)?" $2|$(\1:us)
+"([A-Z]{3}) ([-−]?\d*[02-9]1)([.,]00?)?" $2|$(\1:us)
+"([A-Z]{3}) ([-−]?[234])([.,]00?)?" $2|$(\1:up)
+"([A-Z]{3}) ([-−]?\d*[02-9][234])([.,]00?)?" $2|$(\1:up)
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $2|$(\1:ug)
+
+"((HRK|DKK|SEK|BGN|RSD) [-−]?\d+)[.,]([02-9])1" $1 $(\30) jedna $(\2:ss) #decimal, female, ending with 1 but not 11
+"((HRK|DKK|SEK|BGN|RSD) [-−]?\d+)[.,]([02-9])2" $1 $(\30) dvije $(\2:sp) #decimal, female, ending with 2 but not 12
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1 |$(1)$(\2:ss)
+"(([A-Z]{3}) [-−]?\d+)[.,]([02-9]1)" $1 |$3$(\2:ss)
+"(([A-Z]{3}) [-−]?\d+)[.,]([02-9][234])" $1 |$3$(\2:sp)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 |$(\30)$(\2:sg)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 |$3$(\2:sg)
+
+== ordinal-number ==
+
+(\d+) \1.
+
+== help ==
+
+"" |$(1)|, |$(2)|, |$(3)|\n$(help ordinal-number)
+(.*) \1: |$(\1 1)|, |$(\1 2)|, |$(\1 3)|\n
diff --git a/data/hu.sor b/data/hu.sor
new file mode 100644
index 0000000..5546b96
--- /dev/null
+++ b/data/hu.sor
@@ -0,0 +1,175 @@
+^0 nulla
+1 egy
+2$ kettő
+2 két
+3 három
+4 négy
+5 öt
+6 hat
+7 hét
+8 nyolc
+9 kilenc
+10 tíz
+1(\d) tizen$1
+20 húsz
+2(\d) huszon$1
+3(\d) harminc$1
+4(\d) negyven$1
+5(\d) ötven$1
+6(\d) hatvan$1
+7(\d) hetven$1
+8(\d) nyolcvan$1
+9(\d) kilencven$1
+1(\d\d) száz$1
+(\d)(\d\d) $1száz$2
+11(\d{2}) ezeregy$(1\1)
+1(\d{3}) ezer$1
+
+(\d{1,3})(\d{3}) $1ezer[-$2]
+(\d{1,3})(\d{6}) $1millió[-$2]
+(\d{1,3})(\d{9}) $1milliárd[-$2]
+(\d{1,3})(\d{12}) $1billió[-$2]
+(\d{1,3})(\d{15}) $1billiárd[-$2]
+(\d{1,3})(\d{18}) $1trillió[-$2]
+(\d{1,3})(\d{21}) $1trilliárd[-$2]
+
+# negative numbers
+
+[-−](\d+) mínusz |$1
+
+# decimals
+
+"([-−]?\d+)[.,](\d)" |$1| egész |$2 tized
+"([-−]?\d+)[.,](\d\d)" |$1| egész |$2 század
+"([-−]?\d+)[.,](\d{3})" |$1| egész |$2 ezred
+"([-−]?\d+)[.,](\d)(\d)(\d)(\d)" |$1| egész |$2| |$3| |$4| |$5|
+"([-−]?\d+[.,]\d+)(\d)" $1 |$2|
+
+# currency
+
+# unit/subunit
+
+u:([^,]*),([^,]*) \1
+s:([^,]*),([^,]*) \2
+
+AUD:(.) $(\1: ausztrál dollár, cent)
+BGN:(.) $(\1: bolgár leva, sztotinka)
+BRL:(.) $(\1: brazil real, centavo)
+CAD:(.) $(\1: kanadai dollár, cent)
+CHF:(.) $(\1: svájci frank, rappen)
+CNY:(.) $(\1: kínai jüan, fen)
+CZK:(.) $(\1: cseh korona, haléř)
+DKK:(.) $(\1: dán korona, øre)
+EEK:(.) $(\1: észt korona, sent)
+EUR:(.) $(\1: euró, cent)
+GBP:(.) $(\1: font sterling, penny)
+HKD:(.) $(\1: hongkongi dollár, cent)
+HRK:(.) $(\1: horvát kuna, lipa)
+HUF:(.) $(\1: forint, fillér)
+ISK:(.) $(\1: izlandi korona, eyrir)
+JPY:(.) $(\1: japán jen, szen)
+KRW:(.) $(\1: dél-koreai von, cson)
+LTL:(.) $(\1: litván litas, centas)
+LVL:(.) $(\1: lett lat, santīm)
+MXN:(.) $(\1: mexikói peso, centavo)
+NOK:(.) $(\1: norvég korona, øre)
+NZD:(.) $(\1: új-zélandi dollár, cent)
+PLN:(.) $(\1: lengyel złoty, grosz)
+RON:(.) $(\1: román lej, bani)
+RSD:(.) $(\1: szerb dinár, para)
+RUB:(.) $(\1: orosz rubel, kopejka)
+SEK:(.) $(\1: svéd korona, öre)
+SGD:(.) $(\1: szingapúri dollár, cent)
+TRY:(.) $(\1: török líra, kuruş)
+UAH:(.) $(\1: ukrán hrivnya, kopijka)
+USD:(.) $(\1: USA-dollár, cent)
+ZAR:(.) $(\1: dél-afrikai rand, cent)
+
+"(JPY [-−]?\d+)[.,](\d\d)0" $1
+"(JPY [-−]?\d+[.,]\d\d)(\d)" $1 $2 rin
+
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $2$(\1:u)
+
+"(CNY [-−]?\d+)[.,](\d)0?" $1 $2 jiao
+"(CNY [-−]?\d+[.,]\d)(\d)" $1 $2 fen
+
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 $(\30)$(\2:s)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 $3$(\2:s)
+
+# Article a/az
+
+"(article |cardinal |formal ){3}(([a-zA-Z]+ )*1\d{2}([.,]\d*)?)" az $(formal \2)
+"(article |cardinal ){2}(([a-zA-Z]+ )*1(\d{3})*([.,]\d*)?)" az $2
+"(article |cardinal ){2}(([a-zA-Z]+ )*5.*)" az $2
+"(article |cardinal ){2}(.*)" a $2
+
+== article ==
+
+(1(\d{3}|\d{6})*) az \1
+(5.*) az \1
+(.*) a \1
+
+== ordinal ==
+
+1 első
+2 második
+"(([a-zA-Z]+ )*[-−]?\d+)" $(ordinal $1)
+
+(.*)nulla \1nulladik
+(.*)egy \1egyedik
+(.*)kettő \1kettedik
+(.*)három \1harmadik
+(.*)négy \1negyedik
+(.*)öt \1ötödik
+(.*)hat \1hatodik
+(.*)hét \1hetedik
+(.*)nyolc \1nyolcadik
+(.*)kilenc \1kilencedik
+(.*)tíz \1tizedik
+(.*)húsz \1huszadik
+(.*)harminc \1harmincadik
+(.*)(negy|öt|het|kilenc)ven \1\2venedik
+(.*)(hat|nyolc)van \1\2vanadik
+(.*)száz \1századik
+(.*)ezer \1ezredik
+(.*)illió \1illiomodik
+(.*)illiárd \1illiárdodik
+
+== formal ==
+
+"(([a-zA-Z]+ )*[-−]?\d+([.,]\d*)?)" $(formal |$1)
+(|.*-)((száz|ezer).*) $(formal \1egy\2)
+(.*)két(.*) $(formal \1kettő\2)
+(.*) \1
+
+== year ==
+
+# no hyphen in numbers
+
+"(([a-zA-Z]+ )*[-−]?\d+)" $(year |$1)
+(.*)-(.*) $(year \1\2)
+(.*) \1
+
+== cardinal ==
+
+(.*) $1
+
+== ordinal-number ==
+
+(.*) \1.
+
+== text ==
+
+(\d|10) $1
+(\d{2,4}) \1
+(\d{2,3})(\d{3}) \1 ezer[ $(text \2)]
+(\d{1,3})(\d{6}) \1 millió[ $(text \2)]
+(\d{1,4})(\d{9}) \1 milliárd[ $(text \2)]
+(\d{1,4})(\d{12}) \1 billió[ $(text \2)]
+(\d{1,4})(\d{15}) \1 billiárd[ $(text \2)]
+
+== help ==
+
+"" $(1)|, $(2)|, $(3)\n$(\0 ordinal)$(\0 ordinal-number)year: $(year 2001), $(year 2002)|, $(year 2003)\nformal: $(formal 100), $(formal 200), $(formal 1000)\ntext: $(text 1), $(text 12000), $(text 10000000000)\ncurrency \(for example, HUF\): $(HUF 2,5)\nformal HUF: $(formal HUF 102,5)
+"(ordinal(-number)?|USD)" \1: $(\1 1), $(\1 2), $(\1 3)\n
+
diff --git a/data/id.sor b/data/id.sor
new file mode 100644
index 0000000..d5d6a3d
--- /dev/null
+++ b/data/id.sor
@@ -0,0 +1,122 @@
+^0 nol
+1 satu
+2 dua
+3 tiga
+4 empat
+5 lima
+6 enam
+7 tujuh
+8 delapan
+9 sembilan
+10 sepuluh
+11 sebelas
+1(\d) $1 belas
+(\d)(\d) $1 puluh[ $2]
+1(\d\d) seratus[ $1]
+(\d)(\d\d) $1 ratus[ $2]
+1(\d{3}) seribu[ $1]
+(\d{1,3})(\d{3}) $1 ribu[ $2]
+# sejuta or setu juta etc.
+(\d{1,3})(\d{6}) $1 juta[ $2]
+(\d{1,3})(\d{9}) $1 miliar[ $2]
+(\d{1,3})(\d{12}) $1 triliun[ $2]
+(\d{1,3})(\d{15}) $1 kuadriliun[ $2]
+(\d{1,3})(\d{18}) $1 kuantiliun[ $2]
+(\d{1,3})(\d{21}) $1 sextiliun[ $2]
+(\d{1,3})(\d{24}) $1 septiliun[ $2]
+
+# negative numbers
+
+[-−](\d+) minus |$1
+
+# decimals
+
+"([-−]?\d+)[.,]" $1| koma
+"([-−]?\d+[.,]\d*)(\d)" $1| |$2
+
+# currency
+
+# unit/subunit
+
+u:(.*),(.*) \1
+s:(.*),(.*) \2
+
+AUD:(.) $(\1: dollar Australia, sen)
+BGN:(.) $(\1: lev, leva, stotinka, stotinki)
+BWP:(.) $(\1: pula, pula, thebe, thebe)
+CAD:(.) $(\1: dollar Kanada, sen)
+CHF:(.) $(\1: franc Swiss, sen)
+CNY:(.) $(\1: yuan, fen)
+CZK:(.) $(\1: koruna Czech, koruna Czech, halér, halére)
+EEK:(.) $(\1: kroon, kroonid, sen)
+EUR:(.) $(\1: euro, sen)
+GBP:(.) $(\1: pound sterling, penny)
+GHS:(.) $(\1: cedi Ghana, pesewas)
+GMD:(.) $(\1: dalasi, bututs)
+HKD:(.) $(\1: dollar Hongkong, sen)
+IDR:(.) $(\1: rupiah, sen)
+INR:(.) $(\1: rupee India, paisa)
+JMD:(.) $(\1: dollar Jamaika, sen)
+JPY:(.) $(\1: yen, sen)
+KRW:(.) $(\1: won, chon)
+KES:(.) $(\1: shilling Kenya, sen)
+LRD:(.) $(\1: dollar Liberia, sen)
+LSL:(.) $(\1: loti, sente)
+LTL:(.) $(\1: litas, sen)
+LVL:(.) $(\1: lats, sen)
+MGA:(.) $(\1: ariary, iraimbilanja)
+MUR:(.) $(\1: rupee Mauritius, sen)
+MXN:(.) $(\1: peso Meksiko, centavo)
+MWK:(.) $(\1: kwacha Malawi, tambala)
+NAD:(.) $(\1: dollar Namibia, sen)
+NGN:(.) $(\1: naira, kobo)
+NZD:(.) $(\1: dollar New Zealand, sen)
+PGK:(.) $(\1: kina, toea)
+PHP:(.) $(\1: peso Filipina, centavo)
+PKR:(.) $(\1: rupee Pakistan, paisa)
+PLN:(.) $(\1: zloty, grosz)
+RON:(.) $(\1: leu Romania, ban)
+RSD:(.) $(\1: dinar Serbia, para)
+RUB:(.) $(\1: ruble Russia, kopek)
+RWF:(.) $(\1: franc Rwanda, centime)
+SGD:(.) $(\1: dollar Singapura, sen)
+SLL:(.) $(\1: leone, sen)
+SZL:(.) $(\1: lilangeni, sen)
+THB:(.) $(\1: baht, satang)
+TRY:(.) $(\1: lira Turki, kurus)
+TTD:(.) $(\1: dollar Trinidad dan Tobago, sen)
+TZS:(.) $(\1: shilling Tanzania,sen)
+UAH:(.) $(\1: hryvnia, kopiyka)
+UGX:(.) $(\1: shilling Uganda, sen)
+USD:(.) $(\1: dolar Amerika, sen)
+ZAR:(.) $(\1: rand Afrika Selatan, sen)
+ZMK:(.) $(\1: kwacha Zambia, ngwee)
+ZWL:(.) $(\1: dollar Zimbabwe, sen)
+
+"(JPY [-−]?\d+)[.,](\d\d)0" $1
+"(JPY [-−]?\d+[.,]\d\d)(\d)" $1 $2 rin
+
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $2$(\1:u)
+
+"(CNY [-−]?\d+)[.,](\d)0?" $1 $2 yiao
+"(CNY [-−]?\d+[.,]\d)(\d)" $1 $2 fen
+
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 dan $(\30)$(\2:s)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 dan $3$(\2:s)
+
+== ordinal ==
+
+1 pertama
+(\d+) $(ordinal ke$1)
+"kesatu (.*)" kese\1
+(.*) \1
+
+== ordinal-number ==
+
+1 1
+(\d+) ke-\1
+
+== help ==
+
+"" $(1), $(2), $(3)\n$(help ordinal)$(help ordinal-number)
+(ordinal(-number)?) \1: $(\1 1), $(\1 2), $(\1 3)\n
diff --git a/data/it.sor b/data/it.sor
new file mode 100644
index 0000000..bd1c602
--- /dev/null
+++ b/data/it.sor
@@ -0,0 +1,148 @@
+^0 zero
+1 uno
+2 due
+^3$ tre
+3$ tré
+3 tre
+4 quattro
+5 cinque
+6 sei
+7 sette
+8 otto
+9 nove
+10 dieci
+11 undici
+12 dodici
+13 tredici
+14 quattordici
+15 quindici
+16 sedici
+17 diciassette
+18 diciotto
+19 diciannove
+2([18]) vent$1
+2(\d) venti$1
+3([18]) trent$1
+3(\d) trenta$1
+4([18]) quarant$1
+4(\d) quaranta$1
+5([18]) cinquant$1
+5(\d) cinquanta$1
+6([18]) sessant$1
+6(\d) sessanta$1
+7([18]) settant$1
+7(\d) settanta$1
+8([18]) ottant$1
+8(\d) ottanta$1
+9([18]) novant$1
+9(\d) novanta$1
+1(\d\d) cento$1
+(\d)(\d\d) $1cento$2
+1(\d{3}) mille$1
+(\d{1,2})(\d{3}) $1mila$2
+(\d{3})(\d{3}) $1mila[ $2]
+1(\d{6}) un milione[ $1]
+(\d{1,3})(\d{6}) $1 milioni[ $2]
+1(\d{9}) un miliardo[ $1]
+(\d{1,3})(\d{9}) $1 miliardi[ $2]
+1(\d{12}) un bilione[ $1]
+(\d{1,3})(\d{12}) $1 bilioni[ $2]
+1(\d{15}) un biliardo[ $1]
+(\d{1,3})(\d{15}) $1 biliardi[ $2]
+1(\d{18}) un trilione[ $1]
+(\d{1,3})(\d{18}) $1 trilioni[ $2]
+1(\d{21}) un triliardo[ $1]
+(\d{1,3})(\d{21}) $1 triliardi[ $2]
+
+# negative numbers
+
+[-−](\d+) meno |$1
+
+# decimals
+
+([-−]?\d+)[.,] $1| virgola
+([-−]?\d+[.,])([^0]\d) $1| |$2
+([-−]?\d+[.,])(\d)(\d)(\d) |$1 |$2| |$3| |$4
+([-−]?\d+[.,]\d*)(\d) $1| |$2
+
+# currencies
+
+# unit/subunit
+
+u:([^,]*),([^,]*),([^,]*) \1
+s:([^,]*),([^,]*),([^,]*) \2
+p:([^,]*),([^,]*),([^,]*) \3
+
+CHF:(.) $(\1: franco svizzero, centesimo, centesimi)
+CNY:(.) $(\1: yuan renminbi, fen, fen)
+EUR:(.) $(\1: euro, centesimo, centesimi)
+GBP:(.) $(\1: lira sterlina, penny, pence)
+JPY:(.) $(\1: yen, sen, sen)
+USD:(.) $(\1: dollaro USA, cent, cent)
+
+"(JPY [-−]?\d+)[.,](\d\d)0" $1
+"(JPY [-−]?\d+[.,]\d\d)(\d)" $1 $2 rin
+
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $2$(\1:u)
+
+"(CNY [-−]?\d+)[.,](\d)0?" $1 $2 jiao
+"(CNY [-−]?\d+[.,]\d)(\d)" $1 $2 fen
+
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1 uno$(\2:s)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 $(\30)$(\2:p)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 $3$(\2:p)
+
+== cardinal-feminine ==
+
+1 una
+
+== cardinal-masculine ==
+
+1 un
+
+== cardinal-(feminine|masculine) ==
+
+(.*) $(\1 $2)
+
+== feminine ==
+
+(.*)uno \1una
+
+== masculine ==
+
+(.*)uno \1un
+
+== (feminine|masculine) ==
+
+(.*) \2
+
+== ordinal-feminine ==
+
+([-−]?\d+) $(ordinal-feminine |$1)
+un[ao] \1prima
+due \1seconda
+tre \1terza
+quattro \1quarta
+cinque \1quinta
+sei \1sesta
+sette \1settima
+otto \1ottava
+nove \1nona
+dieci \1decima
+(.*tr)é \1eesima
+(.*sei) \1esima
+"(.*)[^ ][ ]*" \1esima
+
+== ordinal(-masculine)? ==
+([-−]?\d+) $(ordinal-masculine $(ordinal-feminine \2))
+(.*)a \2o
+
+== (ordinal)-number(-feminine|-masculine)? ==
+([-−]?\d+) \3$(ordinal-number $(\1\2 \3))
+.*a ª
+.*o º
+
+== help ==
+
+"" $(1), $(2), |$(3)|\n$(help cardinal-feminine)$(help cardinal-masculine)$(help ordinal-feminine)$(help ordinal-masculine)$(help ordinal-number-feminine)$(help ordinal-number-masculine)
+(.*) \1: $(\1 1), $(\1 2), |$(\1 3)|\n
diff --git a/data/ja.sor b/data/ja.sor
new file mode 100644
index 0000000..5811f1d
--- /dev/null
+++ b/data/ja.sor
@@ -0,0 +1,98 @@
+^0 零
+1 一
+2 二
+3 三
+4 四
+5 五
+6 六
+7 七
+8 八
+9 九
+1(\d) 十$1
+(\d)(\d) $1十$2
+1(\d\d) 百$1
+(\d)(\d\d) $1百$2
+1(\d\d\d) 千$1
+(\d)(\d\d\d) $1千$2
+(\d{1,4})(\d{4}) $1万$2
+(\d{1,4})(\d{8}) $1億$2
+(\d{1,4})(\d{12}) $1兆$2
+(\d{1,4})(\d{16}) $1京$2
+(\d{1,4})(\d{20}) $1垓$2
+(\d{1,4})(\d{24}) $1秭$2
+(\d{1,4})(\d{28}) $1穣$2
+(\d{1,4})(\d{32}) $1溝$2
+(\d{1,4})(\d{36}) $1澗$2
+(\d{1,4})(\d{40}) $1正$2
+(\d{1,4})(\d{44}) $1載$2
+
+# negative numbers?
+
+[-−](\d+) 负|$1
+
+# decimals?
+
+"([-−]?\d+)[.,]" "$1・"
+"([-−]?\d+[.,]\d*)(\d)" $1||$2
+
+# currency
+
+# unit/subunit singular/plural
+
+JPY 円
+
+"([A-Z]{3}) ([-−]?\d+([.,]\d+)?)" $2$1
+
+# formal numbers (大字) for legal and financial documents
+
+== formal ==
+
+^0 零
+1 壱
+2 弐
+3 参
+4 四
+5 五
+6 六
+7 七
+8 八
+9 九
+1(\d) 拾$(formal \1)
+(\d)(\d) $(formal \1)拾$(formal \2)
+1(\d\d) 百$(formal \1)
+(\d)(\d\d) $(formal \1)百$(formal \2)
+1(\d\d\d) 千$(formal \1)
+(\d)(\d\d\d) $(formal \1)千$(formal \2)
+(\d{1,4})(\d{4}) $(formal \1)万$(formal \2)
+(\d{1,4})(\d{8}) $(formal \1)億$(formal \2)
+(\d{1,4})(\d{12}) $(formal \1)兆$(formal \2)
+(\d{1,4})(\d{16}) $(formal \1)京$(formal \2)
+(\d{1,4})(\d{20}) $(formal \1)垓$(formal \2)
+(\d{1,4})(\d{24}) $(formal \1)秭$(formal \2)
+(\d{1,4})(\d{28}) $(formal \1)穣$(formal \2)
+(\d{1,4})(\d{32}) $(formal \1)溝$(formal \2)
+(\d{1,4})(\d{36}) $(formal \1)澗$(formal \2)
+(\d{1,4})(\d{40}) $(formal \1)正$(formal \2)
+(\d{1,4})(\d{44}) $(formal \1)載$(formal \2)
+
+# negative numbers?
+
+[-−](\d+) 负|$(formal \1)
+
+# decimals
+
+"([-−]?\d+)[.,]" "$(formal \1)・"
+"([-−]?\d+[.,]\d*)(\d)" $(formal \1)||$(formal \2)
+
+# currency
+
+# unit/subunit singular/plural
+
+JPY 円
+
+"([A-Z]{3}) ([-−]?\d+([.,]\d+)?)" $(formal \2)$(formal \1)
+
+== help ==
+
+"" |$(1)|, |$(2)|, |$(3)|\n$(help formal)
+(formal) \1: |$(\1 1)|, |$(\1 2)|, |$(\1 3)|\n
diff --git a/data/ko.sor b/data/ko.sor
new file mode 100644
index 0000000..cc4c3fd
--- /dev/null
+++ b/data/ko.sor
@@ -0,0 +1,55 @@
+^0 령 # [:ko-KP:]
+^0 영
+1 일
+2 이
+3 삼
+4 사
+5 오
+6 륙 # [:ko-KP:]
+6 육
+7 칠
+8 팔
+9 구
+1(\d) 십$1
+(\d)(\d) $1십$2
+1(\d\d) 백$1
+(\d)(\d\d) $1백$2
+1(\d\d\d) 천$1
+(\d)(\d\d\d) $1천$2
+(\d{1,4})(\d{4}) $1만$2
+(\d{1,4})(\d{8}) $1억$2
+(\d{1,4})(\d{12}) $1조$2
+(\d{1,4})(\d{16}) $1경$2
+(\d{1,4})(\d{20}) $1해$2
+(\d{1,4})(\d{24}) $1자$2
+(\d{1,4})(\d{28}) $1양$2
+(\d{1,4})(\d{32}) $1구$2
+(\d{1,4})(\d{36}) $1간$2
+(\d{1,4})(\d{40}) $1정$2
+(\d{1,4})(\d{44}) $1재$2
+(\d{1,4})(\d{52}) $1극$2
+
+# negative numbers?
+
+#[-−](\d+) 负|$1
+
+# decimals?
+
+#"([-−]?\d+)[.,]" "$1|点"
+#"([-−]?\d+[.,]\d*)(\d)" $1||$2
+
+# currency
+
+# unit/subunit
+
+u:([^,]*),([^,]*) \1
+s:([^,]*),([^,]*) \2
+
+CNY:(.) $(\1:런민비
+JPY:(.) $(\1:엔,센)
+KPW:(.) $(\1:조선민주주의인민공화국 원,전)
+KRW:(.) $(\1:대한민국 원,전)
+USD:(.) $(\1:미국 달러,센트)
+
+"([A-Z]{3}) ([-−]?\d+([.,]0+)?)" $2$(\1:u)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d+)" $1$3$(\2:s)
diff --git a/data/lb.sor b/data/lb.sor
new file mode 100644
index 0000000..d47640b
--- /dev/null
+++ b/data/lb.sor
@@ -0,0 +1,118 @@
+^0 null
+1$ eent
+1 een
+2 zwee
+3 dräi
+4 véier
+5 fënnef
+6 sechs
+7 siwen
+8 aacht
+9 néng
+10 zéng
+11 eelef
+12 zwielef
+15 fofzéng
+16 siechzéng
+17 siwwenzéng
+18 uechzéng
+19 nonzéng
+1(\d) $1zéng
+20 zwanzeg
+2(\d) $1anzwanzeg
+30 drësseg
+3(\d) $1andrësseg
+4(\d) $1avéierzeg
+50 foffzeg
+5(\d) $1afoffzeg
+60 siechzeg
+6(\d) $1asiechzeg
+70 siwwenzeg
+7(\d) $1asiwwenzeg
+80 achtzeg
+8(\d) $1anachtzeg
+90 nonzeg
+9(\d) $1annonzeg
+(\d)0 $1zeg
+(\d)(\d) $2an$1zeg
+1(\d\d) honnert$1
+(\d)(\d\d) $1honnert$2
+1(\d{3}) dausend$1
+(\d{1,3})(\d{3}) $1dausend$2
+1(\d{6}) eng Millioun[ $1]
+(\d{1,3})(\d{6}) $1 Milliounen[ $2]
+1(\d{9}) eng Milliard[ $1]
+(\d{1,3})(\d{9}) $1 Milliarden[ $2]
+1(\d{12}) eng Billioun[ $1]
+(\d{1,3})(\d{12}) $1 Billiounen[ $2]
+1(\d{15}) eng Billiard[ $1]
+(\d{1,3})(\d{15}) $1 Billiarden[ $2]
+1(\d{18}) eng Trillioun[ $1]
+(\d{1,3})(\d{18}) $1 Trilliounen[ $2]
+1(\d{21}) eng Trilliard[ $1]
+(\d{1,3})(\d{21}) $1 Trilliarden[ $2]
+
+# negative number
+
+[-−](\d+) minus |$1
+
+# decimals
+
+"([-−]?\d+)[.,]" $1| Komma
+"([-−]?\d+[.,]\d*)(\d)" $1| |$2
+
+# currency
+
+# unit/subunit singular/plural
+
+us:([^,]*),([^,]*),([^,]*),([^,]*) \1
+up:([^,]*),([^,]*),([^,]*),([^,]*) \2
+ss:([^,]*),([^,]*),([^,]*),([^,]*) \3
+sp:([^,]*),([^,]*),([^,]*),([^,]*) \4
+
+CHF:(\D+) $(\1: Schwäizer Frang, Schwäizer Frang, Rappen, Rappen)
+CNY:(\D+) $(\1: Yuan, Yuan, Fen, Fen)
+EUR:(\D+) $(\1: Euro, Euro, Cent, Cent)
+GBP:(\D+) $(\1: Pond Sterling, Pond Sterling, Penny, Pence)
+USD:(\D+) $(\1: US-Dollar, US-Dollar, Cent, Cents)
+
+"JPY ([-−]?\d+([.,]\d+)?)" $1 Yen
+
+"([A-Z]{3}) ([-−]?1)([.,]00?)?" $2$(\1:us)
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $2$(\1:up)
+
+"(CNY [-−]?\d+)[.,]10?" $1 $2 Jiao
+"(CNY [-−]?\d+)[.,](\d)0?" $1 $2 Jiao
+"(CNY [-−]?\d+[.,]\d)1" $1 $2 Fen
+"(CNY [-−]?\d+[.,]\d)(\d)" $1 $2 Fen
+
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1 an $(1)$(\2:ss)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 an $(\30)$(\2:sp)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 an $3$(\2:sp)
+
+== ordinal ==
+
+([-−]?[0245679]) $1t
+([-−]?\d*0[245679]) $1t
+([-−]?\d*1\d) $1t
+([-−]?\d+) $(ordinal $1)
+
+(.*)eent \1éischt
+(.*)dräi \1drëtt
+(.*)aacht \1aacht
+"(.*)eine Milli(on|ard)e?" \1einmilli\2st
+"(.*)eine Billi(on|ard)e?" \1einbilli\2st
+"(.*)eine Trilli(on|ard)e?" \1eintrilli\2st
+"(.*) Milli(on|ard)en" \1milli\2st
+"(.*) Billi(on|ard)en" \1billi\2st
+"(.*) Trilli(on|ard)en" \1trilli\2st
+(.*) \1st
+
+== ordinal-number ==
+
+(\d+) \1.
+
+== help ==
+
+"" |$(1)|, $(2), $(3)\n$(help ordinal)$(help ordinal-number)
+(ordinal(-number)?) \1: |$(\1 1)|, $(\1 2), $(\1 3)\n
diff --git a/data/lt.sor b/data/lt.sor
new file mode 100644
index 0000000..d6b4ecf
--- /dev/null
+++ b/data/lt.sor
@@ -0,0 +1,171 @@
+^0 nulis
+1 vienas
+2 du
+3 trys
+4 keturi
+5 penki
+6 šeši
+7 septyni
+8 aštuoni
+9 devyni
+10 dešimt
+11 vienuolika
+12 dvylika
+13 trylika
+14 keturiolika
+15 penkiolika
+16 šešiolika
+17 septyniolika
+18 aštuoniolika
+19 devyniolika
+
+2(\d) dvidešimt[ $1]
+3(\d) trisdešimt[ $1]
+([4-9])(\d) $1|asdešimt[ $2]
+
+1(\d\d) vienas šimtas[ $1]
+([2-9])(\d\d) $1 šimtai[ $2]
+
+1(\d{3}) vienas tūkstantis[ $1]
+(\d?1\d|\d?\d?0)(\d{3}) $1 tūkstančių[ $2]
+(\d?\d1)(\d{3}) $1 tūkstantis[ $2]
+(\d{1,3})(\d{3}) $1 tūkstančiai[ $2]
+
+(\d?1\d|\d?\d?0)(\d{6}) $1 milijonų[ $2]
+(\d?\d?1)(\d{6}) $1 milijonas[ $2]
+(\d{1,3})(\d{6}) $1 milijonai[ $2]
+
+(\d?1\d|\d?\d?0)(\d{9}) $1 milijardų[ $2]
+(\d?\d?1)(\d{9}) $1 milijardas[ $2]
+(\d{1,3})(\d{9}) $1 milijardai[ $2]
+
+(\d?1\d|\d?\d?0)(\d{12}) $1 trilijonų[ $2]
+(\d?\d?1)(\d{12}) $1 trilijonas[ $2]
+(\d{1,3})(\d{12}) $1 trilijonai[ $2]
+
+(\d?1\d|\d?\d?0)(\d{15}) $1 kvadrilijonų[ $2]
+(\d?\d?1)(\d{15}) $1 kvadrilijonas[ $2]
+(\d{1,3})(\d{15}) $1 kvadrilijonai[ $2]
+
+(\d?1\d|\d?\d?0)(\d{18}) $1 kvintilijonų[ $2]
+(\d?\d?1)(\d{18}) $1 kvintilijonas[ $2]
+(\d{1,3})(\d{18}) $1 kvintilijonai[ $2]
+
+# negative numbers
+
+[-−](\d+) minus |$1
+
+# decimals
+# before delimiter
+([-−]?(1|\d*[02-9]1))[.,] $1| sveikas
+([-−]?\d*[2-9])[.,] $1| sveiki
+(0|[-−]?\d*(1[1-9]|[1-9]0))[.,] $1| sveikų
+
+# atfer delimiter
+"([-−]?\d+[.,])(1)" $1| ir |$(f:$2) dešimtoji
+"([-−]?\d+[.,])([2-9])" $1| ir |$(f:$2) dešimtosios
+"([-−]?\d+[.,])([02-9]1)" $1| ir |$(f:$2) šimtoji
+"([-−]?\d+[.,])(1[1-9]|[1-9]0)" $1| ir |$(f:$2) šimtųjų
+"([-−]?\d+[.,])([02-9][2-9])" $1| ir |$(f:$2) šimtosios
+"([-−]?\d+[.,])(\d[02-9]1)" $1| ir |$(f:$2) tūkstantoji
+"([-−]?\d+[.,])(\d1[1-9]|[1-9]0)" $1| ir |$(f:$2) tūkstantųjų
+"([-−]?\d+[.,])(\d[02-9][2-9])" $1| ir |$(f:$2) tūkstantosios
+
+# female conversion
+f:(.*)as \1a
+f:(.*)du \1dvi
+f:(.*)i \1ios
+f:(.*) \1
+
+# currency
+# unit/subunit singular/plural_a/plural_b
+us:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \1
+upa:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \2
+upb:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \3
+ss:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \4
+spa:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \5
+spb:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \6
+
+LTL:(\D+) $(\1: litas, litų, litai, centas, centų, centai)
+EUR:(\D+) $(\1: euras, eurų, eurai, euro centas, euro centų, euro centai)
+USD:(\D+) $(\1: doleris, dolerių, doleriai, centas, centų, centai)
+NOK:(\D+) $(\1: Norvegijos krona, Norvegijos kronų, Norvegijos kronos, erė, erių, erės)
+SEK:(\D+) $(\1: Švedijos krona, Švedijos kronų, Švedijos kronos, erė, erių, erės)
+GBP:(\D+) $(\1: svaras sterlingų, svarų sterlingų, svarai sterlingų, pensas, pensų, pensai)
+RUB:(\D+) $(\1: rublis, rublių, rubliai, kapeika, kapeikų, kapeikos)
+
+# female gender
+# before delimiter
+"(NOK|SEK) ([-−]?(1|\d*[02-9]1))([.,]00?)?" $(f:$2)|$(\1:us) # 1| *01| *21 ...
+"(NOK|SEK) ([-−]?(0|\d*(1[1-9]|[01-9]0)))([.,]00?)?" $2|$(\1:upa) # 0 | *11| *19| *10| *30 ...
+"(NOK|SEK) ([-−]?\d*[2-9])([.,]00?)?" $(f:$2)|$(\1:upb) # *2| *8 ...
+
+# atfer delimiter
+"((NOK|SEK|RUB) [-−]?\d+)[.,](01)" $1| ir |$(f:$(1))$(\2:ss) # *,01 convertion to *,1
+"((NOK|SEK|RUB) [-−]?\d+)[.,]([2-9]1)" $1| ir |$(f:$3)|$(\2:ss) # 21, 51, 91 ...
+"((NOK|SEK|RUB) [-−]?\d+)[.,](\d)" $1| ir |$(\30)$(\2:spa) # *,2 | *,3 ... convertion to *,20 | *,30 ...
+"((NOK|SEK|RUB) [-−]?\d+)[.,](1[1-9])" $1| ir |$3|$(\2:spa) # 11-19
+"((NOK|SEK|RUB) [-−]?\d+)[.,](\d\d)" $1| ir |$(f:$3)$(\2:spb) # all the rest
+
+# male gender (all except female gender filter matches)
+# before delimiter
+"([A-Z]{3}) ([-−]?(1|\d*[02-9]1))([.,]00?)?" $2|$(\1:us)
+"([A-Z]{3}) ([-−]?0|\d*(1[1-9]|[01-9]0))([.,]00?)?" $2|$(\1:upa)
+"([A-Z]{3}) ([-−]?\d*[2-9])([.,]00?)?" $2|$(\1:upb)
+
+# atfer delimiter
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1| ir |$(1)$(\2:ss)
+"(([A-Z]{3}) [-−]?\d+)[.,]([2-9]1)" $1| ir |$3|$(\2:ss)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1| ir |$(\30)$(\2:spa)
+"(([A-Z]{3}) [-−]?\d+)[.,](1[1-9])" $1| ir |$3|$(\2:spa)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1| ir |$3$(\2:spb)
+
+== feminine ==
+
+([-−]?\d+) $(feminine $1)
+(.*)vienas \1viena
+(.*)du \1dvi
+(.*)i \1ios
+
+== masculine ==
+
+([-−]?\d+) $1
+
+== ordinal ==
+
+([-−]?\d+) $(ordinal $1)
+
+(.*)vienas \1pirmas
+(.*)du \1antras
+(.*)trys \1trečias
+(.*)keturi \1ketvirtas
+(.*)penki \1penktas
+(.*)šeši \1šeštas
+(.*)septyni \1septintas
+(.*)aštuoni \1aštuntas
+(.*)devyni \1devintas
+(.*)dešimt \1dešimtas
+(.*)lika \1liktas
+(.*)šimtas \1šimtasis
+(.*) \1 # FIXME (tūkstančių etc.)
+
+== ordinal-masculine ==
+
+([-−]?\d+) $(ordinal $1)
+
+== ordinal-feminine ==
+
+([-−]?\d+) $(ordinal-feminine $(ordinal $1))
+
+(.*)tasis \1toji
+(.*)s \1
+(.*) \1 # FIXME (tūkstančių etc.)
+
+== ordinal-number ==
+
+(\d+) \1.
+
+== help ==
+
+"" $(help feminine)$(help masculine)$(help ordinal-feminine)$(help ordinal-masculine)$(help ordinal-number)
+(feminine|masculine|ordinal(-feminine|-masculine|-number)?) \1: $(\1 1), $(\1 2), $(\1 3)\n
diff --git a/data/lv.sor b/data/lv.sor
new file mode 100644
index 0000000..8e38f86
--- /dev/null
+++ b/data/lv.sor
@@ -0,0 +1,121 @@
+^0 nulle
+1 viens
+2 divi
+3 trīs
+4 četri
+5 pieci
+6 seši
+7 septiņi
+8 astoņi
+9 deviņi
+10 desmit
+11 vienpadsmit
+12 divpadsmit
+13 trīspadsmit
+14 četrpadsmit
+15 piecpadsmit
+16 sešpadsmit
+17 septiņpadsmit
+18 astoņpadsmit
+19 deniņpadsmit
+([2])(\d) divdesmit[ $2]
+([23456789])(\d) $1|desmit[ $2]
+1(\d\d) simts[ $1]
+(\d)(\d\d) $1 simti[ $2]
+1(\d{3}) viens tūkstotis[ $1]
+(\d{1,3})(\d{3}) $1 tūkstoši[ $2]
+1(\d{6}) viens miljons[ $1]
+(\d{1,3})(\d{6}) $1 miljoni[ $2]
+1(\d{9}) viens miljards[ $1]
+(\d{1,3})(\d{9}) $1 miljardi[ $2]
+1(\d{12}) viens triljons[ $1]
+(\d{1,3})(\d{12}) $1 triljoni[ $2]
+1(\d{15}) viens kvadriljons[ $1]
+(\d{1,3})(\d{15}) $1 kvadriljoni[ $2]
+1(\d{18}) viens kvintiljons[ $1]
+(\d{1,3})(\d{18}) $1 kvintiljoni[ $2]
+1(\d{21}) viens sekstiljons[ $1]
+(\d{1,3})(\d{21}) $1 sekstiljoni[ $2]
+1(\d{24}) viens septiljons[ $1]
+(\d{1,3})(\d{24}) $1 septiljoni[ $2]
+
+# negative numbers
+
+[-−](\d+) mīnus |$1
+
+# decimals
+
+
+([-−]?\d+)[.,] $1| komats
+([-−]?\d+[.,]\d*)(\d) $1| |$2
+
+
+# currency
+
+# unit/subunit
+
+us:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \1
+up:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \2
+ug:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \3
+ss:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \4
+sp:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \5
+sg:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \6
+
+LVL:(\D+) $(\1: lats, lati,latu, santīms, santīmi, santīmu)
+EUR:(\D+) $(\1: eiro, eiro, eiro, cents, centi, centu)
+RUB:(\D+) $(\1: rublis, rubļi, rubļu, kapeika, kapeikas, kapeiku)
+USD:(\D+) $(\1: ASV dolārs, ASV dolāri, ASV dolāru, cents, centi, centu)
+
+
+"([A-Z]{3}) ([-−]?1)([.,]00?)?" $2|$(\1:us)
+"([A-Z]{3}) ([-−]?\d*[02-9]1)([.,]00?)?" $2|$(\1:us)
+"([A-Z]{3}) ([-−]?[23456789])([.,]00?)?" $2|$(\1:up)
+"([A-Z]{3}) ([-−]?\d*[02-9][23456789])([.,]00?)?" $2|$(\1:up)
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $2|$(\1:ug)
+
+"((RUB) [-−]?\d+)[.,]([02-9])1" $1 $(\30) |$(feminine 1)$(\2:ss)
+"((RUB) [-−]?\d+)[.,]([02-9][23456789])" $1 $(feminine \3)$(\2:sp)
+
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1 |$(1)$(\2:ss)
+"(([A-Z]{3}) [-−]?\d+)[.,]([02-9])1" $1 $(\30) |$(1)$(\2:ss)
+
+"(([A-Z]{3}) [-−]?\d+)[.,]([02-9][23456789])" $1 |$3$(\2:sp)
+
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 |$(\30)$(\2:sg)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 |$3$(\2:sg)
+
+== feminine ==
+
+([-−]?\d+) $(feminine $1)
+
+(.*)viens viena
+(.*)i \1as
+(.*) \1
+
+== masculine ==
+
+([-−]?\d+) $1
+
+== ordinal ==
+
+([-−]?\d+) $(ordinal $1)
+
+(.*)viens \1pirmais
+(.*)divi \1otrais
+(.*)trīs \1trešais
+(.*)četri \1ceturtais
+(.*)pieci \1piektais
+(.*)seši \1sestais
+(.*)septiņi \1septītais
+(.*)astoņi \1astotais
+(.*)deviņi \1devītais
+(.*)mit \1mitais
+
+== ordinal-number ==
+
+(\d+) \1.
+
+== help ==
+
+"" $(help feminine)$(help masculine)$(help ordinal)$(help ordinal-number)
+(feminine|masculine|ordinal(-number)?) \1: $(\1 1), $(\1 2), $(\1 3)\n
diff --git a/data/ms.sor b/data/ms.sor
new file mode 100644
index 0000000..6f34c98
--- /dev/null
+++ b/data/ms.sor
@@ -0,0 +1,122 @@
+^0 kosong
+1 satu
+2 dua
+3 tiga
+4 empat
+5 lima
+6 enam
+7 tujuh
+8 lapan
+9 sembilan
+10 sepuluh
+11 sebelas
+1(\d) $1 belas
+(\d)(\d) $1 puluh[ $2]
+1(\d\d) seratus[ $1]
+(\d)(\d\d) $1 ratus[ $2]
+1(\d{3}) seribu[ $1]
+(\d{1,3})(\d{3}) $1 ribu[ $2]
+# sejuta or setu juta etc.
+(\d{1,3})(\d{6}) $1 juta[ $2]
+(\d{1,3})(\d{9}) $1 bilion[ $2]
+(\d{1,3})(\d{12}) $1 trilion[ $2]
+(\d{1,3})(\d{15}) $1 kuadrilion[ $2]
+(\d{1,3})(\d{18}) $1 kuantilion[ $2]
+(\d{1,3})(\d{21}) $1 sextilion[ $2]
+(\d{1,3})(\d{24}) $1 septilion[ $2]
+
+# negative numbers
+
+[-−](\d+) minus |$1
+
+# decimals
+
+"([-−]?\d+)[.,]" $1| koma
+"([-−]?\d+[.,]\d*)(\d)" $1| |$2
+
+# currency
+
+# unit/subunit
+
+u:(.*),(.*) \1
+s:(.*),(.*) \2
+
+AUD:(.) $(\1: dollar Australia, sen)
+BGN:(.) $(\1: lev, leva, stotinka, stotinki)
+BWP:(.) $(\1: pula, pula, thebe, thebe)
+CAD:(.) $(\1: dollar Kanada, sen)
+CHF:(.) $(\1: franc Swiss, sen)
+CNY:(.) $(\1: yuan, fen)
+CZK:(.) $(\1: koruna Czech, koruna Czech, halér, halére)
+EEK:(.) $(\1: kroon, kroonid, sen)
+EUR:(.) $(\1: euro, sen)
+GBP:(.) $(\1: pound sterling, penny)
+GHS:(.) $(\1: cedi Ghana, pesewas)
+GMD:(.) $(\1: dalasi, bututs)
+HKD:(.) $(\1: dollar Hongkong, sen)
+IDR:(.) $(\1: rupiah, sen)
+INR:(.) $(\1: rupee India, paisa)
+JMD:(.) $(\1: dollar Jamaika, sen)
+JPY:(.) $(\1: yen, sen)
+KRW:(.) $(\1: won, chon)
+KES:(.) $(\1: shilling Kenya, sen)
+LRD:(.) $(\1: dollar Liberia, sen)
+LSL:(.) $(\1: loti, sente)
+LTL:(.) $(\1: litas, sen)
+LVL:(.) $(\1: lats, sen)
+MGA:(.) $(\1: ariary, iraimbilanja)
+MUR:(.) $(\1: rupee Mauritius, sen)
+MXN:(.) $(\1: peso Meksiko, centavo)
+MWK:(.) $(\1: kwacha Malawi, tambala)
+NAD:(.) $(\1: dollar Namibia, sen)
+NGN:(.) $(\1: naira, kobo)
+NZD:(.) $(\1: dollar New Zealand, sen)
+PGK:(.) $(\1: kina, toea)
+PHP:(.) $(\1: peso Filipina, centavo)
+PKR:(.) $(\1: rupee Pakistan, paisa)
+PLN:(.) $(\1: zloty, grosz)
+RON:(.) $(\1: leu Romania, ban)
+RSD:(.) $(\1: dinar Serbia, para)
+RUB:(.) $(\1: ruble Russia, kopek)
+RWF:(.) $(\1: franc Rwanda, centime)
+SGD:(.) $(\1: dollar Singapura, sen)
+SLL:(.) $(\1: leone, sen)
+SZL:(.) $(\1: lilangeni, sen)
+THB:(.) $(\1: baht, satang)
+TRY:(.) $(\1: lira Turki, kurus)
+TTD:(.) $(\1: dollar Trinidad dan Tobago, sen)
+TZS:(.) $(\1: shilling Tanzania,sen)
+UAH:(.) $(\1: hryvnia, kopiyka)
+UGX:(.) $(\1: shilling Uganda, sen)
+USD:(.) $(\1: dolar Amerika, sen)
+ZAR:(.) $(\1: rand Afrika Selatan, sen)
+ZMK:(.) $(\1: kwacha Zambia, ngwee)
+ZWL:(.) $(\1: dollar Zimbabwe, sen)
+
+"(JPY [-−]?\d+)[.,](\d\d)0" $1
+"(JPY [-−]?\d+[.,]\d\d)(\d)" $1 $2 rin
+
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $2$(\1:u)
+
+"(CNY [-−]?\d+)[.,](\d)0?" $1 $2 yiao
+"(CNY [-−]?\d+[.,]\d)(\d)" $1 $2 fen
+
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 dan $(\30)$(\2:s)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 dan $3$(\2:s)
+
+== ordinal ==
+
+1 pertama
+(\d+) $(ordinal ke$1)
+"kesatu (.*)" kese\1
+(.*) \1
+
+== ordinal-number ==
+
+1 1
+(\d+) ke-\1
+
+== help ==
+
+"" $(1), $(2), $(3)\n$(help ordinal)$(help ordinal-number)
+(ordinal(-number)?) \1: $(\1 1), $(\1 2), $(\1 3)\n
diff --git a/data/nl.sor b/data/nl.sor
new file mode 100644
index 0000000..5be2b94
--- /dev/null
+++ b/data/nl.sor
@@ -0,0 +1,103 @@
+^0$ nul
+1$ een
+1 eenen
+2$ twee
+2 tweeën
+3$ drie
+3 drieën
+4$ vier
+4 vieren
+5$ vijf
+5 vijfen
+6$ zes
+6 zesen
+7$ zeven
+7 zevenen
+8$ acht
+8 achten
+9$ negen
+9 negenen
+
+10 tien
+11 elf
+12 twaalf
+13 dertien
+14 veertien
+1(\d) $1|tien
+
+2(\d) $1twintig
+3(\d) $1dertig
+4(\d) $1veertig
+8(\d) $1tachtig
+(\d)(\d) $2$1|tig
+
+1(\d\d) honderd$1
+(\d)(\d\d) $1|honderd$2
+10(\d{2}) duizend[ $1]
+(\d)0(\d{2}) $1|duizend[ $2]
+(1\d)(\d{2}) $1|honderd$2
+(\d\d)(\d{2}) $1|honderd$2
+(\d{2,3})(\d{3}) $1|duizend[ $2]
+
+(\d{1,3})(\d{6}) $1| miljoen[ $2]
+(\d{1,3})(\d{9}) $1| miljard[ $2]
+(\d{1,3})(\d{12}) $1| biljoen[ $2]
+(\d{1,3})(\d{15}) $1| biljard[ $2]
+(\d{1,3})(\d{18}) $1| triljoen[ $2]
+(\d{1,3})(\d{21}) $1| triljard[ $2]
+
+# negative number
+
+[-−](\d+) min |$1
+
+# decimals
+
+([-−]?\d+)[.,] $1| komma
+([-−]?\d+[.,]\d*)(\d) $1| |$2
+
+# currencies
+
+# unit/subunit
+
+u:([^,]*),([^,]*),([^,]*) \1
+s:([^,]*),([^,]*),([^,]*) \2
+p:([^,]*),([^,]*),([^,]*) \3
+
+CHF:(.) $(\1: Zwitserse franc, centime, centimes)
+CNY:(.) $(\1: renminbi yuan, fen, fen)
+EUR:(.) $(\1: euro, cent, cent)
+GBP:(.) $(\1: pond sterling, penny, pence)
+JPY:(.) $(\1: yen, sen, sen)
+USD:(.) $(\1: Amerikaanse dollar, cent, cent)
+
+"(JPY [-−]?\d+)[.,](\d\d)0" $1
+"(JPY [-−]?\d+[.,]\d\d)(\d)" $1 $2| rin
+
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $2|$(\1:u)
+
+"(CNY [-−]?\d+)[.,](\d)0?" $1 $2| jiao
+"(CNY [-−]?\d+[.,]\d)(\d)" $1 $2| fen
+
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1 een$(\2:s)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 $(\30)|$(\2:p)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 $3|$(\2:p)
+
+== ordinal ==
+
+([-−]?([24-79]|\d*1\d|\d+0[24-79])) $1|de
+([-−]?\d+) $(ordinal |$1)
+
+(.*)een \1eerste
+(.*)drie \1derde
+(.*) \1ste
+
+== ordinal-number ==
+
+([-−]?([2-79]|\d*1\d|\d+0[2-79])) \1de
+([-−]?\d+) \1ste
+
+== help ==
+
+"" $(1)|, $(2)|, $(3)|\n$(\0 ordinal)$(\0 ordinal-number)currency \(for example, EUR\): $(EUR 2.5)
+"(ordinal(-number)?)" \1: $(\1 1), $(\1 2), $(\1 3)\n
+
diff --git a/data/pl.sor b/data/pl.sor
new file mode 100644
index 0000000..40d6423
--- /dev/null
+++ b/data/pl.sor
@@ -0,0 +1,141 @@
+^0 zero
+1 jeden
+2 dwa
+3 trzy
+4 cztery
+5 pięć
+6 sześć
+7 siedem
+8 osiem
+9 dziewięć
+10 dziesięć
+11 jedenaście
+14 czternaście
+15 piętnaście
+16 szesnaście
+19 dziewiętnaście
+1(\d) $1naście
+2(\d) dwadzieścia[ $1]
+3(\d) trzydzieści[ $1]
+4(\d) czterdzieści[ $1]
+(\d)(\d) $1dziesiąt[ $2]
+1(\d\d) sto[ $1]
+2(\d\d) dwieście[ $1]
+([34])(\d\d) $1sta[ $2]
+(\d)(\d\d) $1set[ $2]
+1(\d{3}) tysiąc[ $1]
+([234]|[2-9][234]|\d[02-9][234])(\d{3}) $1 tysiące[ $2]
+(\d{1,3})(\d{3}) $1 tysięcy[ $2]
+
+# affix function
+:1,(.+) \1
+:(1[1-9]),(.+) $1 \2ów
+:([234]|[2-9][234]|\d[02-9][234]),(.+) $1 \2y
+:(\d+),(.+) $1 \2ów
+
+(\d{1,3})(\d{6}) $(:\1,milion)[ $2]
+(\d{1,3})(\d{9}) $(:\1,miliard)[ $2]
+(\d{1,3})(\d{12}) $(:\1,bilion)[ $2]
+(\d{1,3})(\d{15}) $(:\1,biliard)[ $2]
+(\d{1,3})(\d{18}) $(:\1,trylion)[ $2]
+(\d{1,3})(\d{21}) $(:\1,tryliard)[ $2]
+(\d{1,3})(\d{24}) $(:\1,kwadrylion)[ $2]
+
+# negative number
+
+[-−](\d+) minus |$1
+
+# decimals
+
+"([-−]?\d+)[.,]" $1| przecinek
+"([-−]?\d+[.,])([^0]\d)" $1| |$2
+"([-−]?\d+[.,])(\d)(\d)(\d)" $1| |$2 |$3 |$4
+"([-−]?\d+[.,]\d*)(\d)" $1| |$2
+
+# currency
+
+# unit/subunit singular / nominative plural / genitive plural
+
+us:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \1
+up:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \2
+ug:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \3
+ss:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \4
+sp:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \5
+sg:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \6
+
+AUD:(\D+) $(\1: dolar australijski, dolary australijskie, dolarów australijskich, cent, centy, centów)
+BGN:(\D+) $(\1: lew bułgarski, lewy bułgarskie, lewów bułgarskich, stotinka, stotinki, stotinek)
+CHF:(\D+) $(\1: frank szwajcarski, franki szwajcarskie, franków szwajcarskich, centym, centymy, centymów)
+CAD:(\D+) $(\1: dolar kanadyjski, dolary kanadyjskie, dolarów kanadyjskich, cent, centy, centów)
+CNY:(\D+) $(\1: juan, juany, juanów, fen, feny, fenów)
+EUR:(\D+) $(\1: euro, euro, euro, cent, centy, centów)
+GBP:(\D+) $(\1: funt szterling, funty szterlingi, funtów szterlingów, pens, pensy, pensów)
+HUF:(\D+) $(\1: forint, forinty, forintów, filler, fillery, fillerów)
+JPY:(\D+) $(\1: jen, jeny, jenów, sen, seny, senów)
+PLN:(\D+) $(\1: złoty, złote, złotych, grosz, grosze, groszy)
+RUB:(\D+) $(\1: rubel rosyjski, ruble rosyjskie, rubli rosyjskich, kopiejka, kopiejki, kopiejek)
+USD:(\D+) $(\1: dolar amerykański, dolary amerykańskie, dolarów amerykańskich, cent, centy, centów)
+
+"([A-Z]{3}) ([-−]?1)([.,]00?)?" $2$(\1:us)
+"([A-Z]{3}) ([-−]?[234])([.,]00?)?" $2$(\1:up)
+"([A-Z]{3}) ([-−]?\d*[02-9][234])([.,]00?)?" $2$(\1:up)
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $2$(\1:ug)
+
+"(CNY [-−]?\d+)[.,]10?" $1 $2 jiao
+"(CNY [-−]?\d+)[.,](\d)0?" $1 $2 jiao
+"(CNY [-−]?\d+[.,]\d)1" $1 $2 fen
+"(CNY [-−]?\d+[.,]\d)(\d)" $1 $2 fenów
+
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1 |$(1)$(\2:ss)
+"(([A-Z]{3}) [-−]?\d+)[.,]([02-9][234])" $1 |$3$(\2:sp)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 |$(\30)$(\2:sg)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 |$3$(\2:sg)
+
+== ordinal(-masculine)? ==
+
+([-−]?\d+) $(ordinal |$2)
+
+(.*)jeden \2pierwszy
+(.*)dwa \2drugi
+(.*)trzy \2trzeci
+(.*)cztery \2czwarty
+(.*)pięć \2piąty
+(.*)sześć \2szósty
+(.*)siedem \2siódmy
+(.*)osiem \2ósmy
+(.*)dziewięć \2dziewiąty
+(.*)dziesięć \2dziesiąty
+(.*)jedenaście \2jedenasty
+(.*)dwanaście \2dwunasty
+(.*)dwieście \2dwusetny
+(.*)siąt \2siąty
+(.*)trzysta \2trzechsetny
+(.*)czterysta \2czterechsetny
+(.*)ści[ea] \2sty
+(.*)eści \2esty
+(.*)(sto|set) \2setny
+"(.*)dwa tysiące" \2dwutysięczny
+"(.*)pięć tysięcy" \2pięciotysięczny
+"(.*)sto tysięcy" \2stutysięczny
+"(.*) (tysi[ąę]c[ey]?)" \2tysięczny
+(.*)tysiąc \2tysięczny
+(.*(on|ard))(y|ów)? \2owy
+
+== ordinal-feminine ==
+
+([-−]?\d+) $(ordinal-feminine $(ordinal |$1))
+(.*)[yi] \1a
+
+== ordinal-neuter ==
+
+([-−]?\d+) $(ordinal-feminine $(ordinal |$1))
+(.*)[yi] \1e
+
+== ordinal-number ==
+
+(\d+) \1.
+
+== help ==
+
+"" $(1), $(2), $(3)\n$(help ordinal)$(help ordinal-number)
+(ordinal(-number)?) \1: $(\1 1), $(\1 2), $(\1 3)\n
diff --git a/data/pt.sor b/data/pt.sor
new file mode 100644
index 0000000..8501c09
--- /dev/null
+++ b/data/pt.sor
@@ -0,0 +1,193 @@
+^0 zero
+1 um
+2 dois
+3 três
+4 quatro
+5 cinco
+6 seis
+7 sete
+8 oito
+9 nove
+10 dez
+11 onze
+12 doze
+13 treze
+14 quatorze
+15 quinze
+16 dezesseis # [:pt-BR:]
+16 dezasseis
+17 dezessete # [:pt-BR:]
+17 dezassete
+18 dezoito
+19 dezenove # [:pt-BR:]
+19 dezanove
+20 vinte
+30 trinta
+40 quarenta
+50 cinquenta
+60 sessenta
+70 setenta
+80 oitenta
+90 noventa
+(\d)(\d) $(\10) e $2
+100 cem
+1(\d\d) cento e $1
+2(\d\d) duzentos[ e $1]
+3(\d\d) trezentos[ e $1]
+5(\d\d) quinhentos[ e $1]
+(\d)(\d\d) $1centos[ e $2]
+
+:0+
+:0*\d{1,2}(\d{6}){0,} " e " # mil e um, mil e dez
+:0*\d00(\d{6}){0,} " e " # mil e quinhentos
+:0*\d{1,2}000(\d{6}){0,} " e " # um milhão e onze mil
+:0*\d{1}00000(\d{6}){0,} " e " # um milhão e cem mil
+:\d+ " "
+
+pl:1 ão # milhão
+pl:.* ões # milhões
+
+1(\d\d\d) mil$(:\1)$1
+(\d{1,3})(\d\d\d) $1 mil$(:\2)$2
+
+(\d{1,3})(\d{6}) $1 milh$(pl:\1)$(:\2)$2 # [:pt-BR:]
+(\d{1,3})(\d{9}) $1 bilh$(pl:\1)$(:\2)$2 # [:pt-BR:]
+(\d{1,3})(\d{12}) $1 trilh$(pl:\1)$(:\2)$2 # [:pt-BR:]
+(\d{1,3})(\d{15}) $1 quatrilh$(pl:\1)$(:\2)$2 # [:pt-BR:]
+(\d{1,3})(\d{18}) $1 quintilh$(pl:\1)$(:\2)$2 # [:pt-BR:]
+(\d{1,3})(\d{18}) $1 sextilh$(pl:\1)$(:\2)$2 # [:pt-BR:]
+(\d{1,3})(\d{24}) $1 septilh$(pl:\1)$(:\2)$2 # [:pt-BR:]
+
+(\d{1,6})(\d{6}) $1 milh$(pl:\1)$(:\2)$2
+(\d{1,6})(\d{12}) $1 bili$(pl:\1)$(:\2)$2
+(\d{1,6})(\d{18}) $1 trili$(pl:\1)$(:\2)$2
+(\d{1,6})(\d{24}) $1 quatrili$(pl:\1)$(:\2)$2
+
+# negative number
+
+[-−](\d\d*) menos |$1
+
+# decimals
+
+([-−]?\d+)[.] $1| ponto
+([-−]?\d+)[,] $1| vírgula
+([-−]?\d+[.,])([^0]\d) $1| |$2
+"([-−]?\d+[.,])(\d)(\d)(\d)" |$1 |$2| |$3| |$4
+([-−]?\d+[.,]\d*)(\d) $1| |$2
+
+# currency (monedas)
+
+# unit/subunit singular/plural
+
+us:([^,]*),([^,]*),([^,]*),([^,]*) \1
+up:([^,]*),([^,]*),([^,]*),([^,]*) \2
+ss:([^,]*),([^,]*),([^,]*),([^,]*) \3
+sp:([^,]*),([^,]*),([^,]*),([^,]*) \4
+
+AOA:(\D+) $(\1: kwanza, kwanzas, cêntimo, cêntimos)
+ARG:(\D+) $(\1: peso argentino, pesos argentinos, centavo, centavos)
+BOB:(\D+) $(\1: boliviano, bolivianos, centavo, centavos)
+BRL:(\D+) $(\1: real, reais, centavo, centavos) # [:pt-BR:]
+BRL:(\D+) $(\1: real, réis, centavo, centavos)
+CHF:(\D+) $(\1: franco suíço, francos suíços, cêntimo, cêntimos)
+CNY:(\D+) $(\1: yuan renminbi, yuan renminbi, fen, fen)
+CVE:(\D+) $(\1: escudos cabo-verdianos, escudos cabo-verdianos, centavo, centavos)
+EUR:(\D+) $(\1: euro, euros, cent, cents)
+GBP:(\D+) $(\1: libra esterlina, libras esterlinas, penny, pence)
+JPY:(\D+) $(\1: iene, ienes, sen, sen)
+MOP:(\D+) $(\1: pataca, patacas, avo, avos)
+MXN:(\D+) $(\1: peso mexicano, pesos mexicanos, centavo, centavos)
+MZM:(\D+) $(\1: metical, meticais, centavo, centavos)
+STD:(\D+) $(\1: dobra, dobras, cêntimo, cêntimos)
+USD:(\D+) $(\1: dólar americano, dólares americanos, cêntimo, cêntimos)
+XOF:(\D+) $(\1: franco CFA, francos CFA, cêntimo, cêntimos)
+
+# masculine to feminine conversion of "un" after millions,
+# if "as?$" matches currency name
+
+f:(.*il[hi])(.*),(.*) \1$(f:\2,\3) # don't modify millions
+f:(.*um)([^a].*,|,)(.*as?) $(f:\1a\2\3) # um libra -> uma libra
+f:(.*d)oi(s.*),(.*as?) $(f:\1ua\2,\3) # dois libra -> duas libra
+f:(.*ent)o(s.*),(.*as?) $(f:\1a\2,\3) # duzentos libra -> duzentas libra
+f:(.*),(.*) \1\2
+
+"([A-Z]{3}) ([-−]?1)([.,]00?)?"$(f:|$2,$(\1:us))
+"([A-Z]{3}) ([-−]?\d+0{6,})([.,]00?)?" $2 de$(\1:up)
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?"$(f:|$2,$(\1:up))
+
+"(CNY [-−]?\d+)[.,]10?" $1 $2 jiao
+"(CNY [-−]?\d+)[.,](\d)0?" $1 $2 jiao
+"(CNY [-−]?\d+[.,]\d)1" $1 $2 fen
+"(CNY [-−]?\d+[.,]\d)(\d)" $1 $2 fen
+
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1 e |$(1)$(\2:ss)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 e |$(\30)$(\2:sp)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 e |$3$(\2:sp)
+
+== feminine ==
+
+([-−]?\d+) $(feminine $1)
+
+(.*)um \1uma
+(.*)dois(.*) $(feminine \1duas\2)
+(.*) \1
+
+== masculine ==
+
+([-−]?\d+) $1
+
+== ordinal(-masculine)? ==
+
+1 primeiro
+2 segundo
+3 terceiro
+4 quarto
+5 quinto
+6 sexto
+7 sétimo
+8 oitavo
+9 nono
+10 décimo
+20 vigésimo
+30 trigésimo
+40 cuadragésimo
+50 quincuagésimo
+60 sexagésimo
+70 septuagésimo
+80 octogésimo
+90 nonagésimo
+(\d)(\d) $(ordinal \20) $(ordinal \3)
+100 centésimo
+200 ducentésimo
+300 trecentésimo
+400 quadrigentésimo
+500 quingentésimo
+600 sexcentésimo
+700 septicentésimo
+800 octigentésimo
+900 nongentésimo
+(\d)(\d\d) $(ordinal \200) $(ordinal \3)
+1(\d{3}) milésimo[ $(ordinal \2)]
+(\d)(\d{3}) $2 milésimo[ $(ordinal \3)]
+1(\d{6}) milionésimo[ $(ordinal \2)]
+(\d{1,3})(\d{6}) $2 milionésimo[ $(ordinal \3)]
+1(\d{9}) bilionésimo[ $(ordinal \2)]
+(\d{1,3})(\d{9}) $2 bilionésimo[ $(ordinal \3)]
+
+== ordinal-feminine ==
+
+([-−]?\d+) $(ordinal-feminine $(ordinal-masculine \1))
+(.*)o\b(.*) $(ordinal-feminine \1a\2)
+(.*) \1
+
+== (ordinal)-number-(feminine|masculine)? ==
+
+([-−]?\d+) \3$(ordinal-number-feminine $(\1-\2 \3))
+.*er .ᵉʳ
+.*a .ª
+.*o .º
+
+== help ==
+
+"" $(1)|, $(2), $(3)\n$(\0 feminine)$(\0 masculine)$(\0 ordinal-feminine)$(\0 ordinal-masculine)$(\0 ordinal-number-feminine)$(\0 ordinal-number-masculine)
+(feminine|masculine|ordinal(-number)?(-feminine|-masculine)?) \1: $(\1 1), $(\1 2), $(\1 3)\n
diff --git a/data/ro.sor b/data/ro.sor
new file mode 100644
index 0000000..73d4fcd
--- /dev/null
+++ b/data/ro.sor
@@ -0,0 +1,126 @@
+^0 zero
+1 unu
+2$ doi
+2 două
+3 trei
+4 patru
+5 cinci
+6$ șase
+6 șai
+7 șapte
+8 opt
+9 nouă
+10 zece
+11 unsprezece
+12 doisprezece
+14 paisprezece
+1(\d) $1sprezece
+(\d)(\d) $1zeci[ și $2]
+1(\d\d) o sută[ $1]
+(\d)(\d\d) $1 sute[ $2]
+1(\d{3}) o mie[ $1]
+(1?\d)(\d{3}) $1 mii[ $2]
+(\d{1,3})(\d{3}) $1 de mii[ $2]
+
+1(\d{6}) un milion[ $1]
+(1?\d)(\d{6}) $1 milioane[ $2]
+(\d{1,3})(\d{6}) $1 de milioane[ $2]
+1(\d{9}) un miliard[ $1]
+(1?\d)(\d{9}) $1 miliarde[ $2]
+(\d{1,3})(\d{9}) $1 de miliarde[ $2]
+1(\d{12}) un trilion[ $1]
+(1?\d)(\d{12}) $1 trilioane[ $2]
+(\d{1,3})(\d{12}) $1 de trilioane[ $2]
+1(\d{15}) un cvadrilion[ $1]
+(1?\d)(\d{15}) $1 cvadrilioane[ $2]
+(\d{1,3})(\d{15}) $1 de cvadrilioane[ $2]
+1(\d{18}) un cvintilion[ $1]
+(1?\d)(\d{18}) $1 cvintilioane[ $2]
+(\d{1,3})(\d{18}) $1 de cvintilioane[ $2]
+1(\d{21}) un sextilion[ $1]
+(1?\d)(\d{21}) $1 sextilioane[ $2]
+(\d{1,3})(\d{21}) $1 de sextilioane[ $2]
+1(\d{24}) un septilion[ $1]
+(1?\d)(\d{24}) $1 septilioane[ $2]
+(\d{1,3})(\d{24}) $1 de septilioane[ $2]
+
+# negative number
+
+[-−](\d+) minus |$1
+
+# decimals
+
+"([-−]?\d+)[.,]" $1| virgulă
+"([-−]?\d+[.,])([^0]\d)" $1| |$2
+"([-−]?\d+[.,])(\d)(\d)(\d)" $1| |$2 |$3 |$4
+"([-−]?\d+[.,]\d*)(\d)" $1| |$2
+
+# currency
+
+# feminine/masculine correction for 1 and 2
+
+f:(.*)unu \1 o
+f:(.*do)i "\1uă "
+m:(.*un)u \1
+.:(.*) \1
+
+# unit/subunit, singular/plural, feminine/masculine unit, feminine/masculine subunit
+
+us(.).:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) $(\1:\6) \2
+up(.).:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) $(\1:\6) \3
+ss.(.):([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) $(\1:\6) \4
+sp.(.):([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) $(\1:\6) \5
+
+# "mm" means masculine unit and masculine subunit
+
+CHF:(.+),(.+) $(\1mm: franc elvețian, franci elvețieni, cent, cenți, \2)
+CNY:(.+),(.+) $(\1mm: yuan renminbi, yuani renminbi, fen, fen, \2)
+EUR:(.+),(.+) $(\1mm: euro, euro, cent, cenți, \2)
+GBP:(.+),(.+) $(\1fm: liră sterlină, lire sterline, penny, pence, \2)
+JPY:(.+),(.+) $(\1mm: yen, yeni, sen, sen, \2)
+RON:(.+),(.+) $(\1mm: leu românesc, lei românești, ban, bani, \2)
+USD:(.+),(.+) $(\1mm: dolar american, dolari americani, cent, cenți, \2)
+
+"([A-Z]{3}) ([-−]?1)([.,]00?)?"$(\1:us,|$2)
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?"$(\1:up,|$2)
+
+"(CNY [-−]?\d+)[.,]10?" $1| un jiao
+"(CNY [-−]?\d+)[.,](\d)0?" $1| $2| jiao
+"(CNY [-−]?\d+[.,]\d)1" $1| $2| fen
+"(CNY [-−]?\d+[.,]\d)(\d)" $1| $2| fen
+
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1|$(\2:ss,$(1))
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1|$(\2:sp,$(\30))
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1|$(\2:sp,$3)
+
+== ordinal(-masculine)? ==
+
+1 primul
+
+
+([-−]?\d+) al $(ordinal $2)
+
+(.*(opt|ilion|ard)) \2ulea
+(.*) \2lea
+
+== ordinal-feminine ==
+
+1 prima
+([-−]?\d+) a $(ordinal-feminine $1)
+
+(.*)doi \1doua
+(.*)cinci \1cincea
+(.*)[uă] \1a
+(.*)sute \1suta
+(.*)mi[ei] \1mia
+(.*)ane \1ana
+(.*) \1a
+
+== ordinal-number ==
+
+(\d+) \1.
+
+== help ==
+
+"" $(1), |$(2)|, $(3)\n$(help ordinal-feminine)$(help ordinal-masculine)$(help ordinal-number)
+(ordinal(-feminine|-masculine|-number)?) \1: $(\1 1), $(\1 2), $(\1 3)\n
diff --git a/data/ru.sor b/data/ru.sor
new file mode 100644
index 0000000..f3ca545
--- /dev/null
+++ b/data/ru.sor
@@ -0,0 +1,112 @@
+^0 ноль
+1 один
+2$ два
+2 две
+3 три
+4 четыре
+5 пять
+6 шесть
+7 семь
+8 восемь
+9 девять
+10 десять
+11 одиннадцать
+12 двенадцать
+13 тринадцать
+14 четырнадцать
+15 пятнадцать
+16 шестнадцать
+17 семнадцать
+18 восемнадцать
+19 девятнадцать
+([23])(\d) $1|дцать[ $2]
+4(\d) сорок[ $1]
+9(\d) девяносто[ $1]
+(\d)(\d) $1десят[ $2]
+1(\d\d) сто[ $1]
+2(\d\d) двести[ $1]
+([34])(\d\d) $1ста[ $2]
+(\d)(\d\d) $1сот[ $2]
+1(\d{3}) одна тысяча[ $1]
+([234]|\d?[02-9][234])(\d{3}) $1 тысячи[ $2]
+(\d{1,3})(\d{3}) $1 тысяч[ $2]
+1(\d{6}) один миллион[ $1]
+(\d{1,3})(\d{6}) $1 миллионов[ $2]
+1(\d{9}) один миллиард[ $1]
+(\d{1,3})(\d{9}) $1 миллиардов[ $2]
+1(\d{12}) один триллион[ $1]
+(\d{1,3})(\d{12}) $1 триллионов[ $2]
+1(\d{15}) один квадриллион[ $1]
+(\d{1,3})(\d{15}) $1 квадриллионов[ $2]
+1(\d{18}) один квинтиллион[ $1]
+(\d{1,3})(\d{18}) $1 квинтиллионов[ $2]
+1(\d{21}) один секстилион[ $1]
+(\d{1,3})(\d{21}) $1 секстилионов[ $2]
+1(\d{24}) один септиллион[ $1]
+(\d{1,3})(\d{24}) $1 септиллионов[ $2]
+
+# negative numbers
+
+[-−]1 минус единица
+[-−](\d+) минус |$1
+
+# decimals
+
+"1[.,]" одна целая
+"([-−]?1)[.,]" $1 целая
+"([-−]?\d+)[.,]" $1 целых
+"([-−]?\d+[.,])(1)" $1| и одна десятая
+"([-−]?0[.,])(\d)" $1| |$2 десятых
+"([-−]?\d+[.,])(\d)" $1| и |$2 десятый
+"([-−]?\d+[.,])([02-9]1)" $1| и $(f:|$2) сотая
+"([-−]?\d+[.,])(\d\d)" $1| и |$2 сотых
+"([-−]?\d+[.,])(\d[02-9]1)" $1| и $(f:|$2) тысячная
+"([-−]?\d+[.,])(\d11)" $1| и $(f:|$2) тысячных
+"([-−]?\d+[.,])(\d{3})" $1| и |$2 тысячный
+"([-−]?\d+[.,])(\d)(\d)(\d)(\d)" $1| |$2 |$3 |$4 |$5
+"([-−]?\d+[.,]\d*)(\d)" $1| |$2
+
+
+# female conversion
+f:(.*)один \1одна
+f:(.*) \1
+
+# currency
+
+# unit/subunit
+
+us:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \1
+up:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \2
+ug:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \3
+ss:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \4
+sp:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \5
+sg:([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*) \6
+
+EUR:(\D+) $(\1: евро, евро, евро, цент, цента, центов)
+GBP:(\D+) $(\1: фунт стерлингов, фунт стерлингов, фунт стерлингов, пенни, пенса, пенсов)
+RUB:(\D+) $(\1: рубль, рубля, рублей, копейка, копейки, копеек)
+UAH:(\D+) $(\1: гривна, гривны, гривен, копейка, копейки, копеек)
+USD:(\D+) $(\1: доллар США, доллара США, долларов США, цент, цента, центов)
+
+
+"([A-Z]{3}) ([-−]?1)([.,]00?)?" $2|$(\1:us)
+"([A-Z]{3}) ([-−]?\d*[02-9]1)([.,]00?)?" $2|$(\1:us)
+"([A-Z]{3}) ([-−]?[234])([.,]00?)?" $2|$(\1:up)
+"([A-Z]{3}) ([-−]?\d*[02-9][234])([.,]00?)?" $2|$(\1:up)
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $2|$(\1:ug)
+
+"((RUB) [-−]?\d+)[.,]([02-9])1" $1 $(\30) одна$(\2:ss)
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1 |$(1)$(\2:ss)
+"((EUR|GBP|USD) [-−]?\d+)[.,]([02-9]2)" $1 $3|$(\2:sp)
+"(([A-Z]{3}) [-−]?\d+)[.,]([02-9][234])" $1 |$3$(\2:sp)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 |$(\30)$(\2:sg)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 |$3$(\2:sg)
+
+== ordinal-number ==
+
+(\d+) \1.
+
+== help ==
+
+"" |$(1)|, |$(2)|, |$(3)|\n$(help ordinal-number)
+(.*) \1: |$(\1 1)|, |$(\1 2)|, |$(\1 3)|\n
diff --git a/data/sh.sor b/data/sh.sor
new file mode 100644
index 0000000..2da795d
--- /dev/null
+++ b/data/sh.sor
@@ -0,0 +1,108 @@
+#
+# Regular number to text transducer for Serbian (Cyrillic) written in Soros
+# Copyright (c) Goran Rakic <grakic@devbase.net> 2009.
+#
+# Released under Creative Commons 3.0 Attribution - Share Alike license
+# and relicensed under GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Visit http://numbertext.org for more info on Soros language and syntax
+#
+
+(\d{1,3})\.([\d.,]+) $(\1\2)
+
+^0 nula
+1 jedan
+2 dva
+3 tri
+4 četiri
+5 pet
+6 šest
+7 sedam
+8 osam
+9 devet
+10 deset
+
+11 jedanaest
+14 četrnaest
+16 šesnaest
+1(\d) $1naest
+
+4(\d) četrdeset[ $1]
+5(\d) pedeset[ $1]
+6(\d) šezdeset[ $1]
+9(\d) devedeset[ $1]
+(\d)(\d) $1deset[ $2]
+
+1(\d\d) sto[ $1]
+2(\d\d) dvesta[ $1]
+3(\d\d) trista[ $1]
+(\d)(\d\d) $1sto[ $2]
+
+1(\d\d\d) hiljadu[ $1]
+2(\d\d\d) dve hiljade[ $1]
+([34])(\d\d\d) $1 hiljade[ $2]
+(\d{0,1})1(\d)(\d\d\d) $(\11\2) hiljada[ $3]
+(\d{1,2})1(\d\d\d) $(\10) jedna hiljada[ $2]
+(\d{1,2})2(\d\d\d) $(\10) dve hiljade[ $2]
+(\d{1,2})([34])(\d\d\d) $(\10) $2 hiljade[ $3]
+(\d{1,3})(\d\d\d) $1 hiljada[ $2]
+
+1(\d{6}) milion[ $1]
+(\d{0,4})1(\d)(\d{6}) $(\11\2) miliona[ $3]
+(\d{1,5})1(\d{6}) $(\10) jedan milion[ $2]
+(\d{1,3})(\d{6}) $1 miliona[ $2]
+
+1(\d{9}) milijarda[ $1]
+2(\d{9}) dve milijarde[ $1]
+([34])(\d{9}) $1 milijarde[ $2]
+(\d{1,2})0(\d{9}) $(\10) milijardi[ $2]
+(\d{0,1})1(\d)(\d{9}) $(\11\2) milijardi[ $3]
+(\d{1,2})1(\d{9}) $(\10) jedna milijarda[ $2]
+(\d{1,2})2(\d{9}) $(\10) dve milijarde[ $2]
+(\d{1,2})([34])(\d{9}) $(\10) $2 milijarde[ $3]
+(\d{1,3})(\d{9}) $1 milijarde[ $2]
+
+1(\d{12}) bilion[ $1]
+(\d{0,4})1(\d)(\d{12}) $(\11\2) biliona[ $3]
+(\d{1,5})1(\d{12}) $(\10) jedan bilion[ $2]
+(\d{1,6})(\d{12}) $1 biliona[ $2]
+
+1(\d{18}) trilion[ $1]
+(\d{0,4})1(\d)(\d{18}) $(\11\2) triliona[ $3]
+(\d{1,5})1(\d{18}) $(\10) jedan trilion[ $2]
+(\d{1,6})(\d{18}) $1 triliona[ $2]
+
+1(\d{24}) kvadrilion[ $1]
+(\d{0,4})1(\d)(\d{24}) $(\11\2) kvadriliona[ $3]
+(\d{1,5})1(\d{24}) $(\10) jedan kvadrilion[ $2]
+(\d{1,6})(\d{24}) $1 kvadriliona[ $2]
+
+1(\d{30}) kvintilion[ $1]
+(\d{0,4})1(\d)(\d{30}) $(\11\2) kvintiliona[ $3]
+(\d{1,5})1(\d{30}) $(\10) jedan kvintilion[ $2]
+(\d{1,6})(\d{30}) $1 kvintiliona[ $2]
+
+1(\d{36}) sekstilion[ $1]
+(\d{0,4})1(\d)(\d{36}) $(\11\2) sekstiliona[ $3]
+(\d{1,5})1(\d{36}) $(\10) jedan sekstilion[ $2]
+(\d{1,6})(\d{36}) $1 sekstiliona[ $2]
+
+[-−](\d+) minus $1
+
+# Decimal code by https://twitter.com/_uranium_
+"([-−]?\d+)," $1| koma
+"([-−]?\d+,)([^0]\d)" $1 $2
+"([-−]?\d+,\d*[1-9]?)0+$" $1
+"([-−]?\d+,)(\d)(\d)(\d)" $1| |$2 |$3 |$4
+"([-−]?\d+,\d*)(\d)" $1 |$2
+
+== ordinal-number ==
+
+(\d+) \1.
+
+== help ==
+
+"" |$(1)|, |$(2)|, |$(3)|\n$(help ordinal-number)
+(.*) \1: |$(\1 1)|, |$(\1 2)|, |$(\1 3)|\n
diff --git a/data/sl.sor b/data/sl.sor
new file mode 100644
index 0000000..5c30a36
--- /dev/null
+++ b/data/sl.sor
@@ -0,0 +1,98 @@
+^0 nič
+1 ena
+2$ dve
+2 dva
+3 tri
+4 štiri
+5 pet
+6 šest
+7 sedem
+8 osem
+9 devet
+10 deset
+11 enajst
+1(\d) $1najst
+20 dvajset
+2(\d) $1indvajset
+(\d)0 $1deset
+(\d)(\d) $2in$1deset
+1(\d\d) sto[ $1]
+2(\d\d) dvesto[ $1]
+(\d)(\d\d) $1sto[ $2]
+1(\d\d\d) tisoč[ $1]
+(\d{1,3})(\d\d\d) $1 tisoč[ $2]
+1(\d{6}) milijon[ $1]
+([234])(\d{6}) $1 milijona[ $2]
+(\d{1,3})(\d{6}) $1 milijonov[ $2]
+1(\d{9}) milijarda[ $1]
+([234])(\d{9}) $1| milijardi[ $2]
+(\d{1,3})(\d{9}) $1 milijardov[ $2]
+1(\d{12}) bilijon[ $1]
+([234])(\d{12}) $1 bilijona[ $2]
+(\d{1,3})(\d{12}) $1 bilijonov[ $2]
+1(\d{15}) tisoč bilijonov[ $1]
+(\d{1,3})(\d{15}) $1 tisoč bilijonov[ $2]
+1(\d{18}) trilijon[ $1]
+([234])(\d{18}) $1 trilijona[ $2]
+(\d{1,3})(\d{18}) $1 trilijonov[ $2]
+1(\d{21}) tisoč trilijonov[ $1]
+(\d{1,3})(\d{21}) $1 tisoč trilijonov[ $2]
+1(\d{24}) kvadrilijon[ $1]
+([234])(\d{24}) $1 kvadrilijona[ $2]
+(\d{1,3})(\d{24}) $1 kvadrilijonov[ $2]
+
+# negative number
+
+[-−] minus
+[-−](\d+) minus |$1
+
+# decimals
+
+"([-−]?\d+)[.,]" $1| vejica
+"([-−]?\d+[.,])([^0]\d)" $1| |$2
+"([-−]?\d+[.,])(\d)(\d)(\d)" $1| |$2 |$3 |$4
+"([-−]?\d+[.,]\d*)(\d)" $1| |$2
+
+# currency
+
+# unit/subunit affixation
+
+u1:([^,]*)(,[^,]*){9} \1
+u2:([^,]*,){1}([^,]*)(,[^,]*){8} \2
+u3:([^,]*,){2}([^,]*)(,[^,]*){7} \2
+u4:([^,]*,){3}([^,]*)(,[^,]*){6} \2
+u5:([^,]*,){4}([^,]*)(,[^,]*){5} \2
+s1:([^,]*,){5}([^,]*)(,[^,]*){4} \2
+s2:([^,]*,){6}([^,]*)(,[^,]*){3} \2
+s3:([^,]*,){7}([^,]*)(,[^,]*){2} \2
+s4:([^,]*,){8}([^,]*)(,[^,]*){1} \2
+s5:([^,]*,){9}([^,]*) \2
+
+CHF:(.+) $(\1: švicarski frank, švicarska franka, švicarski franki, švicarske franke, švicarskih frankov, centim, centima, centimi, centime, centimov)
+EUR:(.+) $(\1: evro, evra, evri, evre, evrov, cent, centa, centi, cente, centov)
+GBP:(.+) $(\1: funt šterling, funta šterlinga, funti šterlingi, funte šterlinge, funtov šterlingov, peni, penija, peniji, penije, penijev)
+JPY:(.+) $(\1: japonski jen, japonska jena, japonski jeni, japonske jene, japonskih jenov, sen, sena, seni, sene, senov)
+USD:(.+) $(\1: ameriški dolar, ameriška dolarja, ameriški dolarji, ameriške dolarje, ameriških dolarjev, cent, centa, centi, cente, centov)
+
+"([A-Z]{3}) ([-−]?)1([.,]00?)?" $2 en$(\1:u1)
+"([A-Z]{3}) ([-−]?\d*01)([.,]00?)?" $2$(\1:u1)
+"([A-Z]{3}) ([-−]?(2|\d*02))([.,]00?)?" $2$(\1:u2)
+"([A-Z]{3}) ([-−]?(3|\d*03))([.,]00?)?" $2$(\1:u3)
+"([A-Z]{3}) ([-−]?(4|\d*04))([.,]00?)?" $2$(\1:u4)
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $2$(\1:u5)
+
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1 en$(\2:s1)
+"(([A-Z]{3}) [-−]?\d+)[.,](02)" $1 $3$(\2:s2)
+"(([A-Z]{3}) [-−]?\d+)[.,](03)" $1 $3$(\2:s3)
+"(([A-Z]{3}) [-−]?\d+)[.,](04)" $1 $3$(\2:s4)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 $(\30)$(\2:s5)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 $3$(\2:s5)
+
+== ordinal-number ==
+
+(\d+) \1.
+
+== help ==
+
+"" |$(1)|, |$(2)|, |$(3)|\n$(help ordinal-number)
+(.*) \1: |$(\1 1)|, |$(\1 2)|, |$(\1 3)|\n
diff --git a/data/sr.sor b/data/sr.sor
new file mode 100644
index 0000000..3230dd5
--- /dev/null
+++ b/data/sr.sor
@@ -0,0 +1,108 @@
+#
+# Regular number to text transducer for Serbian (Cyrillic) written in Soros
+# Copyright (c) Goran Rakic <grakic@devbase.net> 2009.
+#
+# Released under Creative Commons 3.0 Attribution - Share Alike license
+# and relicensed under GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Visit http://numbertext.org for more info on Soros language and syntax
+#
+
+(\d{1,3})\.([\d.,]+) $(\1\2)
+
+^0 нула
+1 један
+2 два
+3 три
+4 четири
+5 пет
+6 шест
+7 седам
+8 осам
+9 девет
+10 десет
+
+11 једанаест
+14 четрнаест
+16 шеснаест
+1(\d) $1наест
+
+4(\d) четрдесет[ $1]
+5(\d) педесет[ $1]
+6(\d) шездесет[ $1]
+9(\d) деведесет[ $1]
+(\d)(\d) $1десет[ $2]
+
+1(\d\d) сто[ $1]
+2(\d\d) двеста[ $1]
+3(\d\d) триста[ $1]
+(\d)(\d\d) $1сто[ $2]
+
+1(\d\d\d) хиљаду[ $1]
+2(\d\d\d) две хиљаде[ $1]
+([34])(\d\d\d) $1 хиљаде[ $2]
+(\d{0,1})1(\d)(\d\d\d) $(\11\2) хиљада[ $3]
+(\d{1,2})1(\d\d\d) $(\10) једна хиљада[ $2]
+(\d{1,2})2(\d\d\d) $(\10) две хиљаде[ $2]
+(\d{1,2})([34])(\d\d\d) $(\10) $2 хиљаде[ $3]
+(\d{1,3})(\d\d\d) $1 хиљада[ $2]
+
+1(\d{6}) милион[ $1]
+(\d{0,4})1(\d)(\d{6}) $(\11\2) милиона[ $3]
+(\d{1,5})1(\d{6}) $(\10) један милион[ $2]
+(\d{1,3})(\d{6}) $1 милиона[ $2]
+
+1(\d{9}) милијарда[ $1]
+2(\d{9}) две милијарде[ $1]
+([34])(\d{9}) $1 милијарде[ $2]
+(\d{1,2})0(\d{9}) $(\10) милијарди[ $2]
+(\d{0,1})1(\d)(\d{9}) $(\11\2) милијарди[ $3]
+(\d{1,2})1(\d{9}) $(\10) једна милијарда[ $2]
+(\d{1,2})2(\d{9}) $(\10) две милијарде[ $2]
+(\d{1,2})([34])(\d{9}) $(\10) $2 милијарде[ $3]
+(\d{1,3})(\d{9}) $1 милијарде[ $2]
+
+1(\d{12}) билион[ $1]
+(\d{0,4})1(\d)(\d{12}) $(\11\2) билионa[ $3]
+(\d{1,5})1(\d{12}) $(\10) један билион[ $2]
+(\d{1,6})(\d{12}) $1 билиона[ $2]
+
+1(\d{18}) трилион[ $1]
+(\d{0,4})1(\d)(\d{18}) $(\11\2) трилиона[ $3]
+(\d{1,5})1(\d{18}) $(\10) један трилион[ $2]
+(\d{1,6})(\d{18}) $1 трилиона[ $2]
+
+1(\d{24}) квадрилион[ $1]
+(\d{0,4})1(\d)(\d{24}) $(\11\2) квадрилиона[ $3]
+(\d{1,5})1(\d{24}) $(\10) један квадрилион[ $2]
+(\d{1,6})(\d{24}) $1 квадрилиона[ $2]
+
+1(\d{30}) квинтилион[ $1]
+(\d{0,4})1(\d)(\d{30}) $(\11\2) квинтилиона[ $3]
+(\d{1,5})1(\d{30}) $(\10) један квинтилион[ $2]
+(\d{1,6})(\d{30}) $1 квинтилиона[ $2]
+
+1(\d{36}) секстилион[ $1]
+(\d{0,4})1(\d)(\d{36}) $(\11\2) секстилиона[ $3]
+(\d{1,5})1(\d{36}) $(\10) један секстилион[ $2]
+(\d{1,6})(\d{36}) $1 секстилиона[ $2]
+
+[-−](\d+) минус $1
+
+# Decimal code by https://twitter.com/_uranium_
+"([-−]?\d+)," $1| кома
+"([-−]?\d+,)([^0]\d)" $1 $2
+"([-−]?\d+,\d*[1-9]?)0+$" $1
+"([-−]?\d+,)(\d)(\d)(\d)" $1| |$2 |$3 |$4
+"([-−]?\d+,\d*)(\d)" $1 |$2
+
+== ordinal-number ==
+
+(\d+) \1.
+
+== help ==
+
+"" |$(1)|, |$(2)|, |$(3)|\n$(help ordinal-number)
+(.*) \1: |$(\1 1)|, |$(\1 2)|, |$(\1 3)|\n
diff --git a/data/sv.sor b/data/sv.sor
new file mode 100644
index 0000000..2720071
--- /dev/null
+++ b/data/sv.sor
@@ -0,0 +1,144 @@
+^0 noll
+^1$ ett
+^1 en
+1 ett
+2 två
+3 tre
+4 fyra
+5 fem
+6 sex
+7 sju
+8 åtta
+9 nio
+10 tio
+11 elva
+12 tolv
+13 tretton
+14 fjorton
+15 femton
+16 sexton
+17 sjutton
+18 arton
+19 nitton
+2(\d) tjugo$1
+3(\d) trettio$1
+4(\d) fyrtio$1
+7(\d) sjuttio$1
+8(\d) åttio$1
+9(\d) nittio$1
+(\d)(\d) $1tio$2
+(\d)(\d\d) $1|hundra$2
+
+# “ettusen” instead of “etttusen”
+
+(1|\d?[02-9]1)(\d{3}) $1|usen[ $2]
+
+(\d{1,3})(\d{3}) $1tusen[ $2]
+(\d{1,3})(\d{6}) |$1 miljon$(pl:\1)[ $2]
+(\d{1,3})(\d{9}) |$1 miljard$(pl:\1)[ $2]
+(\d{1,3})(\d{12}) |$1 biljon$(pl:\1)[ $2]
+(\d{1,3})(\d{15}) |$1 biljard$(pl:\1)[ $2]
+(\d{1,3})(\d{18}) |$1 triljon$(pl:\1)[ $2]
+(\d{1,3})(\d{21}) |$1 triljard$(pl:\1)[ $2]
+(\d{1,3})(\d{24}) |$1 kvadriljon$(pl:\1)[ $2]
+
+# plural for big numbers
+pl:1
+pl:.* er
+
+# negative number
+
+[-−](\d+) minus |$1
+
+# decimals
+
+"([-−]?\d+)[.,]" $1| komma
+"([-−]?\d+[.,])([^0]\d)" $1| |$2
+"([-−]?\d+[.,])(\d)(\d)(\d)" $1| |$2 |$3 |$4
+"([-−]?\d+[.,]\d*)(\d)" $1| |$2
+
+# currency
+
+# unit/subunit singular/plural
+"us, (.*): (.*), (.*), (.*), (.*), (.*), (.*)" $(\2 \1) \3
+"up, (.*): (.*), (.*), (.*), (.*), (.*), (.*)" $(\2 \1) \4
+"ss, (.*): (.*), (.*), (.*), (.*), (.*), (.*)" $(\5 \1) \6
+"sp, (.*): (.*), (.*), (.*), (.*), (.*), (.*)" $(\5 \1) \7
+
+CHF:(\D+,.*) $(\1: cardinal, schweizisk franc, schweizisk franc, cardinal, centime, centime)
+CNY:(\D+,.*) $(\1: cardinal, yuan renminbi, yuan renminbi, cardinal, fen, fen)
+EUR:(\D+,.*) $(\1: cardinal, euro, euro, cardn, cent, cent)
+GBP:(\D+,.*) $(\1: cardinal-neuter, brittiskt pund, brittiskt pund, cardinal, penny, pence)
+JPY:(\D+,.*) $(\1: cardinal, yen, yen, cardinal, sen, sen)
+SEK:(\D+,.*) $(\1: cardinal, svensk krona, svenska kronor, cardinal-neuter, öre, öre)
+USD:(\D+,.*) $(\1: cardinal, US-dollar, US-dollar, cardinal-neuter, cent, cent)
+
+"([A-Z]{3}) ([-−]?1)([.,]00?)?"$(\1:us, \2)
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?"$(\1:up, \2)
+
+"(CNY [-−]?\d+)[.,]10?" $1 $2 jiao
+"(CNY [-−]?\d+)[.,](\d)0?" $1 $2 jiao
+"(CNY [-−]?\d+[.,]\d)1" $1 $2 fen
+"(CNY [-−]?\d+[.,]\d)(\d)" $1 $2 fen
+
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1$(\2:ss, 1)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1$(\2:sp, \30)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1$(\2:sp, \3)
+
+== cardinal-neuter ==
+
+1 ett
+
+== cardinal(-feminine|-masculine|-neuter)? ==
+
+([-−]?\d+) $(cardinal |$2)
+"(.*[^ ]e)t(tusen.*)" $(cardinal \2n\3) # 21000, 31000 .. 991000
+"(.*e)tt([ ].*|$)" $(cardinal \2n\3) # !etthundra, !ettusen
+(.*) \2
+
+== ordinal(-masculine)? ==
+
+([-−]?\d+) $(ordinal |$2)
+
+== ordinal ==
+
+(.*)ett \1förste # 1
+(.*)två \1andre # 2
+(.*)tre \1tredje # 3
+(.*)fyra \1fjärde # 4
+(.*)sex \1sjätte # 6
+(.*(sju|io)) \1nde # 7, 9, 10, 20..90
+(.*)åtta \1åttonde # 8
+(.*)elva \1elfte # 11
+(.*)tolv \1tolfte # 12
+"(.*(ton|hundra|tusen)) *" \1de # 13, 14..19, 100, 1000
+"(.*)er *" \1te # milljoner...
+"(.*[^ ]) *" \1te # 0, 5, milljon...
+
+== ordinal-feminine ==
+
+([-−]?\d+) $(ordinal-feminine $(ordinal |$1))
+(.*(först|andr))e \1a # 1, 2
+(.*) \1
+
+== ordinal-neuter ==
+
+(.*) $(ordinal-feminine |$1)
+
+== ordinal-number(-feminine|-neuter)? ==
+
+(.*[02-9][12]|[12]) \2:a
+
+== ordinal-number(-feminine|-neuter|-masculine)? ==
+
+(.*) \2:e
+
+== year ==
+
+([-−]?(1[1-9]|[2-9]\d))(\d\d) $1hundra$3
+(.*) $1
+
+== help ==
+
+"" $(1)|, $(2), $(3)\n$(\0 cardinal-feminine)$(\0 cardinal-masculine)$(\0 cardinal-neuter)$(\0 ordinal-feminine)$(\0 ordinal-masculine)$(\0 ordinal-neuter)$(\0 ordinal-number)$(\0 ordinal-number-feminine)$(\0 ordinal-number-masculine)
+((ordinal|cardinal)(-number)?(-feminine|-masculine|-neuter)?) \1: $(\1 1), $(\1 2), $(\1 3)\n
diff --git a/data/th.sor b/data/th.sor
new file mode 100644
index 0000000..57dddaf
--- /dev/null
+++ b/data/th.sor
@@ -0,0 +1,73 @@
+^0 ศูนย์
+^1 หนึ่ง
+1 เอ็ด
+2 สอง
+3 สาม
+4 สี่
+5 ห้า
+6 หก
+7 เจ็ด
+8 แปด
+9 เก้า
+1(\d) สิบ$1
+2(\d) ยี่สิบ$1
+(\d)(\d) $1สิบ$2
+(\d)(\d\d) $1ร้อย$2
+(\d)(\d{3}) $1พัน$2
+(\d)(\d{4}) $1หมื่น$2
+(\d)(\d{5}) $1แสน$2
+(\d)(\d{6}) $1ล้าน$2
+(\d\d)(\d{6}) $1ล้าน$2
+(\d)(\d{8}) $1ร้อยล้าน$2
+(\d)(\d{9}) $1พันล้าน$2
+(\d)(\d{10}) $1หมื่นล้าน$2
+(\d)(\d{11}) $1แสนล้าน$2
+(\d)(\d{12}) $1ล้านล้าน$2
+(\d\d)(\d{12}) $1ล้านล้าน$2
+(\d)(\d{14}) $1ร้อยล้านล้าน$2
+(\d)(\d{15}) $1พันล้านล้าน$2
+(\d)(\d{16}) $1หมื่นล้านล้าน$2
+(\d)(\d{17}) $1แสนล้านล้าน$2
+(\d)(\d{18}) $1ล้านล้านล้าน$2
+(\d\d)(\d{18}) $1ล้านล้านล้าน$2
+(\d)(\d{20}) $1ร้อยล้านล้านล้าน$2
+(\d)(\d{21}) $1พันล้านล้านล้าน$2
+(\d)(\d{22}) $1หมื่นล้านล้านล้าน$2
+(\d)(\d{23}) $1แสนล้านล้านล้าน$2
+(\d)(\d{24}) $1ล้านล้านล้านล้าน$2
+
+# negative numbers
+
+[-−](\d+) ลบ|$1
+
+# decimals
+
+([-−]?\d+)[.,] |$1|จุด
+([-−]?\d+[.,]\d*)(\d) |$1|$2
+
+# currency
+
+"THB ([-−]?\d+)" $1บาทถ้วน
+
+# currency with decimals
+
+"(THB [-−]?\d+)[,.]00" $1
+"THB ([-−]?\d+)[,.](\d{1,2})" $1บาท$2สตางค์
+
+# other currencies?
+
+[A-Z]{3}
+"([A-Z]{3}) ([-−]?\d[\d.,]*)" $2$1
+
+== ordinal ==
+
+([-−]?\d+([.,]\d+)?) ที่$1
+
+== ordinal-number ==
+
+(\d+) \1.
+
+== help ==
+
+"" |$(1)|, |$(2)|, |$(3)|\n$(help ordinal)$(help ordinal-number)
+(.*) \1: |$(\1 1)|, |$(\1 2)|, |$(\1 3)|\n
diff --git a/data/tr.sor b/data/tr.sor
new file mode 100644
index 0000000..72091a5
--- /dev/null
+++ b/data/tr.sor
@@ -0,0 +1,138 @@
+^0 sıfır
+1 bir
+2 iki
+3 üç
+4 dört
+5 beş
+6 altı
+7 yedi
+8 sekiz
+9 dokuz
+1(\d) on[ $1]
+2(\d) yirmi[ $1]
+3(\d) otuz[ $1]
+4(\d) kırk[ $1]
+5(\d) elli[ $1]
+6(\d) altmış[ $1]
+7(\d) yetmiş[ $1]
+8(\d) seksen[ $1]
+9(\d) doksan[ $1]
+
+(1)(\d\d) yüz[ $2] # yüz ..
+([2-9])(\d\d) $1 yüz[ $2] # üç yüz ...
+(1)(\d\d\d) bin[ $2] # bin
+(\d{1,2})([1-9]\d\d) $1 bin[ $2] # on bin iki yüz
+(\d{1,3})(\d{3}) $1 bin[ $2] # yüz bin iki yüz
+(\d{1,3})(\d{6}) $1 milyon[ $2]
+(\d{1,3})(\d{9}) $1 milyar[ $2]
+(\d{1,3})(\d{12}) $1 trilyon[ $2]
+(\d{1,3})(\d{15}) $1 katrilyon[ $2]
+(\d{1,3})(\d{18}) $1 kentilyon[ $2]
+(\d{1,3})(\d{21}) $1 sekstilyon[ $2]
+(\d{1,3})(\d{24}) $1 septilyon[ $2]
+
+# negative number
+
+[-−](\d+) negatif |$1
+
+# decimals
+
+([-−]?\d+)[.,] $1| virgül
+"([-−]?\d+[.,]0*)(\d+)" $1 |$2
+([-−]?\d+[.,]\d*)(\d) $1| |$2
+
+# currency
+
+# unit/subunit singular/plural
+
+us:([^,]*),([^,]*),([^,]*),([^,]*) \1
+up:([^,]*),([^,]*),([^,]*),([^,]*) \2
+ss:([^,]*),([^,]*),([^,]*),([^,]*) \3
+sp:([^,]*),([^,]*),([^,]*),([^,]*) \4
+
+AUD:(\D+) $(\1: Avustralya doları, Avustralya doları, sent, sent)
+BGN:(\D+) $(\1: Bulgar levası, Bulgar levası, stotinka, stotinki)
+BWP:(\D+) $(\1: Botswana pulası, Botswana pulası, thebe, thebe)
+CAD:(\D+) $(\1: Kanada doları, Canadian dollars, sent, sent)
+CHF:(\D+) $(\1: İsviçre frangı, İsviçre frangı, santim, santim)
+CNY:(\D+) $(\1: Çin yuanı, Çin yuanı, fen, fen)
+CZK:(\D+) $(\1: Çek korunası, Çek korunası, heller, heller)
+EEK:(\D+) $(\1: Estonya kronu, Estonya kronu, sent, sent)
+EUR:(\D+) $(\1: euro, euro, sent, sent)
+GBP:(\D+) $(\1: sterlin, sterlin, peni, peni)
+GHS:(\D+) $(\1: Gana sedisi, Gana sedisi, peseva, peseva)
+GMD:(\D+) $(\1: Gambiya dalası, Gambiya dalası, butut, butut)
+HKD:(\D+) $(\1: Hong Kong doları, Hong Kong doları, sent, sent)
+HRK:(\D+) $(\1: Hırvatistan kunası, Hırvatistan kunası, lipa, lipa)
+HUF:(\D+) $(\1: Macar forinti, Macar forinti, filler, filler)
+INR:(\D+) $(\1: Hindistan rupisi, Hindistan rupisi, paise, paise)
+JMD:(\D+) $(\1: Jamaika doları, Jamaika doları, sent, sent)
+JPY:(\D+) $(\1: Japon yeni, Japon yeni, sen, sen)
+KES:(\D+) $(\1: Kenya şilini, Kenya şilini, sent, sent)
+LRD:(\D+) $(\1: Liberya doları, Liberya doları, sent, sent)
+LSL:(\D+) $(\1: Lesotho loti, maloti, sente, lisente)
+LTL:(\D+) $(\1: Litvanya litası, Litvanya litası, centas, centai)
+LVL:(\D+) $(\1: Letonya latı, Letonya latı, santims, santimi)
+MGA:(\D+) $(\1: ariary, ariaries, iraimbilanja, iraimbilanja)
+MUR:(\D+) $(\1: Mauritius rupisi, Mauritius rupisi, sent, sent)
+MXN:(\D+) $(\1: Meksika pezosu, Meksika pezosu, sentavo, sentavo)
+MWK:(\D+) $(\1: Malawian kwacha, Malawian kwacha, tambala, tambala)
+NAD:(\D+) $(\1: Namibya doları, Namibya doları, sent, sent)
+NGN:(\D+) $(\1: Nijerya nairası, Nijerya nairası, kobo, kobo)
+NZD:(\D+) $(\1: Yeni Zelanda doları, Yeni Zelanda doları, sent, sent)
+PGK:(\D+) $(\1: Papua Yeni Gine kinası, Papua Yeni Gine kinası, toea, toea)
+PHP:(\D+) $(\1: Filipinler pezosu, Filipinler pezosu, sentavo, sentavo)
+PKR:(\D+) $(\1: Pakistan rupisi, Pakistan rupisi, paisa, paisa)
+PLN:(\D+) $(\1: Polonya zlotisi, Polonya zlotisi, grosz, groszy)
+RON:(\D+) $(\1: Romen leyi, Romen leyi, ban, ban)
+RSD:(\D+) $(\1: Sırbistan dinarı, Sırbistan dinarı, para, para)
+RUB:(\D+) $(\1: Rus rublesi, Rus rublesi, kopek, kopek)
+RWF:(\D+) $(\1: Ruanda frangı, Ruanda frangı, santim, santim)
+SDG:(\D+) $(\1: Sudan poundu, Sudan poundu, piastre, piastres)
+SGD:(\D+) $(\1: Singapur doları, Singapur doları, sent, sent)
+SLL:(\D+) $(\1: Sierra Leone leonu, Sierra Leone leonu, sent, sent)
+SZL:(\D+) $(\1: lilangeni, emalangeni, cent, cents)
+THB:(\D+) $(\1: Tayland bahtı, Tayland bahtı, satang, satang)
+TRY:(\D+) $(\1: Türk lirası, Türk lirası, kuruş, kuruş)
+TTD:(\D+) $(\1: Trinidad ve Tobago doları, Trinidad ve Tobago doları, sent, sent)
+TZS:(\D+) $(\1: Tanzanya şilini, Tanzanya şilini, sent, sent)
+UAH:(\D+) $(\1: Ukrayna hryvnyası, Ukrayna hryvnyası, kopiyka, kopiyka)
+UGX:(\D+) $(\1: Uganda şilini, Uganda şilini, sent, sent)
+USD:(\D+) $(\1: ABD doları, ABD doları, sent, sent)
+X[AO]F:(\D+) $(\1: CFA franc, CFA francs, centime, centimes)
+ZAR:(\D+) $(\1: Güney Afrika randı, Güney Afrika randı, sent, sent)
+ZMK:(\D+) $(\1: Zambiya kıvaçası, Zambiya Kıvaçası, ngwee, ngwee)
+ZWD:(\D+) $(\1: Zimbabve doları, Zimbabve doları, sent, sent)
+
+"(JPY [-−]?\d+)[.,](\d\d)0" $1
+"(JPY [-−]?\d+[.,]\d\d)(\d)" $1 $2 rin
+
+# removing spaces from number names before currencies
+
+"space:([^ ]+) +([^ ].*)" \1$(space:\2)
+space:(.*) \1
+
+"([A-Z]{3}) ([-−]?1)([.,]00?)?" $2$(\1:us)
+"([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $(space:|$2)$(\1:up)
+
+"(CNY [-−]?\d+)[.,](\d)0?" $1 $2 jiao
+"(CNY [-−]?\d+[.,]\d)(\d)" $1 $2 fen
+
+"((MGA|MRO) [-−]?\d+)[.,]0" $1
+"((MGA|MRO) [-−]?\d+)[.,]2" $1 |$(1)$(\2:ss)
+"((MGA|MRO) [-−]?\d+)[.,]4" $1 |$(2)$(\2:sp)
+"((MGA|MRO) [-−]?\d+)[.,]6" $1 |$(3)$(\2:sp)
+"((MGA|MRO) [-−]?\d+)[.,]8" $1 |$(4)$(\2:sp)
+
+"(([A-Z]{3}) [-−]?\d+)[.,](01)" $1 |$(1)$(\2:ss)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 |$(\30)$(\2:sp)
+"(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 $(space:|$3)$(\2:sp)
+
+== ordinal-number ==
+
+(\d+) \1.
+
+== help ==
+
+"" |$(1)|, |$(2)|, |$(3)|\n$(help cardinal-neuter)$(help cardinal-feminine)$(help cardinal-masculine)$(help ordinal)$(help ordinal-number)
+(.*) \1: |$(\1 1)|, |$(\1 2)|, |$(\1 3)|\n
diff --git a/data/vi.sor b/data/vi.sor
new file mode 100644
index 0000000..75a6dc1
--- /dev/null
+++ b/data/vi.sor
@@ -0,0 +1,43 @@
+^0$ không
+1 một
+2 hai
+3 ba
+4 bốn
+^5$ năm
+5$ lăm
+5 năm
+6 sáu
+7 bảy
+8 tám
+9 chín
+1(\d) mười[ $1]
+(\d)0 $1 mươi
+(\d)1 $1 mươi mốt
+(\d)(\d) $1 mươi[ $2]
+
+(\d)01 $1 trăm linh một
+(\d)(\d\d) $1 trăm[ $2]
+
+(\d{1,3})000 $1 ngàn
+(\d{1,3})001 $1 ngàn không trăm linh một
+(\d{1,3})0(\d\d) $1 ngàn không trăm[ $2]
+(\d{1,3})(\d\d\d) $1 ngàn[ $2]
+
+(\d{1,3})0{6} $1 triệu
+(\d{1,3})0{5}1 $1 triệu không trăm linh một
+(\d{1,3})0{4}(\d\d) $1 triệu không trăm[ $2]
+(\d{1,3})(\d{6}) $1 triệu[ $2]
+
+(\d{1,10})0{9} $1 tỷ
+(\d{1,10})0{8}1 $1 tỷ không trăm linh một
+(\d{1,10})0{7}(\d\d) $1 tỷ không trăm[ $2]
+(\d{1,10})(\d{9}) $1 tỷ[ $2]
+
+== ordinal-number ==
+
+(\d+) \1.
+
+== help ==
+
+"" |$(1)|, |$(2)|, |$(3)|\n$(help ordinal-number)
+(.*) \1: |$(\1 1)|, |$(\1 2)|, |$(\1 3)|\n
diff --git a/data/zh.sor b/data/zh.sor
new file mode 100644
index 0000000..362646b
--- /dev/null
+++ b/data/zh.sor
@@ -0,0 +1,171 @@
+# Mandarin Chinese number names (simplified)
+^0 零
+1 一
+2$ 二
+2 两
+3 三
+4 四
+5 五
+6 六
+7 七
+8 八
+9 九
+^1(\d) 十$1
+(\d)(\d) $1|十$2
+(\d)0{2} $1百
+(\d)0(\d) $1百零$2
+(\d)(\d\d) $1百$2
+(\d)0{3} $1千
+(\d)0(\d\d) $1千零$2
+(\d)(\d\d\d) $1千$2
+(\d{1,4})0{4} $1|万
+(\d{1,4})0(\d{3}) $1|万零$2
+(\d{1,4})(\d{4}) $1|万$2
+(\d{1,4})0{8} $1|亿
+(\d{1,4})0(\d{7}) $1|亿零$2
+(\d{1,4})(\d{8}) $1|亿$2
+(\d{1,4})0{12} $1|兆
+(\d{1,4})0(\d{11}) $1|兆零$2
+(\d{1,4})(\d{12}) $1|兆$2
+(\d{1,4})0{16} $1|京
+(\d{1,4})0(\d{15}) $1|京零$2
+(\d{1,4})(\d{16}) $1|京$2
+(\d{1,4})0{20} $1|垓
+(\d{1,4})0(\d{19}) $1|垓零$2
+(\d{1,4})(\d{20}) $1|垓$2
+(\d{1,4})0{24} $1|秭
+(\d{1,4})0(\d{23}) $1|秭零$2
+(\d{1,4})(\d{24}) $1|秭$2
+(\d{1,4})0{28} $1|穰
+(\d{1,4})0(\d{27}) $1|穰零$2
+(\d{1,4})(\d{28}) $1|穰$2
+(\d{1,4})0{32} $1|沟
+(\d{1,4})0(\d{31}) $1|沟零$2
+(\d{1,4})(\d{32}) $1|沟$2
+(\d{1,4})0{36} $1|涧
+(\d{1,4})0(\d{35}) $1|涧零$2
+(\d{1,4})(\d{36}) $1|涧$2
+(\d{1,4})0{40} $1|正
+(\d{1,4})0(\d{39}) $1|正零$2
+(\d{1,4})(\d{40}) $1|正$2
+(\d{1,4})0{44} $1|载
+(\d{1,4})0(\d{43}) $1|载零$2
+(\d{1,4})(\d{44}) $1|载$2
+
+# negative numbers
+
+[-−](\d+) 负|$1
+
+# decimals
+
+"([-−]?\d+)[.,]" "$1|点"
+"([-−]?\d+[.,]\d*)(\d)" $1||$2
+
+# currency
+
+# unit/subunit singular/plural
+
+AUD 澳大利亚元
+CHF 瑞士法郎
+CNY 人民币
+EUR 歐元
+GBP 英镑
+HKD 港元
+JPY 日圓
+MOP 澳門幣
+USD 美元
+
+# 1/10 角
+# 1/100 分
+
+"([A-Z]{3}) ([-−]?\d+([.,]\d+)?)" $2$1
+
+# Mandarin Chinese number names, formal numbers (大写) for legal and financial documents, simplified
+
+== formal ==
+
+^0 零
+1 壹
+2$ 贰
+2 贰
+3 叁
+4 贰
+5 伍
+6 陆
+7 柒
+8 捌
+9 玖
+^1(\d) 拾$(formal \1)
+(\d)(\d) $(formal \1)|拾$(formal \2)
+(\d)0{2} $(formal \1)佰
+(\d)0(\d) $(formal \1)佰零$(formal \2)
+(\d)(\d\d) $(formal \1)佰$(formal \2)
+(\d)0{3} $(formal \1)仟
+(\d)0(\d\d) $(formal \1)仟零$(formal \2)
+(\d)(\d\d\d) $(formal \1)仟$(formal \2)
+(\d{1,4})0{4} $(formal \1)|萬
+(\d{1,4})0(\d{3}) $(formal \1)|萬零$(formal \2)
+(\d{1,4})(\d{4}) $(formal \1)|萬$(formal \2)
+(\d{1,4})0{8} $(formal \1)|億
+(\d{1,4})0(\d{7}) $(formal \1)|亿零$(formal \2)
+(\d{1,4})(\d{8}) $(formal \1)|亿$(formal \2)
+(\d{1,4})0{12} $(formal \1)|兆
+(\d{1,4})0(\d{11}) $(formal \1)|兆零$(formal \2)
+(\d{1,4})(\d{12}) $(formal \1)|兆$(formal \2)
+(\d{1,4})0{16} $(formal \1)|京
+(\d{1,4})0(\d{15}) $(formal \1)|京零$(formal \2)
+(\d{1,4})(\d{16}) $(formal \1)|京$(formal \2)
+(\d{1,4})0{20} $(formal \1)|垓
+(\d{1,4})0(\d{19}) $(formal \1)|垓零$(formal \2)
+(\d{1,4})(\d{20}) $(formal \1)|垓$(formal \2)
+(\d{1,4})0{24} $(formal \1)|秭
+(\d{1,4})0(\d{23}) $(formal \1)|秭零$(formal \2)
+(\d{1,4})(\d{24}) $(formal \1)|秭$(formal \2)
+(\d{1,4})0{28} $(formal \1)|穰
+(\d{1,4})0(\d{27}) $(formal \1)|穰零$(formal \2)
+(\d{1,4})(\d{28}) $(formal \1)|穰$(formal \2)
+(\d{1,4})0{32} $(formal \1)|沟
+(\d{1,4})0(\d{31}) $(formal \1)|沟零$(formal \2)
+(\d{1,4})(\d{32}) $(formal \1)|沟$(formal \2)
+(\d{1,4})0{36} $(formal \1)|涧
+(\d{1,4})0(\d{35}) $(formal \1)|涧零$(formal \2)
+(\d{1,4})(\d{36}) $(formal \1)|涧$(formal \2)
+(\d{1,4})0{40} $(formal \1)|正
+(\d{1,4})0(\d{39}) $(formal \1)|正零$(formal \2)
+(\d{1,4})(\d{40}) $(formal \1)|正$(formal \2)
+(\d{1,4})0{44} $(formal \1)|载
+(\d{1,4})0(\d{43}) $(formal \1)|载零$(formal \2)
+(\d{1,4})(\d{44}) $(formal \1)|载$(formal \2)
+
+# negative numbers
+
+[-−](\d+) 负|$(formal \1)
+
+# decimals
+
+"([-−]?\d+)[.,]" "$(formal \1)|点"
+"([-−]?\d+[.,]\d*)(\d)" $(formal \1)||$(formal \2)
+
+# currency
+
+# unit/subunit singular/plural
+
+AUD 澳大利亚元
+CHF 瑞士法郎
+CNY 人民币
+EUR 歐元
+GBP 英镑
+HKD 港元
+JPY 日圓
+MOP 澳門幣
+USD 美元
+
+# 1/10 角
+# 1/100 分
+
+"([A-Z]{3}) ([-−]?\d+([.,]\d+)?)" $(formal \2)$(formal \1)
+
+== help ==
+
+"" |$(1)|, |$(2)|, |$(3)|\n$(help formal)
+(formal) \1: |$(\1 1)|, |$(\1 2)|, |$(\1 3)|\n
diff --git a/description.xml.in b/description.xml.in
new file mode 100644
index 0000000..ff8b1a4
--- /dev/null
+++ b/description.xml.in
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<description xmlns="http://openoffice.org/extensions/description/2006"
+xmlns:d="http://openoffice.org/extensions/description/2006"
+xmlns:xlink="http://www.w3.org/1999/xlink">
+ <display-name>
+ <name lang="en">NUMBERTEXT() and MONEYTEXT() Calc functions</name>
+ <name lang="de">NUMBERTEXT() und MONEYTEXT() Calc Funktions</name>
+ <name lang="hu">NUMBERTEXT() és MONEYTEXT() Calc függvények</name>
+ <name lang="it">NUMBERTEXT() e MONEYTEXT() Calc funzione</name>
+ <name lang="pl">Funkcje NUMBERTEXT () i MONEYTEXT () dla programu Calc</name>
+ <name lang="sr">NUMBERTEXT() и MONEYTEXT() функције за Рачун</name>
+ <name lang="sh">NUMBERTEXT() i MONEYTEXT() funkcije za Račun</name>
+ <name lang="sh">NUMBERTEXT() וMONEYTEXT() פונקציות גליון Calc</name>
+ </display-name>
+<!--!echo "<version value=\"`head -1 VERSION`\" />"-->
+ <identifier value="org.numbertext-calc-addin" />
+ <publisher>
+ <name lang="en" xlink:href="http://NUMBERTEXT.org">NUMBERTEXT.org</name>
+ </publisher>
+ <platform value="all" />
+
+<dependencies>
+ <OpenOffice.org-minimal-version value="2.4" d:name="OpenOffice.org 2.4"/>
+</dependencies>
+
+</description>
diff --git a/doc/Tutorial_1.sor b/doc/Tutorial_1.sor
new file mode 100644
index 0000000..df6e1bf
--- /dev/null
+++ b/doc/Tutorial_1.sor
@@ -0,0 +1,116 @@
+# Soros Tutorial – Part One 🔢 Three, Two, One...
+#
+# INTRODUCTION
+#
+# Soros programming language is for number to
+# number name conversion. It’s based on regular
+# expressions, the popular text processing
+# tool of modern programming languages. So if you
+# don’t want to convert numbers to number names,
+# it’s still worth to check this tutorial, because
+# most parts are about regular expressions,
+# giving useful information for modern C++, Java,
+# JavaScript, Python etc. programming, too.
+# If you know regular expressions well, you can
+# jump to the last part of the tutorial!
+#
+# In this part, we will learn the base syntax of
+# Soros, writing small programs to convert
+# input numbers to numbers and colorful (at least
+# in Mozilla Firefox) emojis!
+#
+#
+#
+# TASK 1 – HELLO, WORLD!
+#
+# A Soros program consists of program lines.
+#
+# A program line is an input text and an output text
+# separated by (the first) space:
+#
+# input_text output text
+#
+# Following program line replaces the input text “0”
+# with the output text “Hello, 🌍!”, as you can see
+# in the right output list window, which shows the
+# output of the first 120 integer numbers, including
+# this one:
+
+0 Hello, 🌍!
+
+# Replace “Hello, 🌍!” with “zero” in the previous line,
+# and check the same change in the right output window
+# list!
+#
+# Write here a new program line to convert the input
+# text “1” to “one”!
+
+
+
+# TASK 2 – The early bird catches the worm.
+#
+# First matching program line gives result.
+#
+# Remove the line with the bird COMPLETELY, and
+# then the line with the worm! During these, check
+# the results in the right output list window!
+
+2 🐦
+2 🐛
+2 two
+
+
+
+# TASK 3 – Three blind mice
+#
+# Input text without matching program line, or a
+# matching program line without output text
+# results empty output text.
+#
+# Remove the character # (sign of comment line)
+# before 3 in the following line to hide the mice!
+
+#3
+3 🐁🐁🐁
+
+
+
+# TASK 4 – Five little speckled frogs
+#
+# Modify the following program lines to get correct
+# number of frogs for the input number 5 and 4!
+
+5 🐸🐸🐸🐸🐸🐸
+4 🐸🐸🐸🐸🐸🐸
+
+SCROLL DOWN FOR SOLUTION
+⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Solution – TASK 4
+#
+# 5 🐸🐸🐸🐸🐸
+# 4 🐸🐸🐸🐸
+
+
+######################################################
+# CONGRATULATIONS – You have finished Tutorial One! 🙂
+######################################################
diff --git a/doc/Tutorial_2.sor b/doc/Tutorial_2.sor
new file mode 100644
index 0000000..4289f4b
--- /dev/null
+++ b/doc/Tutorial_2.sor
@@ -0,0 +1,193 @@
+# Soros Tutorial Two 🍒 Fruitful Expressions
+#
+# We learn the basics of regular expressions,
+# writing a program to convert even input
+# numbers to apples, and odd numbers to pears.
+#
+# INTRODUCTION
+#
+# Regular expression (regexp or regex or RE) is
+# a standard for pattern matching and replacement,
+# supported by every modern programming languages.
+#
+# Why? Because it’s the easiest way to handle
+# input texts.
+#
+# A Soros program line can be a regular
+# expression pattern and replacement:
+#
+# regex_pattern regex replacement
+
+
+
+# TASK 1
+#
+# The character . (dot) matches arbitrary
+# characters in a regex pattern.
+#
+# Remove the # in the following program to add
+# bananas to all 1-digit numbers (except one),
+# and tangerines to all 2-digit numbers, and extend
+# the third program line to convert all 3-digit
+# numbers to pineapples (scroll the output
+# window to the end to see 3-digit numbers)!
+
+1 one
+#. 🍌 (1-DIGIT)
+#.. 🍊 (2-DIGIT)
+🍍
+
+# NOTE: Solutions are there in the end of this tutorial.
+
+# TASK 2
+#
+# Dots can be combined with arbitrary other
+# characters.
+#
+# Extend the previous program with a single
+# program line to replace 10, 20, 30 ... 90
+# with lemons instead of bananas!
+# (Copy this lemon emoji: 🍋).
+#
+
+
+
+# TASK 3
+#
+# We can limit the previous pattern only for
+# given characters, putting them between brackets.
+#
+# For example, [abcd] matches only the letter a, b, c and d.
+#
+# Add a *single* program line to the previous program to
+# to replace every 2-digit *even* number with an apple, ie.
+# compressing the following 45-line long program:
+#
+# 10 🍎 (EVEN)
+# 12 🍎 (EVEN)
+# ...
+# 98 🍎 (EVEN)
+
+
+
+# TASK 4
+#
+# The .+ (dot plus) matches 1 or more arbitrary characters.
+#
+# What will be the effect of the following program line, if
+# you change the first line “1 one” with it, and remove the
+# sign of comment? Guess it, and check it!
+
+#.+ 🍎🍎🍎
+
+
+
+# TASK 5
+#
+# We can combine the different regex patterns, for example, the
+# dot plus pattern with the bracket one.
+#
+# Write a program from scratch (removing the old program lines)
+# to show apples and pears for every 2-digit or more input
+# number, using .+ and bracket expressions!
+#
+# 10 🍎 (EVEN)
+# 11 🍐 (ODD)
+# 12 🍎 (EVEN)
+# ...
+# 100 🍎 (EVEN)
+# 101 🍐 (ODD)
+# etc.
+
+
+
+# TASK 6
+#
+# The .* (dot asterisk) matches 0 or more arbitrary characters.
+#
+# Replace the first program line “1 one” with a program line to
+# convert all even input numbers (including the 1-letter ones)
+# to apples, and insert a new program line to convert all
+# odd numbers to pears.
+
+SCROLL DOWN FOR SOLUTIONS
+⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩
+
+
+
+
+
+
+
+
+
+
+
+# SOLUTION – TASK 1
+#
+# 1 one
+# . 🍌 (1-DIGIT)
+# .. 🍊 (2-DIGIT)
+# ... 🍍 (3-DIGIT)
+
+
+
+# SOLUTION – TASK 2
+#
+# 1 one
+# . 🍌 (1-DIGIT)
+# .0 🍋 (10×n)
+# .. 🍊 (2-DIGIT)
+# ... 🍍 (3-DIGIT)
+
+
+
+# SOLUTION – TASK 3
+#
+# 1 one
+# . 🍌 (1-DIGIT)
+# .[02468] 🍎 (EVEN 2-DIGIT)
+# .0 🍋 (10×n)
+# .. 🍊 (2-DIGIT)
+# ... 🍍 (3-DIGIT)
+
+
+
+# SOLUTION – TASK 4
+#
+# All numbers converted to "🍎🍎🍎", because .+ matches
+# every input text, so the following program lines
+# will never be executed, so we can remove them:
+#
+# .+ 🍎🍎🍎
+
+
+
+# SOLUTION – TASK 5
+#
+# 2-digit or bigger numbers are converted to
+# apples and pears by the following two lines:
+#
+# .+[02468] 🍎 (EVEN 2-OR-MORE-DIGIT)
+# .+[13579] 🍐 (ODD 2-OR-MORE-DIGIT)
+#
+# or simply
+#
+# .+[02468] 🍎 (EVEN 2-OR-MORE-DIGIT)
+# .+. 🍐 (ODD 2-OR-MORE-DIGIT)
+
+
+
+# SOLUTION – TASK 6
+#
+# Change + with * in the previous program to convert
+# every (1-digit or larger) number to apples and pears:
+#
+# .*[02468] 🍎 (EVEN NUMBER)
+# .* 🍐 (ODD NUMBER)
+
+
+
+######################################################
+# CONGRATULATIONS – You have finished Tutorial Two! 🙂
+######################################################
diff --git a/doc/Tutorial_3.sor b/doc/Tutorial_3.sor
new file mode 100644
index 0000000..f5394bf
--- /dev/null
+++ b/doc/Tutorial_3.sor
@@ -0,0 +1,94 @@
+# Soros Tutorial Three 🛠️ Hello, Real World!
+#
+# Using the simplest regex reference
+# we solve a typical Soros problem, converting
+# numbers to ordinal abbreviations.
+#
+#
+# INTRODUCTION
+#
+# Syntax of a Soros program line:
+#
+# regex_pattern regex replacement
+#
+# The \0 (backslash zero) in the regex replacement
+# is a reference for the input number.
+#
+# For example, the following program line match every
+# input number and replace it by ownself, i.e. we get
+# back the input number without any changes, as you can
+# see in the right output list window after removing
+# the # at the beginning of the line:
+
+#.* \0
+
+# TASK 1
+#
+# It’s possible to refer the input number multiple times
+# in the same regex_replacement, combined with arbitrary
+# text.
+#
+# Modify the *previous program line* to greet the input
+# number double, as follows!
+#
+# 1 -> Hello, 1! Hi, 1!
+# 2 -> Hello, 2! Hi, 2!
+
+
+
+# TASK 2
+#
+# Complete the program of Tutorial 1 to handle all
+# English ordinal abbreviations!
+#
+# Rules:
+#
+# I Every word ending with 1, 2, 3 has got an
+# abbreviation ending with 1st, 2nd, 3rd,
+# for example, 1 -> 1st (first), 22 -> 22nd
+# (twenty-second), 103 -> 103rd (one hundred third).
+#
+# Ib Exception: numbers ending with 11, 12 or 13.
+# Example: 11 -> 11th (eleventh), 112 -> 112th
+# (one hundred twelfth), 1013 -> 1013th
+# (one thousand and thirteenth).
+#
+# II Other numbers get “th”. Example: 4 -> 4th (fourth).
+
+
+
+
+SCROLL DOWN FOR SOLUTIONS
+⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩
+
+
+
+
+
+
+
+
+# SOLUTION – TASK 1
+#
+# .* HELLO, \0! HI, \0!
+
+
+
+# SOLUTION – TASK 2
+#
+# The trick is there in the first line,
+# a pattern to match all input
+# ending with 1., for example, 10, 11, .. 19,
+# 110, 111 etc.:
+#
+# .*1. \0th
+# .*1 \0st
+# .*2 \0nd
+# .*3 \0rd
+# .* \0th
+
+
+
+########################################################
+# CONGRATULATIONS – You have finished Tutorial Three! 🙂
+########################################################
diff --git a/doc/Tutorial_4.sor b/doc/Tutorial_4.sor
new file mode 100644
index 0000000..7b5d08b
--- /dev/null
+++ b/doc/Tutorial_4.sor
@@ -0,0 +1,191 @@
+# Soros Tutorial Four 👪 Reference & Group
+#
+# We will write a thousand separation program
+# by referring parts of the input text and
+# learning more about regular expression syntax.
+#
+#
+#
+# TASK 1
+#
+# We can create character groups in the regex pattern by
+# parenthesizing, and refer them using reference \1..\9
+# in the regex replacement.
+#
+# For example, following program replaces the
+# characters of arbitry 2-character input (ab -> ba, etc.):
+#
+# (.)(.) \2\1
+#
+# Write a program to return with the last two characters of the
+# input!
+
+
+
+# TASK 2
+#
+# Character sequences in bracket expression can be abbreviated
+# using character ranges separated by a hyphen character.
+#
+# For example, [a-z] matches every character between “a” and “z”,
+# [a-cx-z] matches letter a, b, c, x, y and z.
+#
+# Using this write a program to return with the first character
+# of the input, if that is between 1 and 5, or 9!
+
+
+
+# TASK 3
+#
+# Bracket expression [^...] matches complementers of the
+# given characters or character ranges. For example,
+# [^01] matches every character, except 0 or 1.
+#
+# Write a program to return with the last two characters
+# of the input, if they don’t contain zeroes.
+
+.*([^0][^0]) \1
+
+
+# TASK 4
+#
+# The pattern \d matches an arbitrary digit. For example
+# \d\d\d matches every 3-digit numbers.
+#
+# Using this, write a program to return with the first
+# three digits of the input!
+
+
+
+# TASK 5
+#
+# Repetition sign + and * can be combined with bracket
+# expressions, \d and groups, too. There are three other
+# frequently used repetitions:
+#
+# ? 0, or 1 times
+# {n} exactly n times
+# {n,m} between n and m times
+#
+# For example, \d{6}, \d{1,3}
+#
+# Using this, write a program to do thousand separation
+# between 1 and 100,000,000,000.
+#
+# Rules:
+#
+# I. Separation is only from 5-digit numbers.
+# For example: 1, 10, 1000, 10,000.
+#
+# II. Separate by commas by 3-digit groups from the right side
+# For example: 100,000, 1000,000, 10,000,000, 100,000,000...
+#
+# NOTE: Test your program by typing a single number in the textbox “Input”.
+
+
+
+# OPTIONAL TASK 1
+#
+# Groups can match different patterns:
+#
+# (word1|word2|word3)
+#
+# matches word1 OR word2 OR word3.
+#
+# For example, ([a-z]|10*) matches a single letter OR
+# 10 OR 100 OR 1000 etc.
+#
+# Groups can contain inner groups, too.
+#
+# Guess it, what does the following expression!
+#
+# ((Anne|Becky) (Smith|Johnson)) Full name: \1, First name: \2
+
+
+
+# OPTIONAL TASK 2
+#
+# References can be used within the regex
+# pattern (back references).
+#
+# Following program matches all 2-digit numbers
+# with repeating digits (11, 22, 33, 44 .. 99).
+#
+# (\d)\1 Cute number! 🙂
+#
+# Extend this pattern for every numbers contain only repeating
+# digits (11, 22, ... 111... 555)!
+
+
+
+
+
+
+
+SCROLL DOWN FOR SOLUTIONS
+⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩
+
+
+
+
+
+
+
+
+# SOLUTION – TASK 1
+#
+# .*(..) \1
+#
+# or the less simple
+#
+# .*(.)(.) \1\2
+
+
+
+# SOLUTION – TASK 2
+#
+# ([1-59]).* \1
+
+
+
+# SOLUTION – TASK 3
+#
+# .*([^0][^0]) \1
+
+
+
+# SOLUTION – TASK 4
+#
+# (\d\d\d).* \1
+
+
+
+# SOLUTION – TASK 5
+#
+# NOTE: Last line will return with smaller and big numbers
+# without changes:
+#
+# (\d{2,3})(\d{3}) \1,\2
+# (\d{1,3})(\d{3})(\d{3}) \1,\2,\3
+# (\d{1,3})(\d{3})(\d{3})(\d{3}) \1,\2,\3,\4
+# .* \0
+
+# SOLUTION – OPTIONAL TASK 1
+
+# ((Anne|Becky) (Smith|Johnson)) Full name: \1, First name: \2
+# expression replaces this way:
+#
+# Anne Smith -> Full name: Anne Smith, First name: Anne
+# Becky Smith -> Full name: Becky Smith, First name: Becky
+# Anne Johnson -> Full name: Anne Johnson, First name: Anne
+# Becky Johnson -> Full name: Becky Johnson, First name: Becky
+
+
+
+# SOLUTION – OPTIONAL TASK 2
+#
+# (\d)\1+
+
+#######################################################
+# CONGRATULATIONS – You have finished Tutorial Four! 🙂
+#######################################################
diff --git a/doc/Tutorial_5.sor b/doc/Tutorial_5.sor
new file mode 100644
index 0000000..3687567
--- /dev/null
+++ b/doc/Tutorial_5.sor
@@ -0,0 +1,378 @@
+# Soros Tutorial – Part Five 🚀 ... Go!
+#
+# We will complete the following number to English
+# number name conversion program, learning special
+# features of Soros programming language.
+
+0 zero
+1 one
+2 two
+3 three
+4 four
+5 five
+6 six
+7 seven
+8 eight
+9 nine
+10 ten
+11 eleven
+12 twelve
+13 thirteen
+
+# TASK 1 – Call me again!
+#
+# A Soros program is a single function, named $(). It’s
+# possible to call this function in the regex replacement
+# part with arbitrary text as an argument, and its return value
+# will be inserted in the regex replacement at the place of
+# the function call.
+#
+# In the following program line, the argument is “4”,
+# and function call “$(4)” is replaced with “four”, the
+# result of the call of function $ with the argument “4”:
+
+14 $(4)teen
+
+# Extend the line 16 this way!
+
+15 fifteen
+16
+
+
+
+# TASK 2 – Reference and call...
+#
+# We can use regex references in function arguments.
+# For example, we can describe 18 -> eighteen conversion
+# this way, too:
+
+1(8) $(\1)een
+
+# Using the regex pattern \d (matching arbitrary digits),
+# give a *single* program line for 17 -> seventeen and
+# 19 -> nineteen conversion! (With this, line 14 and 16
+# will be unnecessary, too.)
+
+
+
+# TASK 3 – Abbreviation of $(\n) is $n
+#
+# According to the title of this task, $1 means $(\1),
+# $2 means $(\2) etc. Rewrite the following program part to
+# use this abbreviated form!
+
+20 twenty
+2(\d) twenty-$(\1)
+
+
+
+# TASK 4 – Boundaries
+#
+# Soros programs have default automatic zero deletion in
+# its arguments, ie. $(1) or $(01) are equivalents. But
+# the following program line have a different problem for
+# the input number 100: after left zero deletion it still
+# remains a zero, resulting “one hundred zero” instead of
+# “one hundred”:
+
+1(\d\d) one hundred $1
+
+# The solution is using boundary dependent patterns.
+# These patterns can always match at the first run of the
+# Soros program, but at the next recursive calls,
+# matching depends from the position of the function call:
+#
+# ^pattern only matches, if the function call is there at
+# the beginning of the replacement. Example:
+# 1(\d) $1teen
+#
+# pattern$ only matches, if the function call is there at
+# the end of the replacement. Example:
+# 2(\d) twenty-$(\1)
+#
+# ^pattern$ only matches, if the function call is there at
+# the beginning and the end of the replacement.
+# Example:
+# 1(\d) $(ordinal |$1)
+#
+# NOTE: “|” before or after function calls sets explicite
+# boundary position.
+#
+# Correct the bug “one hundred zero” by using the
+# correct boundary sign on the program line “0 zero”, also
+# create a rule for negative numbers, to handle
+# “-0” -> “minus zero” conversion correctly!
+
+
+
+# TASK 5 – Optional text, depending from the return value
+#
+# Previously, we had a different program line for 20 and one
+# for 21–29 , because English uses a hyphen between the
+# number names. Using brackets around the recursive calls,
+# we can skip the first program line. The hyphen is only
+# added to “thirty”, if the return value of the recursive
+# function calls is not empty.
+
+3(\d) thirty[-$(\1)]
+
+# Write a *single* program line to handle “sixty”,
+# “seventy” (60–79), and “ninety” (90–99)!
+
+
+
+# TASK 6 – Language-dependent program lines
+#
+# Using [:lang-code:] in a comment sets a
+# language-dependent program line. For example,
+# German number to number name rules
+#
+# 3(\d) [$1und]dreissig # [:de-CH:]
+# 3(\d) [$1und]dreißig
+#
+# result “dreissig” for the input “30”, if the language
+# of the conversion is de-CH (Swiss Standard German),
+# otherwise “dreißig”.
+#
+# It’s possible to use arbitrary number language codes
+# in the same program line.
+#
+# In Australia, Great Britain, Ireland and New Zealand,
+# 101 is “one hundred and one”, in other English speaking
+# countries, like USA and Canada, 101 is “one hundred one”.
+# Using the language codes en-AU, en-GB, en-IE and en-NZ
+# and the previous conditional text, describe number 100–999
+# in both variants!
+
+
+
+# TASK 7 – More Functions
+#
+# In Soros language, there is only one real function, the $(),
+# but it’s possible to create function-like structures by using
+# prefixes.
+#
+# Numbertext.org language modules contain functions for
+# number to money conversion (“USD 2” -> “two U.S. dollars”),
+# number to ordinal name conversion (“2” -> “second”) and
+# ordinal-number conversion (“2” -> “2nd”). For example,
+# we can define ordinal numbers as follows:
+#
+# "ordinal 1" first
+# "ordinal 2" second
+# "ordinal 3" third
+#
+# According to the quotation marks, the regex patterns can
+# contain spaces, too.
+#
+# For the space separated prefixes, there is a default left
+# zero deletion, i.e. $(ordinal 1) is equivalent of
+# $(ordinal 001), so program line
+#
+# "ordinal 1(\d\d)" one hundred $(ordinal \1)
+#
+# works also for the input 101, 102 etc. correctly using
+# only the previous program lines.
+#
+# Other method of ordinal number conversion is to convert the
+# input to the default cardinal number names, and modifying
+# their text:
+#
+# "ordinal (\d+)" $(ordinal |$1)
+# "ordinal (.*)one" \1first
+# "ordinal (.*)two" \1second
+#
+# NOTE: As can be seen, it’s possible to embed function
+# calls within function calls, too.
+#
+# What can be the last program line of this function?
+
+
+
+# TASK 8 – Prefix “macros”
+#
+# Prefix macros simplify prefix handling. We can define
+# the previous ordinal function as follows, too
+# (see “ordinal” between double equal signs):
+#
+# == ordinal ==
+#
+# ^0 zeroth
+# 1 first
+# 2 second
+# 3 third
+#
+# because this will be expanded in the following form:
+#
+# "^ordinal 0" zeroth
+# "ordinal 1" first
+# "ordinal 2" second
+# "ordinal 3" third
+#
+# With the other method, converting cardinal number names,
+# and later to ordinal ones:
+#
+# == ordinal ==
+#
+# (\d+) $(ordinal |$1)
+# (.*)one \1first
+# (.*)two \1second
+# ...
+# (.*) \1th
+#
+# How is this expanded?
+
+
+
+# TASK 9 – Join Numbertext development!
+#
+# Your contribution will help LibreOffice and other free
+# softwares to support chapter numbering with number names,
+# converting money amounts to text (MONEYTEXT), creating
+# plural forms of money amounts and support better
+# title casing.
+#
+# Check and fix Soros code of your language on
+# http://NUMBERTEXT.org, or if there is no such module yet,
+# create it, based on the currency code of the
+# English or the more flexible Swedish (sv.sor)
+# modules!
+
+
+
+SCROLL DOWN FOR SOLUTIONS
+⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩
+
+
+
+
+
+
+
+
+# SOLUTION – TASK 1–7
+#
+# Solutions marked as TASK 1–7 in comments:
+#
+# ^0 zero # TASK 4
+# 1 one
+# 2 two
+# 3 three
+# 4 four
+# 5 five
+# 6 six
+# 7 seven
+# 8 eight
+# 9 nine
+# 10 ten
+# 11 eleven
+# 12 twelve
+# 13 thirteen
+# # 14 $(4)teen
+# 15 fifteen
+# # 16 $(6)teen # TASK 1
+# 18 eighteen
+# 1(\d) $1teen # TASK 2
+# 20 twenty
+# 2(\d) twenty-$1 # TASK 3
+# 3(\d) thirty[-$1]
+# 4(\d) forty[-$1]
+# 5(\d) fifty[-$1]
+# 8(\d) eighty[-$1]
+# (\d)(\d) $1ty[-$2] # TASK 5
+#
+# # separator function
+# :0+ # one million
+# :0*\d?\d " and " # one million and twenty-two
+# :\d+ ", " # one million, one thousand
+#
+# (\d)(\d\d) $1 hundred[ and $2] # one hundred and one [:en-AU:] [:en-GB:] [:en-IE:] [:en-NZ:] # TASK 6
+# (\d)(\d\d) $1 hundred[ $2] # default: one hundred one # TASK 6
+# (\d{1,2})([1-9]\d\d) $1 thousand[ $2] # ten thousand two hundred
+# (\d{1,3})(\d{3}) $1 thousand$(:\2)$2 # one hundred thousand, two hundred
+# (\d{1,3})(\d{6}) $1 million$(:\2)$2
+# (\d{1,3})(\d{9}) $1 billion$(:\2)$2
+#
+# # negative number
+#
+# [-−](\d+) negative |$1 # TASK 4
+#
+# # decimals
+#
+# 0[.,] point
+# ([-−]?\d+)[.,] $1| point
+# ([-−]?\d+[.,]\d*)(\d) $1| |$2
+#
+# # currency
+#
+# # unit/subunit singular/plural
+#
+# us:([^,]*),([^,]*),([^,]*),([^,]*) \1
+# up:([^,]*),([^,]*),([^,]*),([^,]*) \2
+# ss:([^,]*),([^,]*),([^,]*),([^,]*) \3
+# sp:([^,]*),([^,]*),([^,]*),([^,]*) \4
+#
+# AUD:(\D+) $(\1: Australian dollar, Australian dollars, cent, cents)
+# CAD:(\D+) $(\1: Canadian dollar, Canadian dollars, cent, cents)
+# CHF:(\D+) $(\1: Swiss franc, Swiss francs, centime, centimes)
+# CNY:(\D+) $(\1: Chinese yuan, Chinese yuan, fen, fen)
+# EUR:(\D+) $(\1: euro, euro, cent, cents)
+# GBP:(\D+) $(\1: pound sterling, pounds sterling, penny, pence)
+# JPY:(\D+) $(\1: Japanese yen, Japanese yen, sen, sen)
+# USD:(\D+) $(\1: U.S. dollar, U.S. dollars, cent, cents)
+#
+# "(JPY [-−]?\d+)[.,](\d\d)0" $1
+# "(JPY [-−]?\d+[.,]\d\d)(\d)" $1 $2 rin
+#
+# "([A-Z]{3}) ([-−]?1)([.,]00?)?" $2$(\1:us)
+# "([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $2$(\1:up)
+#
+# "(CNY [-−]?\d+)[.,](\d)0?" $1 $2 jiao
+# "(CNY [-−]?\d+[.,]\d)(\d)" $1 $2 fen
+#
+# "(([A-Z]{3}) [-−]?\d+)[.,](01)" $1 and |$(1)$(\2:ss)
+# "(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 and |$(\030)$(\2:sp)
+# "(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 and |$3$(\2:sp)
+#
+# == ordinal ==
+#
+# # convert to text, and recall to convert
+# # cardinal names to ordinal ones
+#
+# ([-−]?\d+) $(ordinal |$1)
+#
+# (.*)one \1first
+# (.*)two \1second
+# (.*)three \1third
+# (.*)five \1fifth
+# (.*)eight \1eighth
+# (.*)nine \1ninth
+# (.*)twelve \1twelfth
+# (.*)y \1ieth
+# (.*) \1th # TASK 7
+#
+# == ordinal-number ==
+#
+# (.*1\d) \1th
+# (.*1) \1st
+# (.*2) \1nd
+# (.*3) \1rd
+# (.*) \1th
+
+
+
+# SOLUTION – TASK 8
+#
+# As before in TASK 7:
+#
+# "ordinal (\d+)" $(ordinal |$1)
+# "ordinal (.*)one" \1first
+# "ordinal (.*)two" \1second
+# ...
+# "ordinal (.*)" \1th
+
+
+
+#######################################################
+# CONGRATULATIONS – You have finished Tutorial Five! 🙂
+#######################################################
diff --git a/doc/addnewlocale.txt b/doc/addnewlocale.txt
new file mode 100644
index 0000000..3d79e02
--- /dev/null
+++ b/doc/addnewlocale.txt
@@ -0,0 +1,21 @@
+Adding a new locale to the Numbertext distribution
+
+1. Make a new Soros program in the data/ subdirectory under the
+name of your locale (the format and the numbertext algorithm
+are described in format.txt).
+
+2. Translate the function description for your localized LibreOffice
+in the data/titles.txt
+
+3. Type make in the root directory or without a Unix or Cygwin
+environment, you can manually extend the
+pythonpath/numbertext_locales.py and compile your Soros program with the
+following command in the pythonpath subfolder:
+
+python Compile.py data/your_locale.sor >numbertext_your_locale.py
+python CompileTitles.py data/titles.txt >numbertext_titles.py
+
+4. Type make dist to zip the distribution or use your zip compresser
+in the root directory, eg.
+
+zip -r numbertext.oxt .
diff --git a/doc/format.txt b/doc/format.txt
new file mode 100644
index 0000000..3d66d80
--- /dev/null
+++ b/doc/format.txt
@@ -0,0 +1,7 @@
+Soros language is the key of the easy implementation of
+the platform-independent number to number name conversion.
+
+Soros language specification: see sorosspec.odt.
+
+See also regex tutorial/Wikipedia article about regular expressions
+and use Soros development environment (Soros.html).
diff --git a/doc/numbertext.odt b/doc/numbertext.odt
new file mode 100644
index 0000000..adc103a
--- /dev/null
+++ b/doc/numbertext.odt
Binary files differ
diff --git a/doc/numbertext.pdf b/doc/numbertext.pdf
new file mode 100644
index 0000000..cd3b8ad
--- /dev/null
+++ b/doc/numbertext.pdf
Binary files differ
diff --git a/doc/sorosspec.odt b/doc/sorosspec.odt
new file mode 100644
index 0000000..28a406b
--- /dev/null
+++ b/doc/sorosspec.odt
Binary files differ
diff --git a/doc/sorosspec.pdf b/doc/sorosspec.pdf
new file mode 100644
index 0000000..a4f0181
--- /dev/null
+++ b/doc/sorosspec.pdf
Binary files differ
diff --git a/idl/XNumberText.idl b/idl/XNumberText.idl
new file mode 100644
index 0000000..b2dcdda
--- /dev/null
+++ b/idl/XNumberText.idl
@@ -0,0 +1,28 @@
+#ifndef org_openoffice_addin_sample_XNumberText
+#define org_openoffice_addin_sample_XNumberText
+
+#include <com/sun/star/uno/XInterface.idl>
+#include <com/sun/star/beans/XPropertySet.idl>
+
+module org { module numbertext {
+
+ interface XNumberText : com::sun::star::uno::XInterface
+ {
+ string numbertext(
+ [in] com::sun::star::beans::XPropertySet prop,
+ [in] string num,
+ [in] any lang
+ );
+
+ string moneytext(
+ [in] com::sun::star::beans::XPropertySet prop,
+ [in] string num,
+ [in] any currency,
+ [in] any lang
+ );
+
+ };
+
+}; };
+
+#endif
diff --git a/idl/XNumberText.urd b/idl/XNumberText.urd
new file mode 100644
index 0000000..2984a34
--- /dev/null
+++ b/idl/XNumberText.urd
Binary files differ
diff --git a/idl/buildrdb.sh b/idl/buildrdb.sh
new file mode 100755
index 0000000..96f139b
--- /dev/null
+++ b/idl/buildrdb.sh
@@ -0,0 +1,7 @@
+# use this on linux with ooo build env
+idlc -I $SOLARVER/$INPATH/idl XNumberText.idl
+regmerge ../rdb/sample.rdb /UCR XNumberText.urd
+
+rem use this on windows with ooo build env
+rem guw.pl idlc -I $SOLARVER/$INPATH/idl XNumberText.idl
+rem guw.pl regmerge ../rdb/sample.rdb /UCR XNumberText.urd
diff --git a/java/Makefile b/java/Makefile
new file mode 100644
index 0000000..f93e7d8
--- /dev/null
+++ b/java/Makefile
@@ -0,0 +1,10 @@
+all:
+ cp ../data/*.sor org/numbertext/data
+ CLASSPATH=. javac org/numbertext/Numbertext.java
+ jar cfm numbertext.jar Manifest.txt org
+ java -jar numbertext.jar
+
+check:
+ java -jar numbertext.jar -l en 99-101
+ java -jar numbertext.jar -l en-GB 99-101
+ java -jar numbertext.jar -p ordinal -l en 1-10
diff --git a/java/Manifest.txt b/java/Manifest.txt
new file mode 100644
index 0000000..5aa42ed
--- /dev/null
+++ b/java/Manifest.txt
@@ -0,0 +1,3 @@
+Main-Class: org.numbertext.Numbertext
+Implementation-Version: 1.0b2
+Implementation-Date: 2018-04-26
diff --git a/java/org/numbertext/Numbertext.java b/java/org/numbertext/Numbertext.java
new file mode 100644
index 0000000..3f3a954
--- /dev/null
+++ b/java/org/numbertext/Numbertext.java
@@ -0,0 +1,101 @@
+/* See numbertext.org
+ * 2009-2010 (c) László Németh
+ * License: LGPL/BSD dual license */
+
+package org.numbertext;
+
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+import org.numbertext.Soros;
+import java.net.URL;
+import java.util.HashMap;
+
+public class Numbertext {
+ static HashMap<String, Soros> modules = new HashMap<String, Soros>();
+
+ private static Soros load(String langfile, String langcode) {
+ Soros s;
+ try {
+ URL url = Numbertext.class.getResource("data/" + langfile + ".sor");
+ BufferedReader f = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));
+ StringBuffer st = new StringBuffer();
+ String line = null;
+ while (( line = f.readLine()) != null) {
+ st.append(line);
+ st.append(System.getProperty("line.separator"));
+ }
+ s = new Soros(new String(st), langcode);
+ if (modules != null && langfile != null) modules.put(langcode, s);
+ } catch(Exception e) {
+ return null;
+ }
+ return s;
+ }
+
+ public static String numbertext(String input, String lang) {
+ Soros s = (Soros) modules.get(lang);
+ if (s == null) s = load(lang.replace('-', '_'), lang);
+ if (s == null) s = load(lang.replaceFirst("[-_].*", ""), lang);
+ if (s == null) {
+ System.out.println("Missing language module: " + lang);
+ return null;
+ }
+ return s.run(input);
+ }
+
+ public static String moneytext(String input, String money, String lang) {
+ return numbertext(money + " " + input, lang);
+ }
+
+ public static void main (String[] args) {
+ String lang = "en_US";
+ if (args.length == 0) {
+ System.out.println("Usage: java soros [-l lang] [-p prefix_function] [par1 [par2...]]");
+ System.out.println("Parameter: n: number; n-m: range; n-m~s: range with step");
+ System.out.println("Example: java -jar numbertext -l en_US -p ord 1-10 500 1000-10000~1000");
+ System.out.println(" java -jar numbertext -l en_US # print prefix functions of the language module");
+ System.out.println("License: GNU LGPL/BSD dual-license");
+ return;
+ }
+ int state = 0;
+ boolean missingNumbers = true;
+ String prefix = "";
+ for (int i = 0; i < args.length; i++) {
+ if (state != 0) {
+ if (state == 1) {
+ lang = args[i];
+ if (numbertext("1", lang) == null)
+ System.exit(1);
+ } else if (state == 2) prefix = args[i] + " ";
+ state = 0;
+ continue;
+ }
+ if (args[i].equals("-l")) {
+ state = 1;
+ } else if (args[i].equals("-p")) {
+ state = 2;
+ } else {
+ missingNumbers = false;
+ int idx = args[i].indexOf('-', 1);
+ if (idx > -1) {
+ int b = Integer.parseInt(args[i].substring(0, idx));
+ String e = args[i].substring(idx + 1);
+ int step = e.indexOf('~', idx);
+ int end;
+ if (step > -1) {
+ end = Integer.parseInt(e.substring(0, step));
+ step = Integer.parseInt(e.substring(step + 1));
+ } else {
+ step = 1;
+ end = Integer.parseInt(e);
+ }
+ for (int j = b; j <= end; j = j + step) {
+ System.out.println(numbertext(prefix + j, lang));
+ }
+ } else System.out.println(numbertext(prefix + args[i], lang));
+ }
+ } if (missingNumbers)
+ System.out.println(numbertext("help", lang));
+ }
+}
diff --git a/java/org/numbertext/Soros.java b/java/org/numbertext/Soros.java
new file mode 100644
index 0000000..45e79ee
--- /dev/null
+++ b/java/org/numbertext/Soros.java
@@ -0,0 +1,127 @@
+/* Soros interpreter (see numbertext.org)
+ * 2009-2010 (c) László Németh
+ * License: LGPL/BSD dual license */
+
+package org.numbertext;
+
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import java.util.ArrayList;
+
+public class Soros {
+ private ArrayList<Pattern> patterns = new ArrayList<Pattern>();
+ private ArrayList<String> values = new ArrayList<String>();
+ private ArrayList<Boolean> begins = new ArrayList<Boolean>();
+ private ArrayList<Boolean> ends = new ArrayList<Boolean>();
+
+ private static String m = "\\\";#";
+ private static String m2 = "$()|[]";
+ private static String c = "\uE000\uE001\uE002\uE003";
+ private static String c2 = "\uE004\uE005\uE006\uE007\uE008\uE009";
+ private static String slash = "\uE000";
+ private static String pipe = "\uE003";
+
+ // pattern to recognize function calls in the replacement string
+
+ private static Pattern func = Pattern.compile(translate(
+ "(?:\\|?(?:\\$\\()+)?" + // optional nested calls
+ "(\\|?\\$\\(([^\\(\\)]*)\\)\\|?)" + // inner call (2 subgroups)
+ "(?:\\)+\\|?)?", // optional nested calls
+ m2.substring(0, c.length()), c, "\\")); // \$, \(, \), \| -> \uE000..\uE003
+
+ private boolean numbertext = false;
+
+ public Soros(String source, String lang) {
+ source = translate(source, m, c, "\\"); // \\, \", \;, \# -> \uE000..\uE003
+ // switch off all country-dependent lines, and switch on the requested ones
+ source = source.replaceAll("(^|[\n;])([^\n;#]*#[^\n]*\\[:[^\n:\\]]*:][^\n]*)", "$1#$2")
+ .replaceAll("(^|[\n;])#([^\n;#]*#[^\n]*\\[:" + lang.replace('_', '-') + ":][^\n]*)", "$1$2")
+ .replaceAll("(#[^\n]*)?(\n|$)", ";"); // remove comments
+ if (source.indexOf("__numbertext__") == -1)
+ source = "__numbertext__;" + source;
+ source = source.replace("__numbertext__",
+ // default left zero deletion
+ "\"([a-z][-a-z]* )?0+(0|[1-9]\\d*)\" $(\\1\\2);" +
+ // separator function
+ "\"\uE00A(.*)\uE00A(.+)\uE00A(.*)\" \\1\\2\\3;" +
+ // no separation, if subcall returns with empty string
+ "\"\uE00A.*\uE00A\uE00A.*\"");
+
+ Pattern p = Pattern.compile("^\\s*(\"[^\"]*\"|[^\\s]*)\\s*(.*[^\\s])?\\s*$");
+ Pattern macro = Pattern.compile("== *(.*[^ ]?) ==");
+ String prefix = "";
+ for (String s : source.split(";")) {
+ Matcher matchmacro = macro.matcher(s);
+ if (matchmacro.matches()) {
+ prefix = matchmacro.group(1);
+ continue;
+ }
+ Matcher sp = p.matcher(s);
+ if (!prefix.equals("") && !s.equals("") && sp.matches()) {
+ s = sp.group(1).replaceFirst("^\"", "").replaceFirst("\"$","");
+ s = "\"" + (s.startsWith("^") ? "^" : "") + prefix + (s.equals("") ? "" : " ") +
+ s.replaceFirst("^\\^", "") + "\" " + sp.group(2);
+ sp = p.matcher(s);
+ }
+ if (!s.equals("") && sp.matches()) {
+ s = translate(sp.group(1).replaceFirst("^\"", "").replaceFirst("\"$",""),
+ c.substring(1), m.substring(1), "");
+ s = s.replace(slash, "\\\\"); // -> \\, ", ;, #
+ String s2 = "";
+ if (sp.group(2) != null) s2 = sp.group(2).replaceFirst("^\"", "").replaceFirst("\"$","");
+ s2 = translate(s2, m2, c2, "\\"); // \$, \(, \), \|, \[, \] -> \uE004..\uE009
+ // call inner separator: [ ... $1 ... ] -> $(\uE00A ... \uE00A$1\uE00A ... )
+ s2 = s2.replaceAll("^\\[[$](\\d\\d?|\\([^\\)]+\\))", "\\$(\uE00A\uE00A|\\$$1\uE00A") // add "|"
+ .replaceAll("\\[([^$\\[\\\\]*)[$](\\d\\d?|\\([^\\)]+\\))", "\\$(\uE00A$1\uE00A\\$$2\uE00A")
+ .replaceAll("\uE00A\\]$","|\uE00A)") // add "|" in terminating position
+ .replaceAll("\\]", ")")
+ .replaceAll("(\\$\\d|\\))\\|\\$", "$1||\\$"); // $()|$() -> $()||$()
+ s2 = translate(s2, c, m, ""); // \uE000..\uE003-> \, ", ;, #
+ s2 = translate(s2, m2.substring(0, c.length()), c, ""); // $, (, ), | -> \uE000..\uE003
+ s2 = translate(s2, c2, m2, ""); // \uE004..\uE009 -> $, (, ), |, [, ]
+ s2 = s2.replaceAll("[$]", "\\$") // $ -> \$
+ .replaceAll("\uE000(\\d)", "\uE000\uE001\\$$1\uE002") // $n -> $(\n)
+ .replaceAll("\\\\(\\d)", "\\$$1") // \[n] -> $[n]
+ .replace("\\n", "\n"); // \n -> [new line]
+ patterns.add(Pattern.compile("^" + s.replaceFirst("^\\^", "")
+ .replaceFirst("\\$$", "") + "$"));
+ begins.add(s.startsWith("^"));
+ ends.add(s.endsWith("$"));
+ values.add(s2);
+ }
+ }
+ }
+
+ public String run(String input) {
+ return run(input, true, true);
+ }
+
+ private String run(String input, boolean begin, boolean end) {
+ for (int i = 0; i < patterns.size(); i++) {
+ if ((!begin && begins.get(i)) || (!end && ends.get(i))) continue;
+ Matcher m = patterns.get(i).matcher(input);
+ if (!m.matches()) continue;
+ String s = m.replaceAll(values.get(i));
+ Matcher n = func.matcher(s);
+ while (n.find()) {
+ boolean b = false;
+ boolean e = false;
+ if (n.group(1).startsWith(pipe) || n.group().startsWith(pipe)) b = true;
+ else if (n.start() == 0) b = begin;
+ if (n.group(1).endsWith(pipe) || n.group().endsWith(pipe)) e = true;
+ else if (n.end() == s.length()) e = end;
+ s = s.substring(0, n.start(1)) + run(n.group(2), b, e) + s.substring(n.end(1));
+ n = func.matcher(s);
+ }
+ return s;
+ }
+ return "";
+ }
+
+ private static String translate(String s, String chars, String chars2, String delim) {
+ for (int i = 0; i < chars.length(); i++) {
+ s = s.replace(delim + chars.charAt(i), "" + chars2.charAt(i));
+ }
+ return s;
+ }
+}
diff --git a/libnumbertext.pc.in b/libnumbertext.pc.in
new file mode 100644
index 0000000..2385819
--- /dev/null
+++ b/libnumbertext.pc.in
@@ -0,0 +1,15 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir=@datarootdir@
+datadir=@datadir@
+pkgdatadir=${datarootdir}/libnumbertext
+
+Name: libnumbertext
+Description: Library implementing Soros based Number to Number Name conversion
+Version: @VERSION@
+Requires:
+Libs: -L${libdir} -lnumbertext-1.0
+Cflags: -I${includedir}/libnumbertext/
+
diff --git a/m4/boost.m4 b/m4/boost.m4
new file mode 100644
index 0000000..a0894f3
--- /dev/null
+++ b/m4/boost.m4
@@ -0,0 +1,1574 @@
+# boost.m4: Locate Boost headers and libraries for autoconf-based projects.
+# Copyright (C) 2007-2011, 2014 Benoit Sigoure <tsuna@lrde.epita.fr>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Additional permission under section 7 of the GNU General Public
+# License, version 3 ("GPLv3"):
+#
+# If you convey this file as part of a work that contains a
+# configuration script generated by Autoconf, you may do so under
+# terms of your choice.
+#
+# 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+m4_define([_BOOST_SERIAL], [m4_translit([
+# serial 26
+], [#
+], [])])
+
+# Original sources can be found at http://github.com/tsuna/boost.m4
+# You can fetch the latest version of the script by doing:
+# wget http://github.com/tsuna/boost.m4/raw/master/build-aux/boost.m4
+
+# ------ #
+# README #
+# ------ #
+
+# This file provides several macros to use the various Boost libraries.
+# The first macro is BOOST_REQUIRE. It will simply check if it's possible to
+# find the Boost headers of a given (optional) minimum version and it will
+# define BOOST_CPPFLAGS accordingly. It will add an option --with-boost to
+# your configure so that users can specify non standard locations.
+# If the user's environment contains BOOST_ROOT and --with-boost was not
+# specified, --with-boost=$BOOST_ROOT is implicitly used.
+# For more README and documentation, go to http://github.com/tsuna/boost.m4
+# Note: THESE MACROS ASSUME THAT YOU USE LIBTOOL. If you don't, don't worry,
+# simply read the README, it will show you what to do step by step.
+
+m4_pattern_forbid([^_?(BOOST|Boost)_])
+
+
+# _BOOST_SED_CPP(SED-PROGRAM, PROGRAM,
+# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# --------------------------------------------------------
+# Same as AC_EGREP_CPP, but leave the result in conftest.i.
+#
+# SED-PROGRAM is *not* overquoted, as in AC_EGREP_CPP. It is expanded
+# in double-quotes, so escape your double quotes.
+#
+# It could be useful to turn this into a macro which extracts the
+# value of any macro.
+m4_define([_BOOST_SED_CPP],
+[AC_LANG_PUSH([C++])dnl
+AC_LANG_PREPROC_REQUIRE()dnl
+AC_REQUIRE([AC_PROG_SED])dnl
+AC_LANG_CONFTEST([AC_LANG_SOURCE([[$2]])])
+AS_IF([dnl eval is necessary to expand ac_cpp.
+dnl Ultrix and Pyramid sh refuse to redirect output of eval, so use subshell.
+dnl Beware of Windows end-of-lines, for instance if we are running
+dnl some Windows programs under Wine. In that case, boost/version.hpp
+dnl is certainly using "\r\n", but the regular Unix shell will only
+dnl strip `\n' with backquotes, not the `\r'. This results in
+dnl boost_cv_lib_version='1_37\r' for instance, which breaks
+dnl everything else.
+dnl Cannot use 'dnl' after [$4] because a trailing dnl may break AC_CACHE_CHECK
+dnl
+dnl Beware that GCC 5, when expanding macros, may embed # line directives
+dnl a within single line:
+dnl
+dnl # 1 "conftest.cc"
+dnl # 1 "<built-in>"
+dnl # 1 "<command-line>"
+dnl # 1 "conftest.cc"
+dnl # 1 "/opt/local/include/boost/version.hpp" 1 3
+dnl # 2 "conftest.cc" 2
+dnl boost-lib-version =
+dnl # 2 "conftest.cc" 3
+dnl "1_56"
+dnl
+dnl So get rid of the # and empty lines, and glue the remaining ones together.
+(eval "$ac_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD |
+ grep -v '#' |
+ grep -v '^[[[:space:]]]*$' |
+ tr -d '\r' |
+ tr -s '\n' ' ' |
+ $SED -n -e "$1" >conftest.i 2>&1],
+ [$3],
+ [$4])
+rm -rf conftest*
+AC_LANG_POP([C++])dnl
+])# _BOOST_SED_CPP
+
+
+
+# BOOST_REQUIRE([VERSION], [ACTION-IF-NOT-FOUND])
+# -----------------------------------------------
+# Look for Boost. If version is given, it must either be a literal of the form
+# "X.Y.Z" where X, Y and Z are integers (the ".Z" part being optional) or a
+# variable "$var".
+# Defines the value BOOST_CPPFLAGS. This macro only checks for headers with
+# the required version, it does not check for any of the Boost libraries.
+# On # success, defines HAVE_BOOST. On failure, calls the optional
+# ACTION-IF-NOT-FOUND action if one was supplied.
+# Otherwise aborts with an error message.
+AC_DEFUN_ONCE([BOOST_REQUIRE],
+[AC_REQUIRE([AC_PROG_CXX])dnl
+AC_REQUIRE([AC_PROG_GREP])dnl
+echo "$as_me: this is boost.m4[]_BOOST_SERIAL" >&AS_MESSAGE_LOG_FD
+boost_save_IFS=$IFS
+boost_version_req=$1
+IFS=.
+set x $boost_version_req 0 0 0
+IFS=$boost_save_IFS
+shift
+boost_version_req=`expr "$[1]" '*' 100000 + "$[2]" '*' 100 + "$[3]"`
+boost_version_req_string=$[1].$[2].$[3]
+AC_ARG_WITH([boost],
+ [AS_HELP_STRING([--with-boost=DIR],
+ [prefix of Boost $1 @<:@guess@:>@])])dnl
+AC_ARG_VAR([BOOST_ROOT],[Location of Boost installation])dnl
+# If BOOST_ROOT is set and the user has not provided a value to
+# --with-boost, then treat BOOST_ROOT as if it the user supplied it.
+if test x"$BOOST_ROOT" != x; then
+ if test x"$with_boost" = x; then
+ AC_MSG_NOTICE([Detected BOOST_ROOT; continuing with --with-boost=$BOOST_ROOT])
+ with_boost=$BOOST_ROOT
+ else
+ AC_MSG_NOTICE([Detected BOOST_ROOT=$BOOST_ROOT, but overridden by --with-boost=$with_boost])
+ fi
+fi
+AC_SUBST([DISTCHECK_CONFIGURE_FLAGS],
+ ["$DISTCHECK_CONFIGURE_FLAGS '--with-boost=$with_boost'"])dnl
+boost_save_CPPFLAGS=$CPPFLAGS
+ AC_CACHE_CHECK([for Boost headers version >= $boost_version_req_string],
+ [boost_cv_inc_path],
+ [boost_cv_inc_path=no
+AC_LANG_PUSH([C++])dnl
+m4_pattern_allow([^BOOST_VERSION$])dnl
+ AC_LANG_CONFTEST([AC_LANG_PROGRAM([[#include <boost/version.hpp>
+#if !defined BOOST_VERSION
+# error BOOST_VERSION is not defined
+#elif BOOST_VERSION < $boost_version_req
+# error Boost headers version < $boost_version_req
+#endif
+]])])
+ # If the user provided a value to --with-boost, use it and only it.
+ case $with_boost in #(
+ ''|yes) set x '' /opt/local/include /usr/local/include /opt/include \
+ /usr/include C:/Boost/include;; #(
+ *) set x "$with_boost/include" "$with_boost";;
+ esac
+ shift
+ for boost_dir
+ do
+ # Without --layout=system, Boost (or at least some versions) installs
+ # itself in <prefix>/include/boost-<version>. This inner loop helps to
+ # find headers in such directories.
+ #
+ # Any ${boost_dir}/boost-x_xx directories are searched in reverse version
+ # order followed by ${boost_dir}. The final '.' is a sentinel for
+ # searching $boost_dir" itself. Entries are whitespace separated.
+ #
+ # I didn't indent this loop on purpose (to avoid over-indented code)
+ boost_layout_system_search_list=`cd "$boost_dir" 2>/dev/null \
+ && ls -1 | "${GREP}" '^boost-' | sort -rn -t- -k2 \
+ && echo .`
+ for boost_inc in $boost_layout_system_search_list
+ do
+ if test x"$boost_inc" != x.; then
+ boost_inc="$boost_dir/$boost_inc"
+ else
+ boost_inc="$boost_dir" # Uses sentinel in boost_layout_system_search_list
+ fi
+ if test x"$boost_inc" != x; then
+ # We are going to check whether the version of Boost installed
+ # in $boost_inc is usable by running a compilation that
+ # #includes it. But if we pass a -I/some/path in which Boost
+ # is not installed, the compiler will just skip this -I and
+ # use other locations (either from CPPFLAGS, or from its list
+ # of system include directories). As a result we would use
+ # header installed on the machine instead of the /some/path
+ # specified by the user. So in that precise case (trying
+ # $boost_inc), make sure the version.hpp exists.
+ #
+ # Use test -e as there can be symlinks.
+ test -e "$boost_inc/boost/version.hpp" || continue
+ CPPFLAGS="$CPPFLAGS -I$boost_inc"
+ fi
+ AC_COMPILE_IFELSE([], [boost_cv_inc_path=yes], [boost_cv_version=no])
+ if test x"$boost_cv_inc_path" = xyes; then
+ if test x"$boost_inc" != x; then
+ boost_cv_inc_path=$boost_inc
+ fi
+ break 2
+ fi
+ done
+ done
+AC_LANG_POP([C++])dnl
+ ])
+ case $boost_cv_inc_path in #(
+ no)
+ boost_errmsg="cannot find Boost headers version >= $boost_version_req_string"
+ m4_if([$2], [], [AC_MSG_ERROR([$boost_errmsg])],
+ [AC_MSG_NOTICE([$boost_errmsg])])
+ $2
+ ;;#(
+ yes)
+ BOOST_CPPFLAGS=
+ ;;#(
+ *)
+ AC_SUBST([BOOST_CPPFLAGS], ["-I$boost_cv_inc_path"])dnl
+ ;;
+ esac
+ if test x"$boost_cv_inc_path" != xno; then
+ AC_DEFINE([HAVE_BOOST], [1],
+ [Defined if the requested minimum BOOST version is satisfied])
+ AC_CACHE_CHECK([for Boost's header version],
+ [boost_cv_lib_version],
+ [m4_pattern_allow([^BOOST_LIB_VERSION$])dnl
+ _BOOST_SED_CPP([[/^boost-lib-version = /{s///;s/[\" ]//g;p;q;}]],
+ [#include <boost/version.hpp>
+boost-lib-version = BOOST_LIB_VERSION],
+ [boost_cv_lib_version=`cat conftest.i`])])
+ # e.g. "134" for 1_34_1 or "135" for 1_35
+ boost_major_version=`echo "$boost_cv_lib_version" | sed 's/_//;s/_.*//'`
+ case $boost_major_version in #(
+ '' | *[[!0-9]]*)
+ AC_MSG_ERROR([invalid value: boost_major_version='$boost_major_version'])
+ ;;
+ esac
+fi
+CPPFLAGS=$boost_save_CPPFLAGS
+])# BOOST_REQUIRE
+
+
+# BOOST_STATIC()
+# --------------
+# Add the "--enable-static-boost" configure argument. If this argument is given
+# on the command line, static versions of the libraries will be looked up.
+AC_DEFUN([BOOST_STATIC],
+ [AC_ARG_ENABLE([static-boost],
+ [AS_HELP_STRING([--enable-static-boost],
+ [Prefer the static boost libraries over the shared ones [no]])],
+ [enable_static_boost=yes],
+ [enable_static_boost=no])])# BOOST_STATIC
+
+
+# BOOST_FIND_HEADER([HEADER-NAME], [ACTION-IF-NOT-FOUND], [ACTION-IF-FOUND])
+# --------------------------------------------------------------------------
+# Wrapper around AC_CHECK_HEADER for Boost headers. Useful to check for
+# some parts of the Boost library which are only made of headers and don't
+# require linking (such as Boost.Foreach).
+#
+# Default ACTION-IF-NOT-FOUND: Fail with a fatal error unless Boost couldn't be
+# found in the first place, in which case by default a notice is issued to the
+# user. Presumably if we haven't died already it's because it's OK to not have
+# Boost, which is why only a notice is issued instead of a hard error.
+#
+# Default ACTION-IF-FOUND: define the preprocessor symbol HAVE_<HEADER-NAME> in
+# case of success # (where HEADER-NAME is written LIKE_THIS, e.g.,
+# HAVE_BOOST_FOREACH_HPP).
+AC_DEFUN([BOOST_FIND_HEADER],
+[AC_REQUIRE([BOOST_REQUIRE])dnl
+if test x"$boost_cv_inc_path" = xno; then
+ m4_default([$2], [AC_MSG_NOTICE([Boost not available, not searching for $1])])
+else
+AC_LANG_PUSH([C++])dnl
+boost_save_CPPFLAGS=$CPPFLAGS
+CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+AC_CHECK_HEADER([$1],
+ [m4_default([$3], [AC_DEFINE(AS_TR_CPP([HAVE_$1]), [1],
+ [Define to 1 if you have <$1>])])],
+ [m4_default([$2], [AC_MSG_ERROR([cannot find $1])])])
+CPPFLAGS=$boost_save_CPPFLAGS
+AC_LANG_POP([C++])dnl
+fi
+])# BOOST_FIND_HEADER
+
+
+# BOOST_FIND_LIBS([COMPONENT-NAME], [CANDIDATE-LIB-NAMES],
+# [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST],
+# [CXX-PROLOGUE])
+# --------------------------------------------------------------
+# Look for the Boost library COMPONENT-NAME (e.g., `thread', for
+# libboost_thread) under the possible CANDIDATE-LIB-NAMES (e.g.,
+# "thread_win32 thread"). Check that HEADER-NAME works and check that
+# libboost_LIB-NAME can link with the code CXX-TEST. The optional
+# argument CXX-PROLOGUE can be used to include some C++ code before
+# the `main' function.
+#
+# Invokes BOOST_FIND_HEADER([HEADER-NAME]) (see above).
+#
+# Boost libraries typically come compiled with several flavors (with different
+# runtime options) so PREFERRED-RT-OPT is the preferred suffix. A suffix is one
+# or more of the following letters: sgdpn (in that order). s = static
+# runtime, d = debug build, g = debug/diagnostic runtime, p = STLPort build,
+# n = (unsure) STLPort build without iostreams from STLPort (it looks like `n'
+# must always be used along with `p'). Additionally, PREFERRED-RT-OPT can
+# start with `mt-' to indicate that there is a preference for multi-thread
+# builds. Some sample values for PREFERRED-RT-OPT: (nothing), mt, d, mt-d, gdp
+# ... If you want to make sure you have a specific version of Boost
+# (eg, >= 1.33) you *must* invoke BOOST_REQUIRE before this macro.
+AC_DEFUN([BOOST_FIND_LIBS],
+[AC_REQUIRE([BOOST_REQUIRE])dnl
+AC_REQUIRE([_BOOST_FIND_COMPILER_TAG])dnl
+AC_REQUIRE([BOOST_STATIC])dnl
+AC_REQUIRE([_BOOST_GUESS_WHETHER_TO_USE_MT])dnl
+if test x"$boost_cv_inc_path" = xno; then
+ AC_MSG_NOTICE([Boost not available, not searching for the Boost $1 library])
+else
+dnl The else branch is huge and wasn't intended on purpose.
+AC_LANG_PUSH([C++])dnl
+AS_VAR_PUSHDEF([Boost_lib], [boost_cv_lib_$1])dnl
+AS_VAR_PUSHDEF([Boost_lib_LDFLAGS], [boost_cv_lib_$1_LDFLAGS])dnl
+AS_VAR_PUSHDEF([Boost_lib_LDPATH], [boost_cv_lib_$1_LDPATH])dnl
+AS_VAR_PUSHDEF([Boost_lib_LIBS], [boost_cv_lib_$1_LIBS])dnl
+BOOST_FIND_HEADER([$4])
+boost_save_CPPFLAGS=$CPPFLAGS
+CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+AC_CACHE_CHECK([for the Boost $1 library], [Boost_lib],
+ [_BOOST_FIND_LIBS($@)])
+case $Boost_lib in #(
+ (no) _AC_MSG_LOG_CONFTEST
+ AC_MSG_ERROR([cannot find the flags to link with Boost $1])
+ ;;
+esac
+AC_SUBST(AS_TR_CPP([BOOST_$1_LDFLAGS]), [$Boost_lib_LDFLAGS])dnl
+AC_SUBST(AS_TR_CPP([BOOST_$1_LDPATH]), [$Boost_lib_LDPATH])dnl
+AC_SUBST([BOOST_LDPATH], [$Boost_lib_LDPATH])dnl
+AC_SUBST(AS_TR_CPP([BOOST_$1_LIBS]), [$Boost_lib_LIBS])dnl
+CPPFLAGS=$boost_save_CPPFLAGS
+AS_VAR_POPDEF([Boost_lib])dnl
+AS_VAR_POPDEF([Boost_lib_LDFLAGS])dnl
+AS_VAR_POPDEF([Boost_lib_LDPATH])dnl
+AS_VAR_POPDEF([Boost_lib_LIBS])dnl
+AC_LANG_POP([C++])dnl
+fi
+])
+
+
+# BOOST_FIND_LIB([LIB-NAME],
+# [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST],
+# [CXX-PROLOGUE])
+# --------------------------------------------------------------
+# Backward compatibility wrapper for BOOST_FIND_LIBS.
+AC_DEFUN([BOOST_FIND_LIB],
+[BOOST_FIND_LIBS([$1], $@)])
+
+
+# _BOOST_FIND_LIBS([LIB-NAME], [CANDIDATE-LIB-NAMES],
+# [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST],
+# [CXX-PROLOGUE])
+# --------------------------------------------------------------
+# Real implementation of BOOST_FIND_LIBS: rely on these local macros:
+# Boost_lib, Boost_lib_LDFLAGS, Boost_lib_LDPATH, Boost_lib_LIBS
+#
+# The algorithm is as follows: first look for a given library name
+# according to the user's PREFERRED-RT-OPT. For each library name, we
+# prefer to use the ones that carry the tag (toolset name). Each
+# library is searched through the various standard paths were Boost is
+# usually installed. If we can't find the standard variants, we try
+# to enforce -mt (for instance on MacOSX, libboost_thread.dylib
+# doesn't exist but there's -obviously- libboost_thread-mt.dylib).
+AC_DEFUN([_BOOST_FIND_LIBS],
+[Boost_lib=no
+ case "$3" in #(
+ (mt | mt-) boost_mt=-mt; boost_rtopt=;; #(
+ (mt* | mt-*) boost_mt=-mt; boost_rtopt=`expr "X$3" : 'Xmt-*\(.*\)'`;; #(
+ (*) boost_mt=; boost_rtopt=$3;;
+ esac
+ if test $enable_static_boost = yes; then
+ boost_rtopt="s$boost_rtopt"
+ fi
+ # Find the proper debug variant depending on what we've been asked to find.
+ case $boost_rtopt in #(
+ (*d*) boost_rt_d=$boost_rtopt;; #(
+ (*[[sgpn]]*) # Insert the `d' at the right place (in between `sg' and `pn')
+ boost_rt_d=`echo "$boost_rtopt" | sed 's/\(s*g*\)\(p*n*\)/\1\2/'`;; #(
+ (*) boost_rt_d='-d';;
+ esac
+ # If the PREFERRED-RT-OPT are not empty, prepend a `-'.
+ test -n "$boost_rtopt" && boost_rtopt="-$boost_rtopt"
+ $boost_guess_use_mt && boost_mt=-mt
+ # Look for the abs path the static archive.
+ # $libext is computed by Libtool but let's make sure it's non empty.
+ test -z "$libext" &&
+ AC_MSG_ERROR([the libext variable is empty, did you invoke Libtool?])
+ boost_save_ac_objext=$ac_objext
+ # Generate the test file.
+ AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include <$4>
+$6], [$5])])
+dnl Optimization hacks: compiling C++ is slow, especially with Boost. What
+dnl we're trying to do here is guess the right combination of link flags
+dnl (LIBS / LDFLAGS) to use a given library. This can take several
+dnl iterations before it succeeds and is thus *very* slow. So what we do
+dnl instead is that we compile the code first (and thus get an object file,
+dnl typically conftest.o). Then we try various combinations of link flags
+dnl until we succeed to link conftest.o in an executable. The problem is
+dnl that the various TRY_LINK / COMPILE_IFELSE macros of Autoconf always
+dnl remove all the temporary files including conftest.o. So the trick here
+dnl is to temporarily change the value of ac_objext so that conftest.o is
+dnl preserved accross tests. This is obviously fragile and I will burn in
+dnl hell for not respecting Autoconf's documented interfaces, but in the
+dnl mean time, it optimizes the macro by a factor of 5 to 30.
+dnl Another small optimization: the first argument of AC_COMPILE_IFELSE left
+dnl empty because the test file is generated only once above (before we
+dnl start the for loops).
+ AC_COMPILE_IFELSE([],
+ [ac_objext=do_not_rm_me_plz],
+ [AC_MSG_ERROR([cannot compile a test that uses Boost $1])])
+ ac_objext=$boost_save_ac_objext
+ boost_failed_libs=
+# Don't bother to ident the following nested for loops, only the 2
+# innermost ones matter.
+for boost_lib_ in $2; do
+for boost_tag_ in -$boost_cv_lib_tag ''; do
+for boost_ver_ in -$boost_cv_lib_version ''; do
+for boost_mt_ in $boost_mt -mt ''; do
+for boost_rtopt_ in $boost_rtopt '' -d; do
+ for boost_lib in \
+ boost_$boost_lib_$boost_tag_$boost_mt_$boost_rtopt_$boost_ver_ \
+ boost_$boost_lib_$boost_tag_$boost_rtopt_$boost_ver_ \
+ boost_$boost_lib_$boost_tag_$boost_mt_$boost_ver_ \
+ boost_$boost_lib_$boost_tag_$boost_ver_
+ do
+ # Avoid testing twice the same lib
+ case $boost_failed_libs in #(
+ (*@$boost_lib@*) continue;;
+ esac
+ # If with_boost is empty, we'll search in /lib first, which is not quite
+ # right so instead we'll try to a location based on where the headers are.
+ boost_tmp_lib=$with_boost
+ test x"$with_boost" = x && boost_tmp_lib=${boost_cv_inc_path%/include}
+ for boost_ldpath in "$boost_tmp_lib/lib" '' \
+ /opt/local/lib* /usr/local/lib* /opt/lib* /usr/lib* \
+ "$with_boost" C:/Boost/lib /lib*
+ do
+ # Don't waste time with directories that don't exist.
+ if test x"$boost_ldpath" != x && test ! -e "$boost_ldpath"; then
+ continue
+ fi
+ boost_save_LDFLAGS=$LDFLAGS
+ # Are we looking for a static library?
+ case $boost_ldpath:$boost_rtopt_ in #(
+ (*?*:*s*) # Yes (Non empty boost_ldpath + s in rt opt)
+ Boost_lib_LIBS="$boost_ldpath/lib$boost_lib.$libext"
+ test -e "$Boost_lib_LIBS" || continue;; #(
+ (*) # No: use -lboost_foo to find the shared library.
+ Boost_lib_LIBS="-l$boost_lib";;
+ esac
+ boost_save_LIBS=$LIBS
+ LIBS="$Boost_lib_LIBS $LIBS"
+ test x"$boost_ldpath" != x && LDFLAGS="$LDFLAGS -L$boost_ldpath"
+dnl First argument of AC_LINK_IFELSE left empty because the test file is
+dnl generated only once above (before we start the for loops).
+ _BOOST_AC_LINK_IFELSE([],
+ [Boost_lib=yes], [Boost_lib=no])
+ ac_objext=$boost_save_ac_objext
+ LDFLAGS=$boost_save_LDFLAGS
+ LIBS=$boost_save_LIBS
+ if test x"$Boost_lib" = xyes; then
+ # Check or used cached result of whether or not using -R or
+ # -rpath makes sense. Some implementations of ld, such as for
+ # Mac OSX, require -rpath but -R is the flag known to work on
+ # other systems. https://github.com/tsuna/boost.m4/issues/19
+ AC_CACHE_VAL([boost_cv_rpath_link_ldflag],
+ [case $boost_ldpath in
+ '') # Nothing to do.
+ boost_cv_rpath_link_ldflag=
+ boost_rpath_link_ldflag_found=yes;;
+ *)
+ for boost_cv_rpath_link_ldflag in -Wl,-R, -Wl,-rpath,; do
+ LDFLAGS="$boost_save_LDFLAGS -L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath"
+ LIBS="$boost_save_LIBS $Boost_lib_LIBS"
+ _BOOST_AC_LINK_IFELSE([],
+ [boost_rpath_link_ldflag_found=yes
+ break],
+ [boost_rpath_link_ldflag_found=no])
+ done
+ ;;
+ esac
+ AS_IF([test "x$boost_rpath_link_ldflag_found" != "xyes"],
+ [AC_MSG_ERROR([Unable to determine whether to use -R or -rpath])])
+ LDFLAGS=$boost_save_LDFLAGS
+ LIBS=$boost_save_LIBS
+ ])
+ test x"$boost_ldpath" != x &&
+ Boost_lib_LDFLAGS="-L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath"
+ Boost_lib_LDPATH="$boost_ldpath"
+ break 7
+ else
+ boost_failed_libs="$boost_failed_libs@$boost_lib@"
+ fi
+ done
+ done
+done
+done
+done
+done
+done # boost_lib_
+rm -f conftest.$ac_objext
+])
+
+
+
+# --------------------------------------- #
+# Checks for the various Boost libraries. #
+# --------------------------------------- #
+
+# List of boost libraries: http://www.boost.org/libs/libraries.htm
+# The page http://beta.boost.org/doc/libs is useful: it gives the first release
+# version of each library (among other things).
+
+# BOOST_DEFUN(LIBRARY, CODE)
+# --------------------------
+# Define BOOST_<LIBRARY-UPPERCASE> as a macro that runs CODE.
+#
+# Use indir to avoid the warning on underquoted macro name given to AC_DEFUN.
+m4_define([BOOST_DEFUN],
+[m4_indir([AC_DEFUN],
+ m4_toupper([BOOST_$1]),
+[m4_pushdef([BOOST_Library], [$1])dnl
+$2
+m4_popdef([BOOST_Library])dnl
+])
+])
+
+# BOOST_ARRAY()
+# -------------
+# Look for Boost.Array
+BOOST_DEFUN([Array],
+[BOOST_FIND_HEADER([boost/array.hpp])])
+
+
+# BOOST_ASIO()
+# ------------
+# Look for Boost.Asio (new in Boost 1.35).
+BOOST_DEFUN([Asio],
+[AC_REQUIRE([BOOST_SYSTEM])dnl
+BOOST_FIND_HEADER([boost/asio.hpp])])
+
+
+# BOOST_ASSIGN()
+# -------------
+# Look for Boost.Assign
+BOOST_DEFUN([Assign],
+[BOOST_FIND_HEADER([boost/assign.hpp])])
+
+
+# BOOST_BIND()
+# ------------
+# Look for Boost.Bind.
+BOOST_DEFUN([Bind],
+[BOOST_FIND_HEADER([boost/bind.hpp])])
+
+
+# BOOST_CHRONO()
+# --------------
+# Look for Boost.Chrono.
+BOOST_DEFUN([Chrono],
+[# Do we have to check for Boost.System? This link-time dependency was
+# added as of 1.35.0. If we have a version <1.35, we must not attempt to
+# find Boost.System as it didn't exist by then.
+if test $boost_major_version -ge 135; then
+ BOOST_SYSTEM([$1])
+fi # end of the Boost.System check.
+boost_filesystem_save_LIBS=$LIBS
+boost_filesystem_save_LDFLAGS=$LDFLAGS
+m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl
+LIBS="$LIBS $BOOST_SYSTEM_LIBS"
+LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS"
+BOOST_FIND_LIB([chrono], [$1],
+ [boost/chrono.hpp],
+ [boost::chrono::thread_clock d;])
+if test $enable_static_boost = yes && test $boost_major_version -ge 135; then
+ BOOST_CHRONO_LIBS="$BOOST_CHRONO_LIBS $BOOST_SYSTEM_LIBS"
+fi
+LIBS=$boost_filesystem_save_LIBS
+LDFLAGS=$boost_filesystem_save_LDFLAGS
+])# BOOST_CHRONO
+
+
+# BOOST_CONTEXT([PREFERRED-RT-OPT])
+# -----------------------------------
+# Look for Boost.Context. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+#
+# * This library was introduced in Boost 1.51.0
+# * The signatures of make_fcontext() and jump_fcontext were changed in 1.56.0
+# * A dependency on boost_thread appears in 1.57.0
+BOOST_DEFUN([Context],
+[boost_context_save_LIBS=$LIBS
+ boost_context_save_LDFLAGS=$LDFLAGS
+if test $boost_major_version -ge 157; then
+ BOOST_THREAD([$1])
+ m4_pattern_allow([^BOOST_THREAD_(LIBS|LDFLAGS)$])dnl
+ LIBS="$LIBS $BOOST_THREAD_LIBS"
+ LDFLAGS="$LDFLAGS $BOOST_THREAD_LDFLAGS"
+fi
+BOOST_FIND_LIB([context], [$1],
+ [boost/context/all.hpp],[[
+
+// creates a stack
+void * stack_pointer = new void*[4096];
+std::size_t const size = sizeof(void*[4096]);
+
+#if BOOST_VERSION <= 105100
+ctx::make_fcontext(&fc, f);
+return ctx::jump_fcontext(&fcm, &fc, 3) == 6;
+
+#else
+
+fc = ctx::make_fcontext(stack_pointer, size, f);
+return ctx::jump_fcontext(&fcm, fc, 3) == 6;
+
+#endif
+
+
+]],[dnl
+
+#include <boost/version.hpp>
+#if BOOST_VERSION <= 105100
+
+namespace ctx = boost::ctx;
+
+static ctx::fcontext_t fcm, fc;
+
+static void f(intptr_t i) {
+ ctx::jump_fcontext(&fc, &fcm, i * 2);
+}
+
+#elif BOOST_VERSION <= 105500
+
+namespace ctx = boost::context;
+
+// context
+static ctx::fcontext_t fcm, *fc;
+
+// context-function
+static void f(intptr_t i) {
+ ctx::jump_fcontext(fc, &fcm, i * 2);
+}
+
+#else
+
+namespace ctx = boost::context;
+
+// context
+static ctx::fcontext_t fcm, fc;
+
+// context-function
+static void f(intptr_t i) {
+ ctx::jump_fcontext(&fc, fcm, i * 2);
+}
+#endif
+])
+LIBS=$boost_context_save_LIBS
+LDFLAGS=$boost_context_save_LDFLAGS
+])# BOOST_CONTEXT
+
+
+# BOOST_CONVERSION()
+# ------------------
+# Look for Boost.Conversion (cast / lexical_cast)
+BOOST_DEFUN([Conversion],
+[BOOST_FIND_HEADER([boost/cast.hpp])
+BOOST_FIND_HEADER([boost/lexical_cast.hpp])
+])# BOOST_CONVERSION
+
+
+# BOOST_COROUTINE([PREFERRED-RT-OPT])
+# -----------------------------------
+# Look for Boost.Coroutine. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above. This library was introduced in Boost
+# 1.53.0
+BOOST_DEFUN([Coroutine],
+[
+boost_coroutine_save_LIBS=$LIBS
+boost_coroutine_save_LDFLAGS=$LDFLAGS
+# Link-time dependency from coroutine to context
+BOOST_CONTEXT([$1])
+# Starting from Boost 1.55 a dependency on Boost.System is added
+if test $boost_major_version -ge 155; then
+ BOOST_SYSTEM([$1])
+fi
+m4_pattern_allow([^BOOST_(CONTEXT|SYSTEM)_(LIBS|LDFLAGS)])
+LIBS="$LIBS $BOOST_CONTEXT_LIBS $BOOST_SYSTEM_LIBS"
+LDFLAGS="$LDFLAGS $BOOST_CONTEXT_LDFLAGS"
+
+# in 1.53 coroutine was a header only library
+if test $boost_major_version -eq 153; then
+ BOOST_FIND_HEADER([boost/coroutine/coroutine.hpp])
+else
+ BOOST_FIND_LIB([coroutine], [$1],
+ [boost/coroutine/coroutine.hpp],
+ [
+ #include <boost/version.hpp>
+ #if BOOST_VERSION <= 105500
+ boost::coroutines::coroutine<int(int)> coro; coro.get();
+ #else
+ boost::coroutines::asymmetric_coroutine<int>::pull_type coro; coro.get();
+ #endif
+ ])
+fi
+# Link-time dependency from coroutine to context, existed only in 1.53, in 1.54
+# coroutine doesn't use context from its headers but from its library.
+if test $boost_major_version -eq 153 || test $enable_static_boost = yes && test $boost_major_version -ge 154; then
+ BOOST_COROUTINE_LIBS="$BOOST_COROUTINE_LIBS $BOOST_CONTEXT_LIBS"
+ BOOST_COROUTINE_LDFLAGS="$BOOST_COROUTINE_LDFLAGS $BOOST_CONTEXT_LDFLAGS"
+fi
+if test $enable_static_boost = yes && test $boost_major_version -ge 155; then
+ BOOST_COROUTINE_LIBS="$BOOST_COROUTINE_LIBS $BOOST_SYSTEM_LIBS"
+ BOOST_COROUTINE_LDFLAGS="$BOOST_COROUTINE_LDFLAGS $BOOST_SYSTEM_LDFLAGS"
+fi
+LIBS=$boost_coroutine_save_LIBS
+LDFLAGS=$boost_coroutine_save_LDFLAGS
+])# BOOST_COROUTINE
+
+
+# BOOST_CRC()
+# -----------
+# Look for Boost.CRC
+BOOST_DEFUN([CRC],
+[BOOST_FIND_HEADER([boost/crc.hpp])
+])# BOOST_CRC
+
+
+# BOOST_DATE_TIME([PREFERRED-RT-OPT])
+# -----------------------------------
+# Look for Boost.Date_Time. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Date_Time],
+[BOOST_FIND_LIB([date_time], [$1],
+ [boost/date_time/posix_time/posix_time.hpp],
+ [boost::posix_time::ptime t;])
+])# BOOST_DATE_TIME
+
+
+# BOOST_FILESYSTEM([PREFERRED-RT-OPT])
+# ------------------------------------
+# Look for Boost.Filesystem. For the documentation of PREFERRED-RT-OPT, see
+# the documentation of BOOST_FIND_LIB above.
+# Do not check for boost/filesystem.hpp because this file was introduced in
+# 1.34.
+BOOST_DEFUN([Filesystem],
+[# Do we have to check for Boost.System? This link-time dependency was
+# added as of 1.35.0. If we have a version <1.35, we must not attempt to
+# find Boost.System as it didn't exist by then.
+if test $boost_major_version -ge 135; then
+ BOOST_SYSTEM([$1])
+fi # end of the Boost.System check.
+boost_filesystem_save_LIBS=$LIBS
+boost_filesystem_save_LDFLAGS=$LDFLAGS
+m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl
+LIBS="$LIBS $BOOST_SYSTEM_LIBS"
+LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS"
+BOOST_FIND_LIB([filesystem], [$1],
+ [boost/filesystem/path.hpp], [boost::filesystem::path p;])
+if test $enable_static_boost = yes && test $boost_major_version -ge 135; then
+ BOOST_FILESYSTEM_LIBS="$BOOST_FILESYSTEM_LIBS $BOOST_SYSTEM_LIBS"
+fi
+LIBS=$boost_filesystem_save_LIBS
+LDFLAGS=$boost_filesystem_save_LDFLAGS
+])# BOOST_FILESYSTEM
+
+
+# BOOST_FLYWEIGHT()
+# -----------------
+# Look for Boost.Flyweight.
+BOOST_DEFUN([Flyweight],
+[dnl There's a hidden dependency on pthreads.
+AC_REQUIRE([_BOOST_PTHREAD_FLAG])dnl
+BOOST_FIND_HEADER([boost/flyweight.hpp])
+AC_SUBST([BOOST_FLYWEIGHT_LIBS], [$boost_cv_pthread_flag])
+])
+
+
+# BOOST_FOREACH()
+# ---------------
+# Look for Boost.Foreach.
+BOOST_DEFUN([Foreach],
+[BOOST_FIND_HEADER([boost/foreach.hpp])])
+
+
+# BOOST_FORMAT()
+# --------------
+# Look for Boost.Format.
+# Note: we can't check for boost/format/format_fwd.hpp because the header isn't
+# standalone. It can't be compiled because it triggers the following error:
+# boost/format/detail/config_macros.hpp:88: error: 'locale' in namespace 'std'
+# does not name a type
+BOOST_DEFUN([Format],
+[BOOST_FIND_HEADER([boost/format.hpp])])
+
+
+# BOOST_FUNCTION()
+# ----------------
+# Look for Boost.Function
+BOOST_DEFUN([Function],
+[BOOST_FIND_HEADER([boost/function.hpp])])
+
+
+# BOOST_GEOMETRY()
+# ----------------
+# Look for Boost.Geometry (new since 1.47.0).
+BOOST_DEFUN([Geometry],
+[BOOST_FIND_HEADER([boost/geometry.hpp])
+])# BOOST_GEOMETRY
+
+
+# BOOST_GRAPH([PREFERRED-RT-OPT])
+# -------------------------------
+# Look for Boost.Graphs. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Graph],
+[boost_graph_save_LIBS=$LIBS
+boost_graph_save_LDFLAGS=$LDFLAGS
+# Link-time dependency from graph to regex was added as of 1.40.0.
+if test $boost_major_version -ge 140; then
+ BOOST_REGEX([$1])
+ m4_pattern_allow([^BOOST_REGEX_(LIBS|LDFLAGS)$])dnl
+ LIBS="$LIBS $BOOST_REGEX_LIBS"
+ LDFLAGS="$LDFLAGS $BOOST_REGEX_LDFLAGS"
+fi
+BOOST_FIND_LIB([graph], [$1],
+ [boost/graph/adjacency_list.hpp], [boost::adjacency_list<> g;])
+LIBS=$boost_graph_save_LIBS
+LDFLAGS=$boost_graph_save_LDFLAGS
+])# BOOST_GRAPH
+
+
+# BOOST_IOSTREAMS([PREFERRED-RT-OPT])
+# -----------------------------------
+# Look for Boost.IOStreams. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([IOStreams],
+[BOOST_FIND_LIB([iostreams], [$1],
+ [boost/iostreams/device/file_descriptor.hpp],
+ [boost::iostreams::file_descriptor fd; fd.close();])
+])# BOOST_IOSTREAMS
+
+
+# BOOST_HASH()
+# ------------
+# Look for Boost.Functional/Hash
+BOOST_DEFUN([Hash],
+[BOOST_FIND_HEADER([boost/functional/hash.hpp])])
+
+
+# BOOST_LAMBDA()
+# --------------
+# Look for Boost.Lambda
+BOOST_DEFUN([Lambda],
+[BOOST_FIND_HEADER([boost/lambda/lambda.hpp])])
+
+
+# BOOST_LOCALE()
+# --------------
+# Look for Boost.Locale
+BOOST_DEFUN([Locale],
+[
+boost_locale_save_LIBS=$LIBS
+boost_locale_save_LDFLAGS=$LDFLAGS
+# require SYSTEM for boost-1.50.0 and up
+if test $boost_major_version -ge 150; then
+ BOOST_SYSTEM([$1])
+ m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl
+ LIBS="$LIBS $BOOST_SYSTEM_LIBS"
+ LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS"
+fi # end of the Boost.System check.
+BOOST_FIND_LIB([locale], [$1],
+ [boost/locale.hpp],
+ [[boost::locale::generator gen; std::locale::global(gen(""));]])
+LIBS=$boost_locale_save_LIBS
+LDFLAGS=$boost_locale_save_LDFLAGS
+])# BOOST_LOCALE
+
+# BOOST_LOG([PREFERRED-RT-OPT])
+# -----------------------------
+# Look for Boost.Log. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Log],
+[boost_log_save_LIBS=$LIBS
+boost_log_save_LDFLAGS=$LDFLAGS
+BOOST_SYSTEM([$1])
+BOOST_FILESYSTEM([$1])
+BOOST_DATE_TIME([$1])
+m4_pattern_allow([^BOOST_(SYSTEM|FILESYSTEM|DATE_TIME)_(LIBS|LDFLAGS)$])dnl
+LIBS="$LIBS $BOOST_DATE_TIME_LIBS $BOOST_FILESYSTEM_LIBS $BOOST_SYSTEM_LIBS"
+LDFLAGS="$LDFLAGS $BOOST_DATE_TIME_LDFLAGS $BOOST_FILESYSTEM_LDFLAGS $BOOST_SYSTEM_LDFLAGS"
+BOOST_FIND_LIB([log], [$1],
+ [boost/log/core/core.hpp],
+ [boost::log::attribute a; a.get_value();])
+LIBS=$boost_log_save_LIBS
+LDFLAGS=$boost_log_save_LDFLAGS
+])# BOOST_LOG
+
+
+# BOOST_LOG_SETUP([PREFERRED-RT-OPT])
+# -----------------------------------
+# Look for Boost.Log. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Log_Setup],
+[boost_log_setup_save_LIBS=$LIBS
+boost_log_setup_save_LDFLAGS=$LDFLAGS
+BOOST_LOG([$1])
+m4_pattern_allow([^BOOST_LOG_(LIBS|LDFLAGS)$])dnl
+LIBS="$LIBS $BOOST_LOG_LIBS"
+LDFLAGS="$LDFLAGS $BOOST_LOG_LDFLAGS"
+BOOST_FIND_LIB([log_setup], [$1],
+ [boost/log/utility/setup/from_settings.hpp],
+ [boost::log::basic_settings<char> bs; bs.empty();])
+LIBS=$boost_log_setup_save_LIBS
+LDFLAGS=$boost_log_setup_save_LDFLAGS
+])# BOOST_LOG_SETUP
+
+
+# BOOST_MATH()
+# ------------
+# Look for Boost.Math
+# TODO: This library isn't header-only but it comes in multiple different
+# flavors that don't play well with BOOST_FIND_LIB (e.g, libboost_math_c99,
+# libboost_math_c99f, libboost_math_c99l, libboost_math_tr1,
+# libboost_math_tr1f, libboost_math_tr1l). This macro must be fixed to do the
+# right thing anyway.
+BOOST_DEFUN([Math],
+[BOOST_FIND_HEADER([boost/math/special_functions.hpp])])
+
+
+# BOOST_MPI([PREFERRED-RT-OPT])
+# -------------------------------
+# Look for Boost MPI. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above. Uses MPICXX variable if it is
+# set, otherwise tries CXX
+#
+BOOST_DEFUN([MPI],
+[boost_save_CXX=${CXX}
+boost_save_CXXCPP=${CXXCPP}
+if test x"${MPICXX}" != x; then
+ CXX=${MPICXX}
+ CXXCPP="${MPICXX} -E"
+fi
+BOOST_FIND_LIB([mpi], [$1],
+ [boost/mpi.hpp],
+ [int argc = 0;
+ char **argv = 0;
+ boost::mpi::environment env(argc,argv);])
+CXX=${boost_save_CXX}
+CXXCPP=${boost_save_CXXCPP}
+])# BOOST_MPI
+
+
+# BOOST_MULTIARRAY()
+# ------------------
+# Look for Boost.MultiArray
+BOOST_DEFUN([MultiArray],
+[BOOST_FIND_HEADER([boost/multi_array.hpp])])
+
+
+# BOOST_NUMERIC_UBLAS()
+# --------------------------
+# Look for Boost.NumericUblas (Basic Linear Algebra)
+BOOST_DEFUN([Numeric_Ublas],
+[BOOST_FIND_HEADER([boost/numeric/ublas/vector.hpp])
+])# BOOST_NUMERIC_UBLAS
+
+
+# BOOST_NUMERIC_CONVERSION()
+# --------------------------
+# Look for Boost.NumericConversion (policy-based numeric conversion)
+BOOST_DEFUN([Numeric_Conversion],
+[BOOST_FIND_HEADER([boost/numeric/conversion/converter.hpp])
+])# BOOST_NUMERIC_CONVERSION
+
+
+# BOOST_OPTIONAL()
+# ----------------
+# Look for Boost.Optional
+BOOST_DEFUN([Optional],
+[BOOST_FIND_HEADER([boost/optional.hpp])])
+
+
+# BOOST_PREPROCESSOR()
+# --------------------
+# Look for Boost.Preprocessor
+BOOST_DEFUN([Preprocessor],
+[BOOST_FIND_HEADER([boost/preprocessor/repeat.hpp])])
+
+
+# BOOST_RANGE()
+# --------------------
+# Look for Boost.Range
+BOOST_DEFUN([Range],
+[BOOST_FIND_HEADER([boost/range/adaptors.hpp])])
+
+# BOOST_UNORDERED()
+# -----------------
+# Look for Boost.Unordered
+BOOST_DEFUN([Unordered],
+[BOOST_FIND_HEADER([boost/unordered_map.hpp])])
+
+
+# BOOST_UUID()
+# ------------
+# Look for Boost.Uuid
+BOOST_DEFUN([Uuid],
+[BOOST_FIND_HEADER([boost/uuid/uuid.hpp])])
+
+
+# BOOST_PROGRAM_OPTIONS([PREFERRED-RT-OPT])
+# -----------------------------------------
+# Look for Boost.Program_options. For the documentation of PREFERRED-RT-OPT,
+# see the documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Program_Options],
+[BOOST_FIND_LIB([program_options], [$1],
+ [boost/program_options.hpp],
+ [boost::program_options::options_description d("test");])
+])# BOOST_PROGRAM_OPTIONS
+
+
+
+# _BOOST_PYTHON_CONFIG(VARIABLE, FLAG)
+# ------------------------------------
+# Save VARIABLE, and define it via `python-config --FLAG`.
+# Substitute BOOST_PYTHON_VARIABLE.
+m4_define([_BOOST_PYTHON_CONFIG],
+[AC_SUBST([BOOST_PYTHON_$1],
+ [`python-config --$2 2>/dev/null`])dnl
+boost_python_save_$1=$$1
+$1="$$1 $BOOST_PYTHON_$1"])
+
+
+# BOOST_PYTHON([PREFERRED-RT-OPT])
+# --------------------------------
+# Look for Boost.Python. For the documentation of PREFERRED-RT-OPT,
+# see the documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Python],
+[_BOOST_PYTHON_CONFIG([CPPFLAGS], [includes])
+_BOOST_PYTHON_CONFIG([LDFLAGS], [ldflags])
+_BOOST_PYTHON_CONFIG([LIBS], [libs])
+m4_pattern_allow([^BOOST_PYTHON_MODULE$])dnl
+BOOST_FIND_LIBS([python], [python python3], [$1],
+ [boost/python.hpp],
+ [], [BOOST_PYTHON_MODULE(empty) {}])
+CPPFLAGS=$boost_python_save_CPPFLAGS
+LDFLAGS=$boost_python_save_LDFLAGS
+LIBS=$boost_python_save_LIBS
+])# BOOST_PYTHON
+
+
+# BOOST_REF()
+# -----------
+# Look for Boost.Ref
+BOOST_DEFUN([Ref],
+[BOOST_FIND_HEADER([boost/ref.hpp])])
+
+
+# BOOST_REGEX([PREFERRED-RT-OPT])
+# -------------------------------
+# Look for Boost.Regex. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Regex],
+[BOOST_FIND_LIB([regex], [$1],
+ [boost/regex.hpp],
+ [boost::regex exp("*"); boost::regex_match("foo", exp);])
+])# BOOST_REGEX
+
+
+# BOOST_SERIALIZATION([PREFERRED-RT-OPT])
+# ---------------------------------------
+# Look for Boost.Serialization. For the documentation of PREFERRED-RT-OPT, see
+# the documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Serialization],
+[BOOST_FIND_LIB([serialization], [$1],
+ [boost/archive/text_oarchive.hpp],
+ [std::ostream* o = 0; // Cheap way to get an ostream...
+ boost::archive::text_oarchive t(*o);])
+])# BOOST_SERIALIZATION
+
+
+# BOOST_SIGNALS([PREFERRED-RT-OPT])
+# ---------------------------------
+# Look for Boost.Signals. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Signals],
+[BOOST_FIND_LIB([signals], [$1],
+ [boost/signal.hpp],
+ [boost::signal<void ()> s;])
+])# BOOST_SIGNALS
+
+
+# BOOST_SIGNALS2()
+# ----------------
+# Look for Boost.Signals2 (new since 1.39.0).
+BOOST_DEFUN([Signals2],
+[BOOST_FIND_HEADER([boost/signals2.hpp])
+])# BOOST_SIGNALS2
+
+
+# BOOST_SMART_PTR()
+# -----------------
+# Look for Boost.SmartPtr
+BOOST_DEFUN([Smart_Ptr],
+[BOOST_FIND_HEADER([boost/scoped_ptr.hpp])
+BOOST_FIND_HEADER([boost/shared_ptr.hpp])
+])
+
+
+# BOOST_STATICASSERT()
+# --------------------
+# Look for Boost.StaticAssert
+BOOST_DEFUN([StaticAssert],
+[BOOST_FIND_HEADER([boost/static_assert.hpp])])
+
+
+# BOOST_STRING_ALGO()
+# -------------------
+# Look for Boost.StringAlgo
+BOOST_DEFUN([String_Algo],
+[BOOST_FIND_HEADER([boost/algorithm/string.hpp])
+])
+
+
+# BOOST_SYSTEM([PREFERRED-RT-OPT])
+# --------------------------------
+# Look for Boost.System. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above. This library was introduced in Boost
+# 1.35.0.
+BOOST_DEFUN([System],
+[BOOST_FIND_LIB([system], [$1],
+ [boost/system/error_code.hpp],
+ [boost::system::error_code e; e.clear();])
+])# BOOST_SYSTEM
+
+
+# BOOST_TEST([PREFERRED-RT-OPT])
+# ------------------------------
+# Look for Boost.Test. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Test],
+[m4_pattern_allow([^BOOST_CHECK$])dnl
+BOOST_FIND_LIB([unit_test_framework], [$1],
+ [boost/test/unit_test.hpp], [BOOST_CHECK(2 == 2);],
+ [using boost::unit_test::test_suite;
+ test_suite* init_unit_test_suite(int argc, char ** argv)
+ { return NULL; }])
+])# BOOST_TEST
+
+
+# BOOST_THREAD([PREFERRED-RT-OPT])
+# ---------------------------------
+# Look for Boost.Thread. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Thread],
+[dnl Having the pthread flag is required at least on GCC3 where
+dnl boost/thread.hpp would complain if we try to compile without
+dnl -pthread on GNU/Linux.
+AC_REQUIRE([_BOOST_PTHREAD_FLAG])dnl
+boost_thread_save_LIBS=$LIBS
+boost_thread_save_LDFLAGS=$LDFLAGS
+boost_thread_save_CPPFLAGS=$CPPFLAGS
+# Link-time dependency from thread to system was added as of 1.49.0.
+if test $boost_major_version -ge 149; then
+BOOST_SYSTEM([$1])
+fi # end of the Boost.System check.
+m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl
+LIBS="$LIBS $BOOST_SYSTEM_LIBS $boost_cv_pthread_flag"
+LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS"
+CPPFLAGS="$CPPFLAGS $boost_cv_pthread_flag"
+
+# When compiling for the Windows platform, the threads library is named
+# differently. This suffix doesn't exist in new versions of Boost, or
+# possibly new versions of GCC on mingw I am assuming it's Boost's change for
+# now and I am setting version to 1.48, for lack of knowledge as to when this
+# change occurred.
+if test $boost_major_version -lt 148; then
+ case $host_os in
+ (*mingw*) boost_thread_lib_ext=_win32;;
+ esac
+fi
+BOOST_FIND_LIBS([thread], [thread$boost_thread_lib_ext],
+ [$1],
+ [boost/thread.hpp], [boost::thread t; boost::mutex m;])
+
+case $host_os in
+ (*mingw*) boost_thread_w32_socket_link=-lws2_32;;
+esac
+
+BOOST_THREAD_LIBS="$BOOST_THREAD_LIBS $BOOST_SYSTEM_LIBS $boost_cv_pthread_flag $boost_thread_w32_socket_link"
+BOOST_THREAD_LDFLAGS="$BOOST_SYSTEM_LDFLAGS"
+BOOST_CPPFLAGS="$BOOST_CPPFLAGS $boost_cv_pthread_flag"
+LIBS=$boost_thread_save_LIBS
+LDFLAGS=$boost_thread_save_LDFLAGS
+CPPFLAGS=$boost_thread_save_CPPFLAGS
+])# BOOST_THREAD
+
+AU_ALIAS([BOOST_THREADS], [BOOST_THREAD])
+
+
+# BOOST_TOKENIZER()
+# -----------------
+# Look for Boost.Tokenizer
+BOOST_DEFUN([Tokenizer],
+[BOOST_FIND_HEADER([boost/tokenizer.hpp])])
+
+
+# BOOST_TRIBOOL()
+# ---------------
+# Look for Boost.Tribool
+BOOST_DEFUN([Tribool],
+[BOOST_FIND_HEADER([boost/logic/tribool_fwd.hpp])
+BOOST_FIND_HEADER([boost/logic/tribool.hpp])
+])
+
+
+# BOOST_TUPLE()
+# -------------
+# Look for Boost.Tuple
+BOOST_DEFUN([Tuple],
+[BOOST_FIND_HEADER([boost/tuple/tuple.hpp])])
+
+
+# BOOST_TYPETRAITS()
+# --------------------
+# Look for Boost.TypeTraits
+BOOST_DEFUN([TypeTraits],
+[BOOST_FIND_HEADER([boost/type_traits.hpp])])
+
+
+# BOOST_UTILITY()
+# ---------------
+# Look for Boost.Utility (noncopyable, result_of, base-from-member idiom,
+# etc.)
+BOOST_DEFUN([Utility],
+[BOOST_FIND_HEADER([boost/utility.hpp])])
+
+
+# BOOST_VARIANT()
+# ---------------
+# Look for Boost.Variant.
+BOOST_DEFUN([Variant],
+[BOOST_FIND_HEADER([boost/variant/variant_fwd.hpp])
+BOOST_FIND_HEADER([boost/variant.hpp])])
+
+
+# BOOST_POINTER_CONTAINER()
+# ------------------------
+# Look for Boost.PointerContainer
+BOOST_DEFUN([Pointer_Container],
+[BOOST_FIND_HEADER([boost/ptr_container/ptr_deque.hpp])
+BOOST_FIND_HEADER([boost/ptr_container/ptr_list.hpp])
+BOOST_FIND_HEADER([boost/ptr_container/ptr_vector.hpp])
+BOOST_FIND_HEADER([boost/ptr_container/ptr_array.hpp])
+BOOST_FIND_HEADER([boost/ptr_container/ptr_set.hpp])
+BOOST_FIND_HEADER([boost/ptr_container/ptr_map.hpp])
+])# BOOST_POINTER_CONTAINER
+
+
+# BOOST_WAVE([PREFERRED-RT-OPT])
+# ------------------------------
+# NOTE: If you intend to use Wave/Spirit with thread support, make sure you
+# call BOOST_THREAD first.
+# Look for Boost.Wave. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Wave],
+[AC_REQUIRE([BOOST_FILESYSTEM])dnl
+AC_REQUIRE([BOOST_DATE_TIME])dnl
+boost_wave_save_LIBS=$LIBS
+boost_wave_save_LDFLAGS=$LDFLAGS
+m4_pattern_allow([^BOOST_((FILE)?SYSTEM|DATE_TIME|THREAD)_(LIBS|LDFLAGS)$])dnl
+LIBS="$LIBS $BOOST_SYSTEM_LIBS $BOOST_FILESYSTEM_LIBS $BOOST_DATE_TIME_LIBS \
+$BOOST_THREAD_LIBS"
+LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS $BOOST_FILESYSTEM_LDFLAGS \
+$BOOST_DATE_TIME_LDFLAGS $BOOST_THREAD_LDFLAGS"
+BOOST_FIND_LIB([wave], [$1],
+ [boost/wave.hpp],
+ [boost::wave::token_id id; get_token_name(id);])
+LIBS=$boost_wave_save_LIBS
+LDFLAGS=$boost_wave_save_LDFLAGS
+])# BOOST_WAVE
+
+
+# BOOST_XPRESSIVE()
+# -----------------
+# Look for Boost.Xpressive (new since 1.36.0).
+BOOST_DEFUN([Xpressive],
+[BOOST_FIND_HEADER([boost/xpressive/xpressive.hpp])])
+
+
+# ----------------- #
+# Internal helpers. #
+# ----------------- #
+
+
+# _BOOST_PTHREAD_FLAG()
+# ---------------------
+# Internal helper for BOOST_THREAD. Computes boost_cv_pthread_flag
+# which must be used in CPPFLAGS and LIBS.
+#
+# Yes, we *need* to put the -pthread thing in CPPFLAGS because with GCC3,
+# boost/thread.hpp will trigger a #error if -pthread isn't used:
+# boost/config/requires_threads.hpp:47:5: #error "Compiler threading support
+# is not turned on. Please set the correct command line options for
+# threading: -pthread (Linux), -pthreads (Solaris) or -mthreads (Mingw32)"
+#
+# Based on ACX_PTHREAD: http://autoconf-archive.cryp.to/acx_pthread.html
+AC_DEFUN([_BOOST_PTHREAD_FLAG],
+[AC_REQUIRE([AC_PROG_CXX])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_LANG_PUSH([C++])dnl
+AC_CACHE_CHECK([for the flags needed to use pthreads], [boost_cv_pthread_flag],
+[ boost_cv_pthread_flag=
+ # The ordering *is* (sometimes) important. Some notes on the
+ # individual items follow:
+ # (none): in case threads are in libc; should be tried before -Kthread and
+ # other compiler flags to prevent continual compiler warnings
+ # -lpthreads: AIX (must check this before -lpthread)
+ # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+ # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+ # -llthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+ # -pthread: GNU Linux/GCC (kernel threads), BSD/GCC (userland threads)
+ # -pthreads: Solaris/GCC
+ # -mthreads: MinGW32/GCC, Lynx/GCC
+ # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+ # doesn't hurt to check since this sometimes defines pthreads too;
+ # also defines -D_REENTRANT)
+ # ... -mt is also the pthreads flag for HP/aCC
+ # -lpthread: GNU Linux, etc.
+ # --thread-safe: KAI C++
+ case $host_os in #(
+ *solaris*)
+ # On Solaris (at least, for some versions), libc contains stubbed
+ # (non-functional) versions of the pthreads routines, so link-based
+ # tests will erroneously succeed. (We need to link with -pthreads/-mt/
+ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
+ # a function called by this macro, so we could check for that, but
+ # who knows whether they'll stub that too in a future libc.) So,
+ # we'll just look for -pthreads and -lpthread first:
+ boost_pthread_flags="-pthreads -lpthread -mt -pthread";; #(
+ *)
+ boost_pthread_flags="-lpthreads -Kthread -kthread -llthread -pthread \
+ -pthreads -mthreads -lpthread --thread-safe -mt";;
+ esac
+ # Generate the test file.
+ AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include <pthread.h>],
+ [pthread_t th; pthread_join(th, 0);
+ pthread_attr_init(0); pthread_cleanup_push(0, 0);
+ pthread_create(0,0,0,0); pthread_cleanup_pop(0);])])
+ for boost_pthread_flag in '' $boost_pthread_flags; do
+ boost_pthread_ok=false
+dnl Re-use the test file already generated.
+ boost_pthreads__save_LIBS=$LIBS
+ LIBS="$LIBS $boost_pthread_flag"
+ AC_LINK_IFELSE([],
+ [if grep ".*$boost_pthread_flag" conftest.err; then
+ echo "This flag seems to have triggered warnings" >&AS_MESSAGE_LOG_FD
+ else
+ boost_pthread_ok=:; boost_cv_pthread_flag=$boost_pthread_flag
+ fi])
+ LIBS=$boost_pthreads__save_LIBS
+ $boost_pthread_ok && break
+ done
+])
+AC_LANG_POP([C++])dnl
+])# _BOOST_PTHREAD_FLAG
+
+
+# _BOOST_gcc_test(MAJOR, MINOR)
+# -----------------------------
+# Internal helper for _BOOST_FIND_COMPILER_TAG.
+m4_define([_BOOST_gcc_test],
+["defined __GNUC__ && __GNUC__ == $1 && __GNUC_MINOR__ == $2 && !defined __ICC @ gcc$1$2"])dnl
+
+# _BOOST_mingw_test(MAJOR, MINOR)
+# -----------------------------
+# Internal helper for _BOOST_FIND_COMPILER_TAG.
+m4_define([_BOOST_mingw_test],
+["defined __GNUC__ && __GNUC__ == $1 && __GNUC_MINOR__ == $2 && !defined __ICC && \
+ (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \
+ || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw$1$2"])dnl
+
+
+# _BOOST_FIND_COMPILER_TAG()
+# --------------------------
+# Internal. When Boost is installed without --layout=system, each library
+# filename will hold a suffix that encodes the compiler used during the
+# build. The Boost build system seems to call this a `tag'.
+AC_DEFUN([_BOOST_FIND_COMPILER_TAG],
+[AC_REQUIRE([AC_PROG_CXX])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_CACHE_CHECK([for the toolset name used by Boost for $CXX],
+ [boost_cv_lib_tag],
+[boost_cv_lib_tag=unknown
+if test x$boost_cv_inc_path != xno; then
+ AC_LANG_PUSH([C++])dnl
+ # The following tests are mostly inspired by boost/config/auto_link.hpp
+ # The list is sorted to most recent/common to oldest compiler (in order
+ # to increase the likelihood of finding the right compiler with the
+ # least number of compilation attempt).
+ # Beware that some tests are sensible to the order (for instance, we must
+ # look for MinGW before looking for GCC3).
+ # I used one compilation test per compiler with a #error to recognize
+ # each compiler so that it works even when cross-compiling (let me know
+ # if you know a better approach).
+ # Known missing tags (known from Boost's tools/build/v2/tools/common.jam):
+ # como, edg, kcc, bck, mp, sw, tru, xlc
+ # I'm not sure about my test for `il' (be careful: Intel's ICC pre-defines
+ # the same defines as GCC's).
+ for i in \
+ _BOOST_mingw_test(6, 2) \
+ _BOOST_gcc_test(6, 2) \
+ _BOOST_mingw_test(6, 1) \
+ _BOOST_gcc_test(6, 1) \
+ _BOOST_mingw_test(6, 0) \
+ _BOOST_gcc_test(6, 0) \
+ _BOOST_mingw_test(5, 3) \
+ _BOOST_gcc_test(5, 3) \
+ _BOOST_mingw_test(5, 2) \
+ _BOOST_gcc_test(5, 2) \
+ _BOOST_mingw_test(5, 1) \
+ _BOOST_gcc_test(5, 1) \
+ _BOOST_mingw_test(5, 0) \
+ _BOOST_gcc_test(5, 0) \
+ _BOOST_mingw_test(4, 10) \
+ _BOOST_gcc_test(4, 10) \
+ _BOOST_mingw_test(4, 9) \
+ _BOOST_gcc_test(4, 9) \
+ _BOOST_mingw_test(4, 8) \
+ _BOOST_gcc_test(4, 8) \
+ _BOOST_mingw_test(4, 7) \
+ _BOOST_gcc_test(4, 7) \
+ _BOOST_mingw_test(4, 6) \
+ _BOOST_gcc_test(4, 6) \
+ _BOOST_mingw_test(4, 5) \
+ _BOOST_gcc_test(4, 5) \
+ _BOOST_mingw_test(4, 4) \
+ _BOOST_gcc_test(4, 4) \
+ _BOOST_mingw_test(4, 3) \
+ _BOOST_gcc_test(4, 3) \
+ _BOOST_mingw_test(4, 2) \
+ _BOOST_gcc_test(4, 2) \
+ _BOOST_mingw_test(4, 1) \
+ _BOOST_gcc_test(4, 1) \
+ _BOOST_mingw_test(4, 0) \
+ _BOOST_gcc_test(4, 0) \
+ "defined __GNUC__ && __GNUC__ == 3 && !defined __ICC \
+ && (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \
+ || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw" \
+ _BOOST_gcc_test(3, 4) \
+ _BOOST_gcc_test(3, 3) \
+ "defined _MSC_VER && _MSC_VER >= 1500 @ vc90" \
+ "defined _MSC_VER && _MSC_VER == 1400 @ vc80" \
+ _BOOST_gcc_test(3, 2) \
+ "defined _MSC_VER && _MSC_VER == 1310 @ vc71" \
+ _BOOST_gcc_test(3, 1) \
+ _BOOST_gcc_test(3, 0) \
+ "defined __BORLANDC__ @ bcb" \
+ "defined __ICC && (defined __unix || defined __unix__) @ il" \
+ "defined __ICL @ iw" \
+ "defined _MSC_VER && _MSC_VER == 1300 @ vc7" \
+ _BOOST_gcc_test(2, 95) \
+ "defined __MWERKS__ && __MWERKS__ <= 0x32FF @ cw9" \
+ "defined _MSC_VER && _MSC_VER < 1300 && !defined UNDER_CE @ vc6" \
+ "defined _MSC_VER && _MSC_VER < 1300 && defined UNDER_CE @ evc4" \
+ "defined __MWERKS__ && __MWERKS__ <= 0x31FF @ cw8"
+ do
+ boost_tag_test=`expr "X$i" : 'X\([[^@]]*\) @ '`
+ boost_tag=`expr "X$i" : 'X[[^@]]* @ \(.*\)'`
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#if $boost_tag_test
+/* OK */
+#else
+# error $boost_tag_test
+#endif
+]])], [boost_cv_lib_tag=$boost_tag; break], [])
+ done
+AC_LANG_POP([C++])dnl
+ case $boost_cv_lib_tag in #(
+ # Some newer (>= 1.35?) versions of Boost seem to only use "gcc" as opposed
+ # to "gcc41" for instance.
+ *-gcc | *'-gcc ') :;; #( Don't re-add -gcc: it's already in there.
+ gcc*)
+ boost_tag_x=
+ case $host_os in #(
+ darwin*)
+ if test $boost_major_version -ge 136; then
+ # The `x' added in r46793 of Boost.
+ boost_tag_x=x
+ fi;;
+ esac
+ # We can specify multiple tags in this variable because it's used by
+ # BOOST_FIND_LIB that does a `for tag in -$boost_cv_lib_tag' ...
+ boost_cv_lib_tag="$boost_tag_x$boost_cv_lib_tag -${boost_tag_x}gcc"
+ ;; #(
+ unknown)
+ AC_MSG_WARN([[could not figure out which toolset name to use for $CXX]])
+ boost_cv_lib_tag=
+ ;;
+ esac
+fi])dnl end of AC_CACHE_CHECK
+])# _BOOST_FIND_COMPILER_TAG
+
+
+# _BOOST_GUESS_WHETHER_TO_USE_MT()
+# --------------------------------
+# Compile a small test to try to guess whether we should favor MT (Multi
+# Thread) flavors of Boost. Sets boost_guess_use_mt accordingly.
+AC_DEFUN([_BOOST_GUESS_WHETHER_TO_USE_MT],
+[# Check whether we do better use `mt' even though we weren't ask to.
+AC_LANG_PUSH([C++])dnl
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#if defined _REENTRANT || defined _MT || defined __MT__
+/* use -mt */
+#else
+# error MT not needed
+#endif
+]])], [boost_guess_use_mt=:], [boost_guess_use_mt=false])
+AC_LANG_POP([C++])dnl
+])
+
+# _BOOST_AC_LINK_IFELSE(PROGRAM, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
+# -------------------------------------------------------------------
+# Fork of _AC_LINK_IFELSE that preserves conftest.o across calls. Fragile,
+# will break when Autoconf changes its internals. Requires that you manually
+# rm -f conftest.$ac_objext in between to really different tests, otherwise
+# you will try to link a conftest.o left behind by a previous test.
+# Used to aggressively optimize BOOST_FIND_LIB (see the big comment in this
+# macro).
+#
+# Don't use "break" in the actions, as it would short-circuit some code
+# this macro runs after the actions.
+m4_define([_BOOST_AC_LINK_IFELSE],
+[m4_ifvaln([$1], [AC_LANG_CONFTEST([$1])])dnl
+rm -f conftest$ac_exeext
+boost_save_ac_ext=$ac_ext
+boost_use_source=:
+# If we already have a .o, re-use it. We change $ac_ext so that $ac_link
+# tries to link the existing object file instead of compiling from source.
+test -f conftest.$ac_objext && ac_ext=$ac_objext && boost_use_source=false &&
+ _AS_ECHO_LOG([re-using the existing conftest.$ac_objext])
+AS_IF([_AC_DO_STDERR($ac_link) && {
+ test -z "$ac_[]_AC_LANG_ABBREV[]_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ $as_executable_p conftest$ac_exeext
+dnl FIXME: use AS_TEST_X instead when 2.61 is widespread enough.
+ }],
+ [$2],
+ [if $boost_use_source; then
+ _AC_MSG_LOG_CONFTEST
+ fi
+ $3])
+ac_objext=$boost_save_ac_objext
+ac_ext=$boost_save_ac_ext
+dnl Delete also the IPA/IPO (Inter Procedural Analysis/Optimization)
+dnl information created by the PGI compiler (conftest_ipa8_conftest.oo),
+dnl as it would interfere with the next link command.
+rm -f core conftest.err conftest_ipa8_conftest.oo \
+ conftest$ac_exeext m4_ifval([$1], [conftest.$ac_ext])[]dnl
+])# _BOOST_AC_LINK_IFELSE
+
+# Local Variables:
+# mode: autoconf
+# End:
diff --git a/pkg-desc/pkg-description.txt b/pkg-desc/pkg-description.txt
new file mode 100644
index 0000000..8a9708d
--- /dev/null
+++ b/pkg-desc/pkg-description.txt
@@ -0,0 +1,16 @@
+Usage
+
+=numbertext(5) -> "five"
+=numbertext(5;"de") -> "fünf"
+=moneytext(5;"USD") -> "five dollars"
+=moneytext(5;"HUF";"hu") -> "öt forint"
+
+Help for extra functions and modules of the default language:
+
+=numbertext("help")
+
+Examples for using extra functions:
+
+=moneytext(1; "ord"; "en") (English ordinal numbers) -> "first"
+
+=moneytext(999; "ord2"; "en") (English ordinal abbreviations) -> "1st"
diff --git a/pythonpath/Makefile b/pythonpath/Makefile
new file mode 100644
index 0000000..3fab145
--- /dev/null
+++ b/pythonpath/Makefile
@@ -0,0 +1,22 @@
+# convert all ../data/*.sor files to name_*.py Python modules
+BIN=../bin
+
+all: org/Numbertext/Soros.py org/Numbertext/places.py org/Numbertext/locales.py \
+ $(addprefix numbertext_, $(addsuffix .py, $(basename $(notdir $(wildcard ../data/*.sor)))))
+
+org/Numbertext/Soros.py: ../src/Soros.py
+ cp ../src/Soros.py org/Numbertext/
+
+org/Numbertext/places.py: ../src/places.py
+ cp ../src/places.py org/Numbertext/
+
+#org/Numbertext/%.py: ../data/%.sor $(BIN)/Convert.py
+numbertext_%.py: ../data/%.sor $(BIN)/Convert.py
+ python $(BIN)/Convert.py $< >$@
+
+org/Numbertext/locales.py: $(addprefix numbertext_, $(addsuffix .py, $(basename $(notdir $(wildcard ../data/*.sor)))))
+ python $(BIN)/locales.py $(basename $(notdir $(wildcard ../data/*.sor))) $(shell cat ../data/*.sor | grep -Eo '\[:.....:]' | tr '-' '_' | tr -d '[]:' | sort | uniq) >org/Numbertext/locales.py
+
+clean:
+ rm -f $(addprefix numbertext_, $(addsuffix .py, $(basename $(notdir $(wildcard ../data/*.sor)))))
+ rm -f org/Numbertext/places.py* org/Numbertext/locales.py* org/Numbertext/Soros.py*
diff --git a/pythonpath/org/Numbertext/__init__.py b/pythonpath/org/Numbertext/__init__.py
new file mode 100644
index 0000000..6360efe
--- /dev/null
+++ b/pythonpath/org/Numbertext/__init__.py
@@ -0,0 +1,129 @@
+import uno
+import unohelper
+import re
+
+from org.numbertext import XNumberText
+from com.sun.star.lang import Locale
+
+from org.Numbertext import Soros
+from org.Numbertext.locales import locales
+from org.Numbertext.places import places
+
+# constant
+MINUS = "[-\u2212]" # ASCII hyphen/minus or Unicode minus sign
+
+langname = {}
+# loaded patterns
+patterns = {}
+
+
+class NUMBERTEXT( unohelper.Base, XNumberText):
+
+ def __init__(self, ctx):
+ sLocaleData = "com.sun.star.i18n.LocaleData"
+ self.LocaleData = ctx.ServiceManager.createInstance(sLocaleData)
+ sProvider = "com.sun.star.configuration.ConfigurationProvider"
+ sAccess = "com.sun.star.configuration.ConfigurationAccess"
+ aConfigProvider = ctx.ServiceManager.createInstance(sProvider)
+ prop = uno.createUnoStruct('com.sun.star.beans.PropertyValue')
+ prop.Name = "nodepath"
+ prop.Value = "/org.openoffice.Setup/L10N"
+ self.aSettings = aConfigProvider.createInstanceWithArguments(sAccess,(prop,))
+ self.uilocale = self.aSettings.getByName("ooLocale")
+ self.locale = Locale("en", "US", "")
+ self.func = ctx.ServiceManager.createInstance('com.sun.star.sheet.FunctionAccess')
+ for i in locales:
+ langname[i.split("_")[0]] = i
+
+ def queryLocale(self, prop, loc):
+ if loc != None:
+ a = loc.split("-")
+ if len(a) == 1:
+ return Locale(a[0], "", "")
+ if len(a) == 2:
+ return Locale(a[0], a[1], "")
+ else:
+ return Locale(a[0], a[1], a[2])
+ locale = prop.getPropertyValue("CharLocale")
+ if locale != None and locale.Language != "zxx":
+ return locale
+ return Locale("en", "US", "")
+
+ # set module name for importing locale data
+ def getModule(self, Language, Country, Variant):
+ global patterns
+ if Country == "":
+ module = Language
+ if Variant == "":
+ module = Language + "_" + Country
+ else:
+ module = Language + "_" + Country + "_" + Variant
+ if not module in locales:
+ module = Language + "_" + Country
+ if not module in locales:
+ module = Language
+ if not module in locales:
+ try:
+ module = langname[Language]
+ except:
+ module = "en_US"
+ if not module in patterns:
+ try:
+ d = __import__("numbertext_" + module)
+ except:
+ try:
+ d = __import__("numbertext_" + Language)
+ except:
+ return "Error: missing language data (" + module + ")"
+ patterns[module] = Soros.compile(d.__doc__, module.replace("_", "-"))
+ return module
+
+ def getCurrency(self, locale):
+ allcurr = self.LocaleData.getAllCurrencies(locale)
+ if allcurr != None:
+ struct = uno.createUnoStruct("com.sun.star.i18n.Currency")
+ for struct in allcurr:
+ if struct.Default:
+ return struct
+ return None
+
+ # XNumberText method implementations
+ def moneytext(self, prop, num, curr, loc):
+ global patterns
+ num = num.strip()
+ # query document language
+ locale = self.queryLocale(prop, loc)
+ mod = self.getModule(locale.Language, locale.Country, locale.Variant)
+ decimalplaces = 2;
+ if curr == None:
+ currency = self.getCurrency(locale)
+ decimalplaces = currency.DecimalPlaces
+ outcurr = currency.ID + " "
+ else:
+ outcurr = curr + " "
+ if curr in places:
+ decimalplaces = places[curr]
+ if num.rfind(".") > -1 or num.rfind(",") > -1:
+ num = float(num.replace(",","."))
+ if (type(decimalplaces) == type(0.1)):
+ pl = 10**decimalplaces;
+ num = str(round(num * pl) / pl)
+ else:
+ num = str(self.func.callFunction("round", (num, decimalplaces)))
+ return get_numbertext(outcurr + num, patterns[mod])
+
+ def numbertext(self, prop, num, loc):
+ global patterns
+ # query document language
+ loc = self.queryLocale(prop, loc)
+ mod = self.getModule(loc.Language, loc.Country, loc.Variant)
+ return get_numbertext(num.strip(), patterns[mod])
+
+def get_numbertext(num, conv):
+ try:
+ n = conv.run(num)
+ except:
+ return "Conversion error"
+ if n == "":
+ return num
+ return n
diff --git a/pythonpath/org/__init__.py b/pythonpath/org/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/pythonpath/org/__init__.py
diff --git a/rdb/sample.rdb b/rdb/sample.rdb
new file mode 100644
index 0000000..d1b87aa
--- /dev/null
+++ b/rdb/sample.rdb
Binary files differ
diff --git a/reg.uno.py b/reg.uno.py
new file mode 100644
index 0000000..dfaff9f
--- /dev/null
+++ b/reg.uno.py
@@ -0,0 +1,14 @@
+import uno
+import unohelper
+
+def createInstance( ctx ):
+ # NumberText uses a new type, importing it at the top of this file
+ # leads to a failure during adding the extension to OOo
+ import org.Numbertext
+ return org.Numbertext.NUMBERTEXT( ctx )
+
+# pythonloader looks for a static g_ImplementationHelper variable
+g_ImplementationHelper = unohelper.ImplementationHelper()
+g_ImplementationHelper.addImplementation( \
+ createInstance,"org.numbertext",
+ ("com.sun.star.sheet.AddIn",),)
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..b6af6ca
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,20 @@
+AM_CXXFLAGS = -D_THREAD_SAFE -D_GNU_SOURCE -DVERBOSE
+
+LIBS += $(BOOST_REGEX_LIBS)
+
+libnumbertext_1_0_includedir = $(includedir)/libnumbertext
+libnumbertext_1_0_include_HEADERS = \
+ Soros.hxx Numbertext.hxx \
+ $(builddir)/numbertext-version.h
+
+lib_LTLIBRARIES = libnumbertext-1.0.la
+libnumbertext_1_0_la_SOURCES = \
+ Soros.cxx Numbertext.cxx
+libnumbertext_1_0_la_LDFLAGS = -no-undefined
+
+bin_PROGRAMS = spellout
+spellout_SOURCES = spellout.cxx
+spellout_LDADD = libnumbertext-1.0.la
+
+EXTRA_DIST = numbertext-version.h \
+ numbertext-version.h.in
diff --git a/src/Numbertext.cxx b/src/Numbertext.cxx
new file mode 100644
index 0000000..e500c26
--- /dev/null
+++ b/src/Numbertext.cxx
@@ -0,0 +1,110 @@
+/* Soros interpreter (see numbertext.org)
+ * 2018 (c) László Németh
+ * License: LGPL/BSD dual license */
+
+#include <sstream>
+#include <fstream>
+
+#include "Numbertext.hxx"
+
+#ifdef HAVE_BOOST_REGEX_HPP
+ #include <boost/locale/encoding_utf.hpp>
+ using namespace boost;
+#else
+ #include <codecvt>
+ #include <locale>
+ using namespace std;
+#endif
+
+#define MODULE_DIR ""
+#define SOROS_EXT ".sor"
+
+bool readfile(std::string filename, std::wstring& result)
+{
+ std::wifstream wif(filename);
+ if (wif.fail())
+ return false;
+#ifdef _MSC_VER
+ wif.imbue(std::locale(std::locale(), new std::codecvt_utf8<wchar_t>));
+#else
+ wif.imbue(std::locale("en_US.UTF-8"));
+#endif
+ std::wstringstream wss;
+ wss << wif.rdbuf();
+ result = wss.str();
+ return true;
+}
+
+Numbertext::Numbertext():
+ prefix(MODULE_DIR),
+ modules(0)
+{
+}
+
+bool Numbertext::load(std::string lang, std::string filename)
+{
+ std::wstring module;
+ if (filename.length() == 0)
+ filename = prefix + regex_replace(lang,
+ regex("-"), "_") + SOROS_EXT;
+ if (!readfile(filename, module))
+ {
+ // try to load without the country code
+ filename = regex_replace(filename,
+ regex("[-_].." SOROS_EXT "$"), SOROS_EXT);
+ if (!readfile(filename, module))
+ return false;
+ }
+ modules.insert(std::make_pair(lang, Soros(module, string2wstring(lang))));
+ return true;
+}
+
+bool Numbertext::numbertext(std::wstring& number, std::string lang)
+{
+ auto module = modules.find(lang);
+ if (module == modules.end())
+ {
+ if (!load(lang))
+ return false;
+ module = modules.find(lang);
+ }
+ module->second.run(number);
+ return true;
+}
+
+bool Numbertext::numbertext(std::string& number, std::string lang)
+{
+ std::wstring wnumber = string2wstring(number);
+ bool result = numbertext(wnumber, lang);
+ number = wstring2string(wnumber);
+ return result;
+}
+
+std::string Numbertext::numbertext(int number, std::string lang)
+{
+ std::wstring wnumber = std::to_wstring(number);
+ numbertext(wnumber, lang);
+ return wstring2string(wnumber);
+}
+
+std::wstring Numbertext::string2wstring(const std::string& st)
+{
+#ifndef HAVE_BOOST_REGEX_HPP
+ typedef std::codecvt_utf8<wchar_t> convert_type;
+ std::wstring_convert<convert_type, wchar_t> converter;
+ return converter.from_bytes( st );
+#else
+ return ::locale::conv::utf_to_utf<wchar_t>(st.c_str(), st.c_str() + st.size());
+#endif
+}
+
+std::string Numbertext::wstring2string(const std::wstring& st)
+{
+#ifndef HAVE_BOOST_REGEX_HPP
+ typedef std::codecvt_utf8<wchar_t> convert_type;
+ std::wstring_convert<convert_type, wchar_t> converter;
+ return converter.to_bytes( st );
+#else
+ return ::locale::conv::utf_to_utf<char>(st.c_str(), st.c_str() + st.size());
+#endif
+}
diff --git a/src/Numbertext.hxx b/src/Numbertext.hxx
new file mode 100644
index 0000000..eb5daa1
--- /dev/null
+++ b/src/Numbertext.hxx
@@ -0,0 +1,29 @@
+/* Soros interpreter (see numbertext.org)
+ * 2018 (c) László Németh
+ * License: LGPL/BSD dual license */
+
+#ifndef NUMBERTEXT_HXX
+#define NUMBERTEXT_HXX
+
+#include "Soros.hxx"
+#include <unordered_map>
+
+class Numbertext
+{
+public:
+ Numbertext();
+ void set_prefix(std::string st) { prefix = st; };
+ bool load(std::string lang, std::string filename = "");
+ bool numbertext(std::wstring& number, std::string lang);
+ // UTF-8 encoded input
+ bool numbertext(std::string& number, std::string lang);
+ std::string numbertext(int number, std::string lang);
+ static std::wstring string2wstring(const std::string& s);
+ static std::string wstring2string(const std::wstring& s);
+
+private:
+ std::string prefix;
+ std::unordered_map<std::string, Soros> modules;
+};
+
+#endif
diff --git a/src/Soros.cxx b/src/Soros.cxx
new file mode 100644
index 0000000..b56e63b
--- /dev/null
+++ b/src/Soros.cxx
@@ -0,0 +1,212 @@
+/* Soros interpreter (see numbertext.org)
+ * 2018 (c) László Németh
+ * License: LGPL/BSD dual license */
+
+#include "Soros.hxx"
+
+#ifdef HAVE_BOOST_REGEX_HPP
+ using namespace boost;
+#else
+ using namespace std;
+#endif
+
+#define ITERATION_LIMIT 250
+#define SEP L"\uE00A"
+
+#ifdef HAVE_BOOST_REGEX_HPP
+#define FIX L"\\"
+#else
+#define FIX L""
+#endif
+
+const std::wstring Soros::m = L"\\\";#";
+const std::wstring Soros::m2 = L"$()|[]";
+const std::wstring Soros::c = L"\uE000\uE001\uE002\uE003";
+const std::wstring Soros::c2 = L"\uE004\uE005\uE006\uE007\uE008\uE009";
+const std::wstring Soros::slash = L"\uE000";
+const std::wstring Soros::pipe = L"\uE003";
+// pattern to recognize function calls in the replacement string
+const wregex Soros::func ( Soros::translate (
+ L"(?:\\|?(?:\\$\\()+)?" // optional nested calls
+ "(\\|?\\$\\(([^\\(\\)]*)\\)\\|?)" // inner call (2 subgroups)
+ "(?:\\)+\\|?)?", // optional nested calls
+ Soros::m2.substr(0, 4), Soros::c, L"\\")); // \$, \(, \), \| -> \uE000..\uE003
+
+void Soros::replace(std::wstring& s, const std::wstring& search,
+ const std::wstring& str) {
+ size_t pos = 0;
+ while ((pos = s.find(search, pos)) != std::wstring::npos) {
+ s.replace(pos, search.length(), str);
+ pos += str.length();
+ }
+}
+
+Soros::Soros(std::wstring source, std::wstring filtered_lang):
+ begins(0),
+ ends(0)
+{
+ source = translate(source, m, c, L"\\"); // \\, \", \;, \# -> \uE000..\uE003
+ // switch off all country-dependent lines, and switch on the requested ones
+ source = regex_replace(source, wregex(L"(^|[\n;])([^\n;#]*#[^\n]*\\[:[^\n:\\]]*:\\][^\n]*)"), L"$1#$2");
+ replace(filtered_lang, L"_", L"-");
+ source = regex_replace(source, wregex(L"(^|[\n;])#([^\n;#]*#[^\n]*\\[:" + filtered_lang + L":\\][^\n]*)"), L"$1$2");
+ source = regex_replace(source, wregex(L"(#[^\n]*)?(\n|$)"), L";"); // remove comments
+ // __numbertext__ sets the place of left zero deletion rule
+ if (source.find(L"__numbertext__") == std::wstring::npos)
+ source.insert(0, L"__numbertext__;");
+ source = regex_replace(source, wregex(L"__numbertext__"),
+ // default left zero deletion
+ L"\"([a-z][-a-z]* )?0+(0|[1-9]" FIX L"\\d*)\" $$(" FIX L"\\1" FIX L"\\2);"
+ // separator function
+ SEP L"(.*)" SEP L"(.+)" SEP L"(.*) " FIX L"\\1" FIX L"\\2" FIX L"\\3;"
+ // no separation, if subcall returns with empty string
+ SEP L".*" SEP SEP L".*");
+
+ wregex p(L"^\\s*(\"[^\"]*\"|[^\\s]*)\\s*(.*[^\\s])?\\s*$");
+ wregex macro(L"== *([^ ]*) *==");
+ size_t pos = 0;
+ size_t old_pos = 0;
+ wregex quoteStart(L"^\"");
+ wregex quoteEnd(L"\"$");
+ std::wstring smacro = L"";
+ while ((pos = source.find(L";", pos)) != std::wstring::npos) {
+ wsmatch sp;
+ std::wstring linOrig = source.substr(old_pos, pos - old_pos);
+ // pattern extension after == macro ==:
+ // foo bar -> "macro foo" bar
+ // "foo bar" baz -> "macro foo bar" baz
+ // "^foo bar" baz -> "^macro foo bar" baz
+ std::wstring lin = linOrig;
+ if (smacro.length() > 0 && linOrig.length() > 0 && regex_search(linOrig, sp, p))
+ {
+ std::wstring s = regex_replace(sp[1].str(), quoteStart, L"");
+ s = regex_replace(s, quoteEnd, L"");
+ std::wstring sEmpty = (s.length() == 0) ? L"" : L" ";
+ if (s[0] == L'^') {
+ s = regex_replace(s, wregex(L"^\\^"), L"");
+ lin = L"\"^" + smacro + sEmpty + s + L"\" " + sp[2].str();
+ } else
+ lin = L"\"" + smacro + sEmpty + s + L"\" " + sp[2].str();
+ }
+ if (linOrig.length() > 0 && regex_match(linOrig, sp, macro))
+ {
+ smacro = sp[1].str();
+ }
+ else if (lin.length() > 0 && regex_search(lin, sp, p))
+ {
+ std::wstring s = regex_replace(sp[1].str(), quoteStart, L"");
+ s = regex_replace(s, quoteEnd, L"");
+ s = translate(s, c.substr(1), m.substr(1), L"");
+ replace(s, slash, L"\\\\"); // -> \\, ", ;, #
+ begins.push_back(s[0] == L'^');
+ ends.push_back(s[s.length()-1] == L'$');
+ s = L"^" + regex_replace(s, wregex(L"^\\^"), L"");
+ s = regex_replace(s, wregex(L"\\$$"), L"") + L"$";
+ try
+ {
+ patterns.push_back(wregex(s));
+ } catch (...)
+ {
+ std::wcout << L"Soros: bad regex in \"" << sp[1].str() << "\"" << std::endl;
+ break;
+ }
+ std::wstring s2 = L"";
+ if (sp.size() > 1)
+ {
+ s2 = regex_replace(sp[2].str(), quoteStart, L"");
+ s2 = regex_replace(s2, quoteEnd, L"");
+ }
+ s2 = translate(s2, m2, c2, L"\\"); // \$, \(, \), \|, \[, \] -> \uE004..\uE009
+ // call inner separator: "[ ... $1 ... ]" -> "$(" SEP " ... " SEP "$1" SEP "... )"
+ s2 = regex_replace(s2, wregex(L"^\\[[$](\\d\\d?|\\([^\\)]+\\))"),
+ L"$$(" SEP SEP L"|$$$1" SEP); // add "|" in terminating position
+ s2 = regex_replace(s2, wregex(L"\\[([^$\\[\\\\]*)[$](\\d\\d?|\\([^\\)]+\\))"),
+ L"$$(" SEP L"$1" SEP L"$$$2" SEP);
+ s2 = regex_replace(s2, wregex(SEP L"\\]$"), L"|" SEP L")"); // add "|" in terminating position
+ s2 = translate(s2, L"]", L")", L"");
+ s2 = regex_replace(s2, wregex(L"([$]\\d|\\))\\|[$]"), L"$1||$$"); // $()|$() -> $()||$()
+ s2 = translate(s2, c, m, L""); // \uE000..\uE003-> \, ", ;, #
+ s2 = translate(s2, m2.substr(0, 4), c, L""); // $, (, ), | -> \uE000..\uE003
+ s2 = translate(s2, c2, m2, L""); // \uE004..\uE007 -> $, (, ), |
+ s2 = regex_replace(s2, wregex(L"[$]"), L"\\$$"); // $ -> \$
+ s2 = regex_replace(s2, wregex(L"\uE000(\\d)"), L"\uE000\uE001$$$1\uE002"); // $n -> $(\n)
+ s2 = regex_replace(s2, wregex(L"\\\\([1-9])"), L"$$0$1"); // \[n] -> $[n]
+ s2 = regex_replace(s2, wregex(L"\\\\0"), L"$$0"); // \0 -> $0
+ s2 = regex_replace(s2, wregex(L"\\\\n"), L"\n"); // \n -> [new line]
+ values.push_back(s2);
+ }
+ pos++;
+ old_pos = pos;
+ }
+}
+
+int Soros::run(std::wstring& input)
+{
+ int level = 0;
+ run(input, level);
+ return level;
+}
+
+void Soros::run(std::wstring& input, int& level, bool begin, bool end)
+{
+ if (level == -1)
+ return;
+ if (++level > ITERATION_LIMIT)
+ {
+ std::wcout << "Soros: iteration limit exceeded at the input \"" << input << "\"" << std::endl;
+ input = L"";
+ level = -1;
+ return;
+ }
+ for (size_t i = 0; i < patterns.size(); i++)
+ {
+ if ((!begin && begins[i]) || (!end && ends[i]))
+ continue;
+ if (!regex_match(input, patterns[i]))
+ continue;
+ input = regex_replace(input, patterns[i], values[i]);
+ wsmatch n;
+ while (regex_search(input, n, func))
+ {
+ bool b = false;
+ bool e = false;
+ if (n[1].str()[0] == pipe[0] || n[0].str()[0] == pipe[0])
+ {
+ b = true;
+ }
+ else if (n.position() == 0)
+ {
+ b = begin;
+ }
+ if (n[1].str().back() == pipe[0] || n[0].str().back() == pipe[0])
+ {
+ e = true;
+ }
+ else if (n.position() + n[0].length() == (signed) input.length())
+ {
+ e = end;
+ }
+ std::wstring piece = n[2].str();
+ run(piece, level, b, e);
+ input = input.substr(0, n.position(1)) +
+ piece +
+ input.substr(n.position(1) + n[1].length());
+ }
+ level--;
+ return;
+ }
+ level--;
+ input = L"";
+}
+
+std::wstring Soros::translate(
+ std::wstring s,
+ const std::wstring chars,
+ const std::wstring chars2,
+ const std::wstring delim)
+{
+ int i = 0;
+ for(const wchar_t& ch : chars)
+ replace(s, delim + ch, chars2.substr(i++, 1));
+ return s;
+}
diff --git a/src/Soros.hxx b/src/Soros.hxx
new file mode 100644
index 0000000..2f105aa
--- /dev/null
+++ b/src/Soros.hxx
@@ -0,0 +1,48 @@
+/* Soros interpreter (see numbertext.org)
+ * 2018 (c) László Németh
+ * License: LGPL/BSD dual license */
+
+#ifndef SOROS_HXX_
+#define SOROS_HXX_
+
+#include <iostream>
+#include <iterator>
+#include <string>
+
+#ifndef _MSC_VER
+#include "config.h"
+#endif
+
+#ifdef HAVE_BOOST_REGEX_HPP
+ #include <boost/regex.hpp>
+#else
+ #include <regex>
+#endif
+
+class Soros {
+
+public:
+ Soros(std::wstring program, std::wstring filtered_lang);
+ int run(std::wstring& input);
+ static std::wstring translate(std::wstring s,
+ std::wstring chars, std::wstring chars2, std::wstring delim);
+private:
+ void run(std::wstring& input, int& level, bool begin = true, bool end = true);
+ static void replace(std::wstring& s, const std::wstring& search,
+ const std::wstring& replace);
+
+#ifdef HAVE_BOOST_REGEX_HPP
+ std::vector<boost::wregex> patterns;
+ static const boost::wregex func;
+#else
+ std::vector<std::wregex> patterns;
+ static const std::wregex func;
+#endif
+ std::vector<std::wstring> values;
+ std::vector<bool> begins;
+ std::vector<bool> ends;
+
+ static const std::wstring m, m2, c, c2, slash, pipe;
+};
+
+#endif
diff --git a/src/Soros.js b/src/Soros.js
new file mode 100644
index 0000000..ce55d24
--- /dev/null
+++ b/src/Soros.js
@@ -0,0 +1,131 @@
+function Soros(program, lang) {
+ this.funcpat = /(\|?(\uE008\()+)?(\|?\uE008\(([^\(\)]*)\)\|?)(\)+\|?)?/
+ this.meta = "\\\"$()|#;[]"
+ this.enc = "\uE000\uE001\uE002\uE003\uE004\uE005\uE006\uE007\uE008\uE009"
+ this.lines = []
+ if (!/__numbertext__/.test(program))
+ program = "__numbertext__;" + program
+
+ program = program.replace("__numbertext__",
+ // default left zero deletion
+ "\"([a-z][-a-z]* )?0+(0|[1-9]\\d*)\" $(\\1\\2);" +
+ // separator function
+ "\"\uE00A(.*)\uE00A(.+)\uE00A(.*)\" \\1\\2\\3;" +
+ // no separation, if subcall returns with empty string
+ "\"\uE00A.*\uE00A\uE00A.*\"")
+
+ // subclass for line data
+ this.linetype = function (regex, repl, begin, end) {
+ this.pat = regex
+ this.repl = repl
+ this.begin = begin
+ this.end = end
+ };
+
+ // strip function
+ this.strip = function (st, ch) {
+ if (st == undefined) return ""
+ return st.replace(new RegExp("^" + ch + "+"), "")
+ .replace(new RegExp(ch + "+$"), "")
+ };
+
+ // character translation function
+ this.tr = function (text, chars, chars2, delim) {
+ for (var i = 0; i < chars.length; i++) {
+ var s = delim + chars[i]
+ while (text.indexOf(s) >= 0) {
+ text = text.replace(s, chars2[i]);
+ }
+ }
+ return text
+ };
+
+ // private run function
+ this._run = function (data, begin, end) {
+ for (var i in this.lines) {
+ var l = this.lines[i]
+ if (! ((!begin && l.begin) || (!end && l.end))) {
+ var m = l.pat.exec(data)
+ if (m != null) {
+ var s = data.replace(l.pat, l.repl)
+ var n = this.funcpat.exec(s)
+ while (n != null) {
+ var b = false
+ var e = false
+ if (n[3][0] == "|" || n[0][0] == "|") {
+ b = true
+ } else if (n.index == 0) {
+ b = begin
+ }
+ if (n[3][n[0].length - 1] == "|" || n[3][n[0].length - 1] == "|") {
+ e = true
+ } else if (n.index + n[0].length == s.length) {
+ e = end
+ }
+ s = s.substring(0, n.index + (n[1] == undefined ? 0 : n[1].length)) + this._run(n[4], b, e) +
+ s.substring(n.index + (n[1] == undefined ? 0 : n[1].length) + n[3].length)
+ n = this.funcpat.exec(s)
+ }
+ return s
+ }
+ }
+ }
+ return ""
+ };
+
+ // run with the string input parameter
+ this.run = function (data) {
+ data = this._run(this.tr(data, this.meta, this.enc, ""), true, true)
+ return this.tr(data, this.enc, this.meta, "")
+ };
+
+ // constructor
+// program = program.replace(/\\\\/g, "\uE000")
+// program = program.replace(/\\[(]/g, "\uE003")
+// program = program.replace(/\\[)]/g, "\uE004")
+// program = program.replace(/\\[|]/g, "\uE005")
+ program = this.tr(program, this.meta, this.enc, "\\")
+ // switch off all country-dependent lines, and switch on the requested ones
+ program = program.replace(/(^|[\n;])([^\n;#]*#[^\n]*[[]:[^\n:\]]*:][^\n]*)/g, "$1#$2")
+ .replace(new RegExp("(^|[\n;])#([^\n;#]*#[^\n]*[[]:" + lang.replace("_", "-") + ":][^\n]*)", "g"), "$1$2")
+ var l = program.replace(/(#[^\n]*)?(\n|$)/g, ";").split(";")
+ var matchline = new RegExp(/^\s*(\"[^\"]*\"|[^\s]*)\s*(.*[^\s])?\s*$/)
+ var prefix = ""
+ for (var i in l) {
+ var macro = /== *(.*[^ ]?) ==/.exec(l[i])
+ if (macro != null) {
+ prefix = macro[1]
+ continue
+ }
+ var s = matchline.exec(l[i])
+ if (prefix != "" && l[i] != "" && s != null) {
+ s1 = this.strip(s[1], "\"")
+ var empty = (s1 == "")
+ var start = (!empty && s1[0] == '^')
+ if (s[2] == undefined) s[2] = ""
+ l2 = "\"" + (start ? "^" : "") + prefix + (empty ? "" : " ") +
+ s1.replace("^\^", "") + "\" " + s[2]
+ s = matchline.exec(l2)
+ }
+ if (s != null) {
+ s[1] = this.strip(s[1], "\"")
+ if (s[2] == undefined) s[2] = ""; else s[2] = this.strip(s[2], "\"")
+ var line = new this.linetype(
+ new RegExp("^" + s[1].replace("^\^", "").replace("\$$", "") + "$"),
+ s[2].replace(/\\n/g, "\n")
+ // call inner separator: [ ... $1 ... ] -> $(\uE00A ... \uE00A$1\uE00A ... )
+ .replace(/^[[]\$(\d\d?|\([^\)]+\))/g,"$(\uE00A\uE00A|$$$1\uE00A")
+ .replace(/[[]([^\$[\\]*)\$(\d\d?|\([^\)]+\))/g,"$(\uE00A$1\uE00A$$$2\uE00A")
+ .replace(/\uE00A]$/, "|\uE00A)") // add "|" in terminating position
+ .replace(/]/g, ")")
+ .replace(/(\$\d|\))\|\$/g,"$1||$$") // $(..)|$(..) -> $(..)||$(..)
+ .replace(/\$/g, "\uE008")
+ .replace(/\\0/g, "$$&")
+ .replace(/\\(\d)/g, "$$$1")
+ .replace(/\uE008(\d)/g, "\uE008($$$1)"),
+ /^\^/.test(s[1]), /\$$/.test(s[1])
+ )
+ this.lines = this.lines.concat(line)
+ }
+ }
+};
diff --git a/src/Soros.py b/src/Soros.py
new file mode 100644
index 0000000..b34fce6
--- /dev/null
+++ b/src/Soros.py
@@ -0,0 +1,119 @@
+"Soros interpreter (see http://numbertext.org)"
+from __future__ import unicode_literals
+from __future__ import print_function
+import re, sys
+
+def run(program, data, lang):
+ return compile(program, lang).run(data)
+
+def compile(program, lang):
+ return _Soros(program, lang)
+
+# conversion function
+def _tr(text, chars, chars2, delim):
+ for i in range(0, len(chars)):
+ text = text.replace(delim + chars[i], chars2[i])
+ return text
+
+# string literals for metacharacter encoding
+_m = "\\\";#$()|[]"
+_c = u"\uE000\uE001\uE002\uE003\uE004\uE005\uE006\uE007\uE008\uE009" # Unicode private area
+_pipe = u"\uE003"
+# separator prefix = \uE00A
+
+# pattern to recognize function calls in the replacement string
+_func = re.compile(_tr(r"""(?:\|?(?:\$\()+)? # optional nested calls
+ (\|?\$\(([^\(\)]*)\)\|?) # inner call (2 subgroups)
+ (?:\)+\|?)?""", # optional nested calls
+ _m[4:8], _c[:4], "\\"), re.X) # \$, \(, \), \| -> \uE000..\uE003
+
+class _Soros:
+ def __init__(self, prg, lang):
+ self.lines = []
+ if prg.find("__numbertext__") == -1:
+ prg = "__numbertext__;" + prg
+ # default left zero deletion
+ # and separator function (no separation, if subcall returns with empty string)
+ prg = prg.replace("__numbertext__", u"""0+(0|[1-9]\\d*) $1
+\"([a-z][-a-z]* )0+(0|[1-9]\\d*)\" $(\\1\\2)
+\"\uE00A(.*)\uE00A(.+)\uE00A(.*)\" \\1\\2\\3
+\"\uE00A.*\uE00A\uE00A.*\"
+""")
+ prg = _tr(prg, _m[:4], _c[:4], "\\") # \\, \", \;, \# -> \uE000..\uE003
+ # switch off all country-dependent lines, and switch on the requested ones
+ prg = re.sub(r"(^|[\n;])([^\n;#]*#[^\n]*[[]:[^\n:\]]*:][^\n]*)", r"\1#\2", prg)
+ prg = re.sub(r"(^|[\n;])#([^\n;#]*#[^\n]*[[]:" + lang.replace("_", "-") + r":][^\n]*)", r"\1\2", prg)
+ matchline = re.compile("^\s*(\"[^\"]*\"|[^\s]*)\s*(.*[^\s])?\s*$")
+ prefix = ""
+ for s in re.sub("(#[^\n]*)?(\n|$)", ";", prg).split(";"):
+ macro = re.match("== *(.*[^ ]?) ==", s)
+ if macro != None:
+ prefix = macro.group(1)
+ continue
+ m = matchline.match(s)
+ if prefix != "" and s != "" and m != None:
+ s = m.group(1).strip("\"")
+ space = " " if s != "" else ""
+ caret = ""
+ if s[0:1] == "^":
+ s = s[1:]
+ caret = "^"
+ s2 = m.group(2) if m.group(2) != None else ""
+ s = "\"" + caret + prefix + space + s + "\" " + s2
+ m = matchline.match(s)
+ if m != None:
+ s = _tr(m.group(1).strip("\""), _c[1:4], _m[1:4], "") \
+ .replace(_c[_m.find("\\")], "\\\\") # -> \\, ", ;, #
+ if m.group(2) != None:
+ s2 = m.group(2).strip("\"")
+ else:
+ s2 = ""
+ s2 = _tr(s2, _m[4:], _c[4:], "\\") # \$, \(, \), \|, \[, \] -> \uE004..\uE009
+ # call inner separator: [ ... $1 ... ] -> $(\uE00A ... \uE00A$1\uE00A ... )
+ s2 = re.sub(r"[[]\$(\d\d?|\([^\)]+\))",u"$(\uE00A\uE00A|$\\1\uE00A", s2)
+ s2 = re.sub(r"[[]([^\$[\\]*)\$(\d\d?|\([^\)]+\))",u"$(\uE00A\\1\uE00A$\\2\uE00A", s2)
+ s2 = re.sub(r"\uE00A]$","|\uE00A)", s2) # add "|" in terminating position
+ s2 = re.sub(r"]",")", s2)
+ s2 = re.sub(r"(\$\d|\))\|\$", r"\1||$", s2) # $()|$() -> $()||$()
+ s2 = _tr(s2, _c[:4], _m[:4], "") # \uE000..\uE003-> \, ", ;, #
+ s2 = _tr(s2, _m[4:8], _c[:4], "") # $, (, ), | -> \uE000..\uE003
+ s2 = _tr(s2, _c[4:], _m[4:], "") # \uE004..\uE009 -> $, (, ), |, [, ]
+ s2 = re.sub(r"\\(\d)", r"\\g<\1>",
+ re.sub(r"\uE000(\d)", "\uE000\uE001\\\\g<\\1>\uE002", s2))
+ try:
+ self.lines = self.lines + [[
+ re.compile("^" + s.lstrip("^").rstrip("$") + "$"),
+ s2, s[:1] == "^", s[-1:] == "$"]]
+ except:
+ print("Error in following regex line: " + s, file=sys.stderr)
+ raise
+
+ def run(self, data):
+ return self._run(data, True, True)
+
+ def _run(self, data, begin, end):
+ for i in self.lines:
+ if not ((begin == False and i[2]) or (end == False and i[3])):
+ m = i[0].match(data)
+ if m:
+ try:
+ s = m.expand(i[1])
+ except:
+ print("Error for the following input: " + data, file=sys.stderr)
+ raise
+ n = _func.search(s)
+ while n:
+ b = False
+ e = False
+ if n.group(1)[0:1] == _pipe or n.group()[0:1] == _pipe:
+ b = True
+ elif n.start() == 0:
+ b = begin
+ if n.group(1)[-1:] == _pipe or n.group()[-1:] == _pipe:
+ e = True
+ elif n.end() == len(s):
+ e = end
+ s = s[:n.start(1)] + self._run(n.group(2), b, e) + s[n.end(1):]
+ n = _func.search(s)
+ return s
+ return ""
diff --git a/src/numbertext-version.h.in b/src/numbertext-version.h.in
new file mode 100644
index 0000000..fa308d1
--- /dev/null
+++ b/src/numbertext-version.h.in
@@ -0,0 +1,9 @@
+#ifndef NUMBERTEXT_VERSION_H
+#define NUMBERTEXT_VERSION_H
+
+#define NUMBERTEXT_VERSION "@NUMBERTEXT_VERSION@"
+#define NUMBERTEXT_VERSION_MAJOR @NUMBERTEXT_MAJOR_VERSION@
+#define NUMBERTEXT_VERSION_MINOR @NUMBERTEXT_MINOR_VERSION@
+#define NUMBERTEXT_VERSION_MICRO @NUMBERTEXT_MICRO_VERSION@
+
+#endif
diff --git a/src/places.py b/src/places.py
new file mode 100644
index 0000000..29761e7
--- /dev/null
+++ b/src/places.py
@@ -0,0 +1,121 @@
+places = { "AMD":2,
+"ARS":2,
+"ATS":2,
+"AUD":2,
+"AZM":2,
+"AZN":2,
+"BAM":2,
+"BDT":2,
+"BEF":2,
+"BGL":2,
+"BGN":2,
+"BOB":2,
+"BOP":0,
+"BRL":2,
+"BTN":2,
+"BYR":2,
+"BZD":2,
+"CAD":2,
+"CDF":2,
+"CHF":2,
+"CLP":0,
+"CNY":2,
+"COP":2,
+"CRC":2,
+"CZK":2,
+"CSD":2,
+"DEM":2,
+"DKK":2,
+"DOP":2,
+"ECS":2,
+"EEK":2,
+"EGP":2,
+"ERN":2,
+"ESP":0,
+"ETB":2,
+"EUR":2,
+"FIM":2,
+"FRF":2,
+"GBP":2,
+"GEL":2,
+"GHC":2,
+"GHS":2,
+"GRD":2,
+"GTQ":2,
+"HKD":2,
+"HNL":2,
+"HRK":2,
+"HUF":2,
+"IDR":2,
+"IEP":2,
+"ILS":2,
+"INR":2,
+"IRR":0,
+"ISK":2,
+"ITL":0,
+"JMD":2,
+"JPY":0,
+"KGS":2,
+"KHR":0,
+"KRW":0,
+"KZT":2,
+"LAK":2,
+"LBP":2,
+"LTL":2,
+"LUF":2,
+"LVL":2,
+"MGA":0.7,
+"MKD":2,
+"MMK":2,
+"MNT":2,
+"MOP":2,
+"MRO":0.7,
+"MXN":2,
+"MYR":2,
+"NAD":2,
+"NIO":2,
+"NLG":2,
+"NOK":2,
+"NPR":2,
+"NZD":2,
+"PAB":2,
+"PEN":2,
+"PGK":2,
+"PHP":2,
+"PLN":2,
+"PLZ":2,
+"PTE":2,
+"PYG":2,
+"ROL":2,
+"RON":2,
+"RSD":2,
+"RUB":2,
+"RUR":2,
+"RWF":2,
+"SAR":2,
+"SEK":2,
+"SGD":2,
+"SIT":2,
+"SKK":2,
+"SOS":2,
+"SVC":0,
+"THB":2,
+"TJS":2,
+"TMM":2,
+"TND":3,
+"TRL":2,
+"TRY":2,
+"TTD":2,
+"TWD":2,
+"TZS":2,
+"UAH":2,
+"UGX":2,
+"USD":2,
+"UYU":2,
+"UZS":2,
+"VEB":2,
+"VEF":2,
+"VND":2,
+"XAF":2,
+"ZAR":2,
+"ZWD":2}
diff --git a/src/soroside.py b/src/soroside.py
new file mode 100644
index 0000000..27e916f
--- /dev/null
+++ b/src/soroside.py
@@ -0,0 +1,55 @@
+import Soros
+import sys
+import codecs
+
+out = sys.stdout
+
+state = ""
+output = ""
+prefix = ""
+params = []
+for i in sys.argv:
+ if state != "":
+ if state == "prefix":
+ prefix = i + " "
+ elif state == "output":
+ output = i
+ state = ""
+ continue
+ if i == "-p":
+ state = "prefix"
+ elif i == "-o":
+ state = "output"
+ else:
+ params += [i]
+
+if output != "":
+ out = codecs.open(output, "wb", encoding="UTF-8")
+
+if len(params) < 2:
+ print ("Usage: soros [-o file_output] [-p prefix] soros_file number(s)")
+ print ("numbers may be ranges (1-100) or ranges with steps (1-100~10)")
+ sys.exit()
+
+fil = codecs.open(params[1], encoding="UTF-8")
+s = Soros.compile(fil.read())
+for i in params[2:]:
+ b = i[1:].split("-", 1)
+ b[0] = i[0] + b[0]
+ if len(b) > 1:
+ step = 1
+ c = b[1].split("~", 1)
+ if len(c) > 1:
+ b[1] = c[0]
+ step = int(c[1])
+ for j in range(int(b[0]), int(b[1]) + 1, step):
+ try:
+ print (s.run(prefix + str(j)))
+ except:
+ print >>out, s.run(prefix + str(j))
+
+ else:
+ try:
+ print (s.run(prefix + i))
+ except:
+ print >>out, s.run(prefix + i)
diff --git a/src/spellout.cxx b/src/spellout.cxx
new file mode 100644
index 0000000..e84f0e5
--- /dev/null
+++ b/src/spellout.cxx
@@ -0,0 +1,118 @@
+#include "Numbertext.hxx"
+#include "numbertext-version.h"
+#include <cstring>
+
+#ifdef HAVE_BOOST_REGEX_HPP
+ using namespace boost;
+#else
+ using namespace std;
+#endif
+
+#define LANG "LANG"
+#define PATH "NUMBERTEXTPATH"
+#define DEFPATH "/usr/share/numbertext/"
+#define DEFPATH2 "data/"
+
+enum State { base, loaded, flag_lang, flag_prefix};
+
+void error()
+{
+ std::cerr << "spellout: missing language module" << std::endl;
+ std::exit(EXIT_FAILURE);
+}
+
+int main(int argc, char* argv[])
+{
+ if (argc == 1) {
+ std::cout << "spellout " NUMBERTEXT_VERSION ": convert numbers to number names and money amounts" << std::endl;
+ std::cout << "Usage: spellout [-l lang] [-p prefix] par1 [par2...]" << std::endl;
+ std::cout << "Parameter: n: number; n-m: range; n-m~s: range with step" << std::endl;
+ std::cout << "Examples: spellout 1-10 500 1000-10000~1000" << std::endl;
+ std::cout << " spellout -l en-GB -p ordinal 1-100" << std::endl;
+ std::cout << " spellout -l en -p ordinal-number 1-100" << std::endl;
+ std::cout << " spellout -l en -p USD 100.45" << std::endl;
+ std::cout << " spellout -l en -p \"money USD\" 100.45" << std::endl;
+ std::cout << "Help of language module: spellout -l es help" << std::endl;
+ std::cout << "License: GNU LGPL/BSD dual-license\n";
+ return 0;
+ }
+ std::vector <std::string> paths;
+ paths.push_back("");
+ paths.push_back(DEFPATH);
+ paths.push_back(DEFPATH2);
+
+ if (getenv(PATH))
+ paths.insert(paths.begin() + 1, std::string(getenv(PATH)) + "/");
+ std::string lang;
+
+ Numbertext nt;
+ State state = State::base;
+ std::string prefix = "";
+ for (int i = 1; i < argc; i++)
+ {
+ if (state == State::flag_lang || state == State::flag_prefix)
+ {
+ if (state == State::flag_lang)
+ {
+ lang = argv[i];
+ }
+ else
+ {
+ prefix = argv[i];
+ prefix += " ";
+ }
+ state = State::base;
+ continue;
+ }
+ if (strcmp(argv[i], "-l") == 0)
+ {
+ state = State::flag_lang;
+ }
+ else if (strcmp(argv[i], "-p") == 0)
+ {
+ state = State::flag_prefix;
+ }
+ else
+ {
+ if (lang.empty()) {
+ if (getenv(LANG)) {
+ lang = std::string(getenv(LANG));
+ lang = lang.substr(0, lang.find("."));
+ }
+ if (lang.empty())
+ lang = "en";
+ }
+
+ if (state != State::loaded) {
+ for(auto const& path: paths) {
+ nt.set_prefix(path);
+ if (nt.load(lang))
+ break;
+ }
+ state = State::loaded;
+ }
+
+ std::string arg = argv[i];
+ smatch n;
+ if (regex_match(arg, n, regex("([0-9]+)-([0-9]+)~?([0-9]+)?")))
+ {
+ long long b = std::stoll(n[1].str());
+ long long end = std::stoll(n[2].str());
+ long long step = (n[3].length() == 0) ? 1 : std::stoll(n[3].str());
+ for (int j = b; j <= end; j = j + step) {
+ std::string result = prefix + std::to_string(j);
+ if (!nt.numbertext(result, lang))
+ error();
+ std::cout << result << std::endl;
+ }
+ }
+ else
+ {
+ std::string result = prefix + arg;
+ if (!nt.numbertext(result, lang))
+ error();
+ std::cout << result << std::endl;
+ }
+ }
+ }
+}
diff --git a/test/Makefile b/test/Makefile
new file mode 100644
index 0000000..0241054
--- /dev/null
+++ b/test/Makefile
@@ -0,0 +1,5 @@
+all:
+ for i in *.test; do echo -n "$$i ";./$$i && echo done; done
+
+clean:
+ rm -rf testSubDir
diff --git a/test/test b/test/test
new file mode 100755
index 0000000..91efcd5
--- /dev/null
+++ b/test/test
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+TESTDIR="."
+
+TEMPDIR="./testSubDir"
+
+if [ ! -d $TEMPDIR ]; then
+ mkdir $TEMPDIR
+fi
+
+PYTHONPATH=../src/ python test.py $TESTDIR/$1 $TESTDIR/$2 $TEMPDIR/test.out$$
+diff $TEMPDIR/test.out$$ $TESTDIR/$3 || exit 1
diff --git a/test/test.py b/test/test.py
new file mode 100644
index 0000000..ec06111
--- /dev/null
+++ b/test/test.py
@@ -0,0 +1,23 @@
+from __future__ import print_function
+import sys
+import Soros
+import codecs
+#
+# test input_file input_stream output_stream [conditional_language_codes...]
+#
+fil = codecs.open(sys.argv[1], encoding="UTF-8")
+inp = codecs.open(sys.argv[2], encoding="UTF-8").readlines()
+out = codecs.open(sys.argv[3], "wb", encoding="UTF-8")
+prg = fil.read()
+s = {}
+langs = ["default"] + sys.argv[4:]
+for l in langs:
+ s[l] = Soros.compile(prg, l)
+ll = len(langs)
+for l in langs:
+ print("Language: " + l, file=sys.stderr)
+ if ll > 1:
+ print("Language: " + l, file=out)
+ for i in inp:
+ print(s[l].run(i.strip()), file=out)
+
diff --git a/test/test.sh b/test/test.sh
new file mode 100755
index 0000000..91efcd5
--- /dev/null
+++ b/test/test.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+TESTDIR="."
+
+TEMPDIR="./testSubDir"
+
+if [ ! -d $TEMPDIR ]; then
+ mkdir $TEMPDIR
+fi
+
+PYTHONPATH=../src/ python test.py $TESTDIR/$1 $TESTDIR/$2 $TEMPDIR/test.out$$
+diff $TEMPDIR/test.out$$ $TESTDIR/$3 || exit 1
diff --git a/test/test0.test b/test/test0.test
new file mode 100755
index 0000000..9a6a4a1
--- /dev/null
+++ b/test/test0.test
@@ -0,0 +1,13 @@
+#!/bin/bash
+export LC_COLLATE=C # case-sensitive file glob
+for i in ../data/[a-zHR]*.sor # skip Suzhou.sor (multiline regex support needs for conditional text, yet)
+do
+ echo === $i ===
+ # check first 1000 numbers in all languages, checking also the conditional lines
+ PYTHONPATH=../src python test.py $i <(seq 0 2000) /dev/stdout $(grep -Eo '\[:.....:]' $i | tr -d '[]:' | sort | uniq) |
+ awk -v fil="$i" '
+ /Language:/{delete a; lang=$2}
+ /^$/{print "Missing output: " fil " (input number: " NR%2000", language: " lang ")";next}
+ a[$0]==1{print "Duplicate: $0 (input number: " NR%2000 ", language: " lang ")"}
+ {a[$0]=1}'
+done
diff --git a/test/test1.in b/test/test1.in
new file mode 100644
index 0000000..18a667e
--- /dev/null
+++ b/test/test1.in
@@ -0,0 +1,24 @@
+1
+2
+3
+4
+5
+15
+0
+10
+8
+18
+6
+7
+9
+14
+16
+17
+19
+51
+20
+21
+30
+38
+40
+45 \ No newline at end of file
diff --git a/test/test1.out b/test/test1.out
new file mode 100644
index 0000000..86a91a5
--- /dev/null
+++ b/test/test1.out
@@ -0,0 +1,24 @@
+one
+two
+three
+four
+five
+fifteen
+zero
+ten
+eight
+eighteen
+six
+seven
+nine
+fourteen
+sixteen
+seventeen
+nineteen
+fifty-one
+twenty
+twenty-one
+thirty
+thirty-eight
+fierzig
+fifundfierzig
diff --git a/test/test1.sor b/test/test1.sor
new file mode 100644
index 0000000..986e62f
--- /dev/null
+++ b/test/test1.sor
@@ -0,0 +1,39 @@
+# line separators
+
+1 one; 2 two
+3 three
+
+# comments
+4 four # ;5 foo
+
+# boundary
+
+^5$ five
+^5 fif
+1(5) $1teen # fifteen
+
+^0$ zero
+1(0) ten$1 # ten
+
+8$ eight
+8 eigh
+1(8) $1teen # eighteen
+
+# back-references
+
+6 six
+7 seven
+9 nine
+
+1(4) $(4)teen # recall with fix argument
+1(6) $(006)teen # left-zero deletion
+1(7) $(\1)teen # reference
+1(9) $1teen # abbreviated form: $1 = $(\1)
+50 fifty
+(5)(\d) $(\10)-$2 # $(\10) expanded to $(50)
+
+# conditional text
+
+2(\d) twenty[-$1] # twenty, twenty-one
+3([08]) thirty[-$(\1)] # thirty, thirty-eight
+4([05]) [$1und]fierzig # fierzig, fifundfierzig
diff --git a/test/test1.test b/test/test1.test
new file mode 100755
index 0000000..6513589
--- /dev/null
+++ b/test/test1.test
@@ -0,0 +1,4 @@
+#!/bin/sh
+DIR="`dirname $0`"
+NAME="`basename $0 .test`"
+$DIR/test.sh $NAME.sor $NAME.in $NAME.out
diff --git a/test/test2.in b/test/test2.in
new file mode 100644
index 0000000..956483b
--- /dev/null
+++ b/test/test2.in
@@ -0,0 +1,2 @@
+ABC
+smart rats
diff --git a/test/test2.out b/test/test2.out
new file mode 100644
index 0000000..c70743f
--- /dev/null
+++ b/test/test2.out
@@ -0,0 +1,2 @@
+CBA
+star trams
diff --git a/test/test2.sor b/test/test2.sor
new file mode 100644
index 0000000..634cabe
--- /dev/null
+++ b/test/test2.sor
@@ -0,0 +1,2 @@
+# reverse function
+(.*)(.) \2$1
diff --git a/test/test2.test b/test/test2.test
new file mode 100755
index 0000000..6513589
--- /dev/null
+++ b/test/test2.test
@@ -0,0 +1,4 @@
+#!/bin/sh
+DIR="`dirname $0`"
+NAME="`basename $0 .test`"
+$DIR/test.sh $NAME.sor $NAME.in $NAME.out
diff --git a/test/test3.in b/test/test3.in
new file mode 100644
index 0000000..7f97837
--- /dev/null
+++ b/test/test3.in
@@ -0,0 +1,7 @@
+0
+3
+13
+23
+33
+303
+3003
diff --git a/test/test3.out b/test/test3.out
new file mode 100644
index 0000000..43e4eb6
--- /dev/null
+++ b/test/test3.out
@@ -0,0 +1,7 @@
+zero
+tre
+tredici
+ventitré
+trentatré
+trecentotré
+tremilatré
diff --git a/test/test3.sor b/test/test3.sor
new file mode 100644
index 0000000..8369b64
--- /dev/null
+++ b/test/test3.sor
@@ -0,0 +1,43 @@
+__numbertext__
+^0 zero
+1 uno
+2 due
+^3$ tre
+3$ tré
+3 tre
+4 quattro
+5 cinque
+6 sei
+7 sette
+8 otto
+9 nove
+10 dieci
+11 undici
+12 dodici
+13 tredici
+14 quattordici
+15 quindici
+16 sedici
+17 diciassette
+18 diciotto
+19 diciannove
+2([18]) vent$1
+2(\d) venti$1
+3([18]) trent$1
+3(\d) trenta$1
+4([18]) quarant$1
+4(\d) quaranta$1
+5([18]) cinquant$1
+5(\d) cinquanta$1
+6([18]) sessant$1
+6(\d) sessanta$1
+7([18]) settant$1
+7(\d) settanta$1
+8([18]) ottant$1
+8(\d) ottanta$1
+9([18]) novant$1
+9(\d) novanta$1
+(\d)(\d\d) $1cento$2
+1(\d{3}) mille$1
+(\d{1,2})(\d{3}) $1mila$2
+(\d{3})(\d{3}) $1mila $2
diff --git a/test/test3.test b/test/test3.test
new file mode 100755
index 0000000..6513589
--- /dev/null
+++ b/test/test3.test
@@ -0,0 +1,4 @@
+#!/bin/sh
+DIR="`dirname $0`"
+NAME="`basename $0 .test`"
+$DIR/test.sh $NAME.sor $NAME.in $NAME.out
diff --git a/test/test4.in b/test/test4.in
new file mode 100644
index 0000000..46f1b0f
--- /dev/null
+++ b/test/test4.in
@@ -0,0 +1,3 @@
+1000
+2000
+3000
diff --git a/test/test4.out b/test/test4.out
new file mode 100644
index 0000000..9055f93
--- /dev/null
+++ b/test/test4.out
@@ -0,0 +1,3 @@
+ettusen
+tvåtusen
+tretusen
diff --git a/test/test4.sor b/test/test4.sor
new file mode 100644
index 0000000..1d951b0
--- /dev/null
+++ b/test/test4.sor
@@ -0,0 +1,11 @@
+__numbertext__
+^0 noll
+1 ett
+2 två
+3 tre
+(\d)000 $($1tusen) # postprocessing
+
+# convert triple consonant "ttt" to "tt"
+
+(\D+t)t(t\D+) \1\2
+(\D+) \1
diff --git a/test/test4.test b/test/test4.test
new file mode 100755
index 0000000..6513589
--- /dev/null
+++ b/test/test4.test
@@ -0,0 +1,4 @@
+#!/bin/sh
+DIR="`dirname $0`"
+NAME="`basename $0 .test`"
+$DIR/test.sh $NAME.sor $NAME.in $NAME.out
diff --git a/test/test5.in b/test/test5.in
new file mode 100644
index 0000000..3e8cd34
--- /dev/null
+++ b/test/test5.in
@@ -0,0 +1,2 @@
+1000000
+1000001
diff --git a/test/test5.out b/test/test5.out
new file mode 100644
index 0000000..eb27c58
--- /dev/null
+++ b/test/test5.out
@@ -0,0 +1,2 @@
+un million
+un million uno
diff --git a/test/test5.sor b/test/test5.sor
new file mode 100644
index 0000000..4c6ed54
--- /dev/null
+++ b/test/test5.sor
@@ -0,0 +1,7 @@
+# check boundary detection in nested calls
+__numbertext__
+^1$ uno
+^1 un
+(1)000000 $($($1)) million
+(1)(000001) $($($1)) million $(|$($2))
+(\D+) \1
diff --git a/test/test5.test b/test/test5.test
new file mode 100755
index 0000000..6513589
--- /dev/null
+++ b/test/test5.test
@@ -0,0 +1,4 @@
+#!/bin/sh
+DIR="`dirname $0`"
+NAME="`basename $0 .test`"
+$DIR/test.sh $NAME.sor $NAME.in $NAME.out
diff --git a/test/test6.in b/test/test6.in
new file mode 100644
index 0000000..6178079
--- /dev/null
+++ b/test/test6.in
@@ -0,0 +1 @@
+b
diff --git a/test/test6.out b/test/test6.out
new file mode 100644
index 0000000..a4c6917
--- /dev/null
+++ b/test/test6.out
@@ -0,0 +1 @@
+a a
diff --git a/test/test6.sor b/test/test6.sor
new file mode 100644
index 0000000..5572c3b
--- /dev/null
+++ b/test/test6.sor
@@ -0,0 +1,3 @@
+# check quoted space in return value
+a " "
+b a$(a)a
diff --git a/test/test6.test b/test/test6.test
new file mode 100755
index 0000000..6513589
--- /dev/null
+++ b/test/test6.test
@@ -0,0 +1,4 @@
+#!/bin/sh
+DIR="`dirname $0`"
+NAME="`basename $0 .test`"
+$DIR/test.sh $NAME.sor $NAME.in $NAME.out
diff --git a/test/test7.in b/test/test7.in
new file mode 100644
index 0000000..c32fa00
--- /dev/null
+++ b/test/test7.in
@@ -0,0 +1,4 @@
+ordinal 2
+ordinal 1002
+ordinal
+2
diff --git a/test/test7.out b/test/test7.out
new file mode 100644
index 0000000..f302043
--- /dev/null
+++ b/test/test7.out
@@ -0,0 +1,4 @@
+secondA
+one thousand secondB
+Ordinal example...
+two
diff --git a/test/test7.sor b/test/test7.sor
new file mode 100644
index 0000000..a52ce0e
--- /dev/null
+++ b/test/test7.sor
@@ -0,0 +1,16 @@
+# check prefix macro
+
+1 one
+
+== ordinal ==
+
+1 first
+^2 secondA
+2 secondB
+3 third
+(\d)(\d{3}) $1 thousand $(ordinal \2)
+"" Ordinal example...
+
+== ==
+
+2 two
diff --git a/test/test7.test b/test/test7.test
new file mode 100755
index 0000000..6513589
--- /dev/null
+++ b/test/test7.test
@@ -0,0 +1,4 @@
+#!/bin/sh
+DIR="`dirname $0`"
+NAME="`basename $0 .test`"
+$DIR/test.sh $NAME.sor $NAME.in $NAME.out
diff --git a/test/thaicheck.ods b/test/thaicheck.ods
new file mode 100644
index 0000000..4f667e8
--- /dev/null
+++ b/test/thaicheck.ods
Binary files differ
diff --git a/web/AUTHORS.html.in b/web/AUTHORS.html.in
new file mode 100644
index 0000000..72eaab9
--- /dev/null
+++ b/web/AUTHORS.html.in
@@ -0,0 +1,16 @@
+<html>
+<head><title>
+Authors and contributors of NUMBERTEXT/MONEYTEXT development</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+<body>
+<style type="text/css">
+@import "numbertext.css";
+</style>
+<pre>
+<!-- **************************************************************************************************** -->
+<!--!cat ../AUTHORS-->
+<!-- **************************************************************************************************** -->
+</pre>
+</body>
+</html> \ No newline at end of file
diff --git a/web/Makefile b/web/Makefile
new file mode 100644
index 0000000..9bfe313
--- /dev/null
+++ b/web/Makefile
@@ -0,0 +1,8 @@
+all:
+ cat index.html.in | ../bin/shellhtml >webroot/index.html
+ cat Soros.html.in | ../bin/shellhtml >webroot/Soros.html
+ cat AUTHORS.html.in | ../bin/shellhtml >webroot/AUTHORS.html
+
+clean:
+ rm -f webroot/index.html webroot/Soros.html webroot/AUTHORS.html webroot/*.pdf
+ rm -f webroot/Soros.py webroot/Soros.js
diff --git a/web/Soros.html.in b/web/Soros.html.in
new file mode 100644
index 0000000..0c9e17b
--- /dev/null
+++ b/web/Soros.html.in
@@ -0,0 +1,129 @@
+<html>
+<head><title>Soros IDE 1.0 &ndash; Integrated developing environment of the Soros programming language</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+<body>
+<style type="text/css">
+@import "css/numbertext.css";
+</style>
+<div class='title'>
+<table width="100%" style='border-style: solid; border-width: 0px 0px 1px 0px;'><tr><td><span>&bull;&bull;&bull; NUMBERTEXT.org &bull;&bull;&bull;
+IDE of Soros programming language (<a href="https://github.com/Numbertext/libnumbertext/blob/master/doc/sorosspec.pdf">specification</a>) </span></td><td align='right'>
+<span class='nowrap'>
+<!--<a class="menu2" href="IDE.html">IDE</a>-->
+<a class="menu2" href="index.html#about">Back</a>
+</span></td></tr></table></div>
+
+<script type="text/javascript" language="javascript1.3">
+MAXLIST=1000
+<!-- **************************************************************************************************** -->
+<!--!cat ../src/Soros.js-->
+<!-- **************************************************************************************************** -->
+function convert() {
+ var s = document.getElementById('number').value;
+ var prefix = document.getElementById('prefix').value;
+ if (prefix != "")
+ prefix = prefix + " ";
+ var ranges = s.split(";")
+ var res = ""
+ if ( ranges.length > 1 || s.match(/\d[-]/) ) {
+ for (var j = 0; j < ranges.length; j++) {
+ if (ranges[j].match(/\d-/)) {
+ var nums = ranges[j].split("-")
+ var nums2 = nums[1].split("~")
+ var maxi = parseInt(nums2[0])
+ var begin = parseInt(nums[0])
+ if (maxi < begin) maxi = begin + 111;
+ var steps = nums2.length == 1 ? 1 : parseInt(nums2[1])
+ if (maxi - begin > MAXLIST) maxi = begin + MAXLIST
+ for (var i = begin; i <= maxi; i=i+steps)
+ res = res + i + "\t" + mySoros.run(prefix + i + "") + "\n";
+ } else {
+ res = res + ranges[j] + "\t" + mySoros.run(prefix + ranges[j]) + "\n";
+ }
+ }
+ document.getElementById('numbers').value = res;
+ document.getElementById('result').value = "";
+ } else {
+ document.getElementById('result').value = mySoros.run(prefix + s);
+ document.getElementById('numbers').value = "";
+ }
+}
+function comp() {
+ var lang = document.getElementById('select').value + "-" + document.getElementById('country').value;
+ mySoros = new Soros(document.getElementById('def').value, lang);
+}
+function load_prg() {
+ var modulename = document.getElementById('select').value;
+ var workspace = document.getElementById('def');
+ var tutorial = (modulename.indexOf("Tutorial") > -1);
+ workspace.spellcheck = tutorial ? false : true;
+ workspace.style.fontSize = tutorial ? "120%" : "100%";
+ var tutorial4 = tutorial && (modulename.indexOf("4") > -1);
+ var tutorial5 = tutorial && (modulename.indexOf("5") > -1);
+ document.getElementById('number').value = tutorial5 ? "-1;-0;0-19;20-29~2;30-40~3;60-79~5;90-120~5;ordinal 0;ordinal 1;ordinal 2;ordinal 3;ordinal 100;ordinal 101" : (tutorial4 ? "1;10;100;1000;10000;1000000;1234567;10000000;12345678;100000000;123456789;1000000000;1234567890" : "0-120");
+ workspace.value = document.getElementById(modulename).value;
+}
+function copy_result() {
+ document.getElementById('number').value = document.getElementById('result').value;
+}
+</script>
+<table width="100%">
+ <tr>
+ <td>
+ <div class='row'>
+ <label for="country" accesskey="c"><u>C</u>ountry:</label>
+ <input type="text" title="Country (for example, “GB” for “en”)" style="width: 3em;" id="country" onkeyup="comp();convert()" value="" />
+ <label for="prefix" accesskey="p"><u>P</u>refix:</label>
+ <input type="text" title="Prefix (for example, “ordinal”)" style="width: 10em;" id="prefix" onkeyup="convert();" value="" />
+ <label for="number" accesskey="i"><u>I</u>nput:</label>
+ <input type="text" title="Number (eg. 1234) or number range (1-100) or number with currency (USD 15)" id="number" onkeyup="convert();" style="width: 10em;" value="0-120" />
+ &nbsp;&nbsp;
+ Output: <input type="button" id="result" onclick="copy_result();js();" />
+ </div>
+ <tr>
+ <td>
+ <div class='row' id='header'>
+ <label for="def" accesskey="e">Program <u>e</u>ditor</label>&nbsp;&nbsp;
+ <label for="select" accesskey="l"><u>L</u>oad:</label>
+ <select id="select" onchange="load_prg(); comp(); convert();">
+ <option value="xx">New module</option>
+<!-- **************************************************************************************************** -->
+<!--!cd ../doc;for i in *.sor; do name=`basename $i .sor | sed "s/_/ – Part /"`; echo "<option value='$name'>$name</option>"; done-->
+<!--!cd ../data;for i in ??.sor ???*.sor; do name=`basename $i .sor | tr "_" " "`; echo "<option value='$name'>$name</option>"; done-->
+<!-- **************************************************************************************************** -->
+ </select>
+ </div>
+</table>
+<table>
+<td valign="top">
+<textarea title="Program" id="def" onkeyup="comp();convert();"></textarea>
+<td valign="top" align="left">
+<textarea id="numbers" title="list" readonly></textarea>
+</table>
+<!-- **************************************************************************************************** -->
+<!--!cd ../doc;for i in *.sor; do echo "<textarea id='`basename $i .sor | sed "s/_/ – Part /"`' class='hidden'>"; cat $i; echo "</textarea>"; done-->
+<!--!cd ../data;for i in ??.sor ???*.sor; do echo "<textarea id='`basename $i .sor | tr "_" " "`' class='hidden'>"; cat $i; echo "</textarea>"; done-->
+<!-- **************************************************************************************************** -->
+<textarea id="xx" class="hidden"></textarea>
+<script type="text/javascript" language="javascript1.3">
+if (navigator.appName.indexOf("Microsoft")!=-1) {
+x = document.body.clientWidth
+y = document.body.clientHeight
+}else{
+x = window.innerWidth
+y = window.innerHeight
+}
+var area1 = document.getElementById('def')
+var area2 = document.getElementById('numbers')
+x = Math.round(x / 2 - x / 90)
+y = Math.round(y - y / 7)
+area1.style.width= x + "px"
+area1.style.height= y + "px"
+area2.style.width= x + "px"
+area2.style.height= y + "px"
+
+document.getElementById('select').value = "Tutorial – Part 1";
+load_prg(); comp(); convert();
+</script>
+</html>
diff --git a/web/index.html.in b/web/index.html.in
new file mode 100644
index 0000000..9f61efd
--- /dev/null
+++ b/web/index.html.in
@@ -0,0 +1,482 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<title>Numbertext.org</title>
+<meta name="description" content="">
+<meta name="author" content="">
+
+<!-- Bootstrap -->
+<link rel="stylesheet" type="text/css" href="css/bootstrap.css">
+<link rel="stylesheet" type="text/css" href="fonts/font-awesome/css/font-awesome.css">
+
+<!-- Stylesheet
+ ================================================== -->
+<link rel="stylesheet" type="text/css" href="css/style.css">
+<link rel="stylesheet" type="text/css" href="css/prettyPhoto.css">
+<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,700,800,600,300' rel='stylesheet' type='text/css'>
+<script type="text/javascript" src="js/modernizr.custom.js"></script>
+
+<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
+<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
+<!--[if lt IE 9]>
+ <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
+ <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
+ <![endif]-->
+</head>
+<body id="page-top" data-spy="scroll" data-target=".navbar-fixed-top">
+<div id="preloader">
+ <div id="status"> <img src="img/preloader.gif" height="64" width="64" alt=""> </div>
+</div>
+<!-- Navigation -->
+<nav class="navbar navbar-custom navbar-fixed-top" role="navigation">
+ <div class="container">
+ <div class="navbar-header">
+ <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-main-collapse"> <i class="fa fa-bars"></i> </button>
+ <a class="navbar-brand page-scroll" href="#page-top"> <i class="fa fa-list-ol"></i> NUMBERTEXT.ORG</a> </div>
+
+ <!-- Collect the nav links, forms, and other content for toggling -->
+ <div class="collapse navbar-collapse navbar-right navbar-main-collapse">
+ <ul class="nav navbar-nav">
+ <!-- Hidden li included to remove active class from about link when scrolled up past about section -->
+ <li class="hidden"> <a href="#page-top"></a> </li>
+ <li> <a class="page-scroll" href="#about">About</a> </li>
+ <li> <a class="page-scroll" href="#services">Download</a> </li>
+ <li> <a class="page-scroll" href="#team">Contributors</a> </li>
+ <li> <a class="page-scroll" href="#testimonials">Spell out numbers</a> </li>
+ <!-- <li> <a class="page-scroll" href="#contact">Contact</a> </li>-->
+ </ul>
+ </div>
+ <!-- /.navbar-collapse -->
+ </div>
+ <!-- /.container -->
+</nav>
+
+<!-- Header -->
+<div id="intro">
+ <div class="intro-body">
+ <div class="container">
+ <div class="row">
+ <div class="col-md-10 col-md-offset-1">
+ <h1><span class="brand-heading"></span>Numbertext.org</h1>
+ <p class="intro-text">Home of Soros Programming Language</p>
+ <a href="#about" class="btn btn-default page-scroll">Learn More</a>
+ <a href="#testimonials" class="btn btn-default2 page-scroll">Spell Out Numbers</a> </div>
+ </div>
+ </div>
+ </div>
+</div>
+<!-- About Section -->
+<div id="about">
+ <div class="container">
+ <div class="section-title text-center center">
+ <h2>About Us</h2>
+ <hr>
+ </div>
+ <div class="row">
+ <div class="col-md-4">
+ <div class="about-text">
+ <!--<iframe width="560" height="315" src="https://www.youtube.com/embed/N9BZ1tCsasw" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>-->
+ <iframe width="350" height="280" src="https://www.youtube.com/embed/N9BZ1tCsasw" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
+ Spelling out numbers and money amounts in LibreOffice Calc
+ </div>
+ </div>
+ <div class="col-md-4">
+ <div class="about-text">
+
+ <h4>From Numbers to Number Names</h4>
+ <p>We provide easy to configure, lightweight open source C++, Java, JavaScript, Python libraries
+ and a LibreOffice Spreadsheet extension for number to number name conversion, including cardinal and
+ ordinal numbers, ordinal indicators and money amounts with currencies in more than 30 languages
+ and numeral systems.</p>
+ <p>Join the Numbertext/LibreOffice development: please, check the Soros language tutorial in the integrated language module development environment, fix bugs or missing parts of the language modules, or create new modules based on the existing ones!</p>
+ </div>
+ </div>
+ <div class="col-md-4">
+ <div class="about-text">
+
+ <h4>Background</h4>
+
+ <p>NUMBERTEXT/MONEYTEXT functions and Soros programming language was developed in 2009 for generalization of BAHTTEXT spreadsheet function, a function of Microsoft Excel for number to Thai number name and currency conversion, standardized by ECMA–376 and ISO/IEC 29 500:2008 Office Open XML format.</p>
+ <p>Soros programming language is based on regular expressions, just like its small interpreters (in Python: less, than 120 lines). Despite its simplicity, it can handle language variants, complex spelling functions and rules in a concise manner.</p>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+<!-- Services Section -->
+<div id="services" class="text-center">
+ <div class="container">
+ <div class="section-title center">
+ <h2>Download</h2>
+ <hr>
+ </div>
+ <div class="space"></div>
+ <div class="row">
+ <div class="col-md-3 col-sm-6">
+ <div class="service"> <i class="fa fa-table"></i>
+ <h3>LibreOffice</h3>
+ <p>Extension with NUMBERTEXT and MONEYTEXT spreadsheet functions: <a href="https://extensions.libreoffice.org/extensions/numbertext-1/1-0-beta/@@download/file/numbertext-1.0b2.oxt">numbertext-1.0b2.oxt</a>
+ (<a href="https://extensions.libreoffice.org/extensions/numbertext-1/1-0-beta">description</a>)</p>
+ </div>
+ </div>
+ <div class="col-md-3 col-sm-6">
+ <div class="service"> <i class="fa fa-cogs"></i>
+ <h3>C++</h3>
+ <p>Source distribution (1.0 beta 2): <a href="https://github.com/Numbertext/libnumbertext/releases/download/1.0.beta2/libnumbertext-1.0.1.tar.xz">libnumbertext-1.0.1.tar.xz</a> (<a href="https://github.com/Numbertext/libnumbertext/releases/tag/1.0.beta2">installation</a>)</p>
+ </div>
+ </div>
+ <div class="col-md-3 col-sm-6">
+ <div class="service"> <i class="fa fa-coffee"></i>
+ <h3>Java</h3>
+ <p>JAR package: <a href="https://github.com/Numbertext/libnumbertext/releases/download/1.0.beta2/numbertext.jar">numbertext.jar</a> (1.0 beta 2).
+ Usage: java -jar numbertext.jar</p>
+ </div>
+ </div>
+ <div class="col-md-3 col-sm-6">
+ <div class="service"><i class="fa fa-pencil"></i>
+ <h3>Python & JavaScript</h3>
+ <p>Interpreters: <a href="https://github.com/Numbertext/libnumbertext/blob/master/src/Soros.py">Soros.py</a> and <a href="https://github.com/Numbertext/libnumbertext/blob/master/src/Soros.js">Soros.js</a>. For usage, see source distribution (<a href="https://github.com/Numbertext/libnumbertext/archive/1.0.beta2.zip">zip</a> or <a href="https://github.com/Numbertext/libnumbertext/archive/1.0.beta2.tar.gz">tar.gz</a>).</p>
+ </div>
+ </div>
+ </div>
+ <div class="space"></div>
+ <div class="row">
+ <div class="col-md-3 col-sm-6">
+ <div class="service"><i class="fa fa-github"></i>
+ <h3>Sources</h3>
+ <p>Repository on GitHub: <a href="https://github.com/Numbertext/libnumbertext">Numbertext/libnumbertext</a></p>
+ </div>
+ </div>
+ <div class="col-md-3 col-sm-6">
+ <div class="service"><i class="fa fa-wrench"></i>
+ <h3>Add a new language</h3>
+ <p>module or fix an old one in the <a href="Soros.html">integrated development environment</a>.</p>
+ </div>
+ </div>
+ <div class="col-md-3 col-sm-6">
+ <div class="service"><i class="fa fa-book"></i>
+ <h3>Soros language</h3>
+ <p><a href="https://github.com/Numbertext/libnumbertext/blob/master/doc/sorosspec.pdf">Specification</a> and
+ <a href="Soros.html">Tutorial</a>.</p>
+ </div>
+ </div>
+ <div class="col-md-3 col-sm-6">
+ <div class="service"><i class="fa fa-bug"></i>
+ <h3>Feedback</h3>
+ <p>Please, use <a href="https://github.com/Numbertext/libnumbertext/issues">GitHub Issues</a> to report problems in code and language data.</p>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+<!-- Team Section -->
+<div id="team" class="text-center">
+ <div class="container">
+ <div class="section-title center">
+<!--!cat ../AUTHORS | awk '/^[^ ].*:/{if(z!=1)print"•";else{print "<p>";z=0};print toupper(gensub("(\\(| at |:).*", "", "g", $0))}/author/{print gensub("^\\s*-.*author of[^A-Z]*(.*) module.*", "(\\1)", "g", $0)}/^=/{print gensub("= (.*) =", "</p><div id='row'><p></p><p></p></div><h2></h2><h2>\\1</h2>", "g");z=1}{next}'-->
+<h2></h2>
+<h2>Donors</h2>
+<p><a href="http://fsf.hu">FSF.hu Foundation</a>, Hungary • <a href="https://nlnet.nl">NLNet Foundation</a>, Netherlands</p>
+
+ </div>
+</div>
+<!-- Testimonials Section -->
+<div id="testimonials" class="text-center" onmouseover="getInputFocus();">
+ <div class="container">
+ <div class="section-title center">
+ <h2 class="input"><span>Spell out number&nbsp;&nbsp;</span><input id='num' onKeyUp='usernum();'>
+<!--</input> in <select id="lang" onChange='usernum();'>
+<option value="-">all languages</option>
+</select>-->
+<span>&nbsp;&nbsp;as&nbsp;&nbsp;</span><select id="money" onChange='usernum();'>
+<option value="-">Cardinal number</option>
+<option value="ordinal">Ordinal number</option>
+<option value="ordinal-number">Ordinal indicator</option>
+<option value="year">Year</option>
+<option value="formal">Formal number</option>
+<option value="def">Default currency</option>
+<option value="CHF">CHF</option>
+<option value="EUR">EUR</option>
+<option value="GBP">GBP</option>
+<option value="JPY">JPY</option>
+<option value="USD">USD</option>
+</select>
+ </h2>
+ </div>
+ <div class="row">
+ </div>
+ <div class="row" id="result">
+ </div>
+ </div>
+</div>
+<!-- Contact Section -->
+
+<!--
+<div id="contact" class="text-center">
+ <div class="container">
+ <div class="section-title center">
+ <h2>Contact us</h2>
+ <hr>
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis sed dapibus leo nec ornare diamcommodo nibh ante facilisis.</p>
+ </div>
+ <div class="col-md-8 col-md-offset-2">
+ <div class="col-md-4">
+ <div class="contact-item"> <i class="fa fa-map-marker fa-2x"></i>
+ <p>4321 California St,<br>
+ San Francisco, CA 12345</p>
+ </div>
+ </div>
+ <div class="col-md-4">
+ <div class="contact-item"> <i class="fa fa-envelope-o fa-2x"></i>
+ <p>info@company.com</p>
+ </div>
+ </div>
+ <div class="col-md-4">
+ <div class="contact-item"> <i class="fa fa-phone fa-2x"></i>
+ <p> +1 123 456 1234<br>
+ +1 321 456 1234</p>
+ </div>
+ </div>
+ <div class="clearfix"></div>
+ </div>
+ <div class="col-md-8 col-md-offset-2">
+ <h3>Leave us a message</h3>
+ <form name="sentMessage" id="contactForm" novalidate>
+ <div class="row">
+ <div class="col-md-6">
+ <div class="form-group">
+ <input type="text" id="name" class="form-control" placeholder="Name" required="required">
+ <p class="help-block text-danger"></p>
+ </div>
+ </div>
+ <div class="col-md-6">
+ <div class="form-group">
+ <input type="email" id="email" class="form-control" placeholder="Email" required="required">
+ <p class="help-block text-danger"></p>
+ </div>
+ </div>
+ </div>
+ <div class="form-group">
+ <textarea name="message" id="message" class="form-control" rows="4" placeholder="Message" required></textarea>
+ <p class="help-block text-danger"></p>
+ </div>
+ <div id="success"></div>
+ <button type="submit" class="btn btn-default">Send Message</button>
+ </form>
+ <div class="social">
+ <h3>Follow us</h3>
+ <ul>
+ <li><a href="#"><i class="fa fa-facebook"></i></a></li>
+ <li><a href="#"><i class="fa fa-twitter"></i></a></li>
+ <li><a href="#"><i class="fa fa-dribbble"></i></a></li>
+ <li><a href="#"><i class="fa fa-github"></i></a></li>
+ <li><a href="#"><i class="fa fa-instagram"></i></a></li>
+ <li><a href="#"><i class="fa fa-linkedin"></i></a></li>
+ </ul>
+ </div>
+ </div>
+ </div>
+</div>
+-->
+<div id="footer">
+ <div class="container">
+ <p>Copyright &copy; Numbertext.org. Designed by <a href="http://www.templatewire.com" rel="nofollow">TemplateWire</a>.
+ Cover Photo: <a href="https://commons.wikimedia.org/wiki/File:Tablet_with_Cuneiform_Inscription_LACMA_M.79.106.2_(2_of_4).jpg">Wikipedia Commons</a></p>
+ </div>
+</div>
+
+<!-- Numbertext data -->
+<!-- **************************************************************************************************** -->
+<!--!cd ../data;for i in ??.sor ???*.sor; do echo "<textarea id='`basename $i .sor | tr "_" " "`' class='hidden'>"; cat $i; echo "</textarea>"; done-->
+<!-- **************************************************************************************************** -->
+<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
+<script type="text/javascript" src="js/jquery.1.11.1.js"></script>
+<!-- Include all compiled plugins (below), or include individual files as needed -->
+<script type="text/javascript" src="js/bootstrap.js"></script>
+<script type="text/javascript" src="js/SmoothScroll.js"></script>
+<script type="text/javascript" src="js/jquery.prettyPhoto.js"></script>
+<script type="text/javascript" src="js/jquery.isotope.js"></script>
+<script type="text/javascript" src="js/jquery.parallax.js"></script>
+<script type="text/javascript" src="js/jqBootstrapValidation.js"></script>
+<script type="text/javascript" src="js/contact_me.js"></script>
+
+<!-- Javascripts
+ ================================================== -->
+ <script type="text/javascript" src="js/main.js"></script>
+<!-- **************************************************************************************************** -->
+<!--!cd ../data;for i in *.sor; do echo "<textarea rows='0' cols='0' id='`basename $i .sor`' class='hidden'>"; cat $i; echo "</textarea>"; done-->
+<!-- **************************************************************************************************** -->
+<script language="javascript1.3">
+
+function getInputFocus() {
+ if (!window.inputFocused) {
+ window.inputFocused = true;
+ document.getElementById('num').focus();
+ }
+}
+
+<!-- **************************************************************************************************** -->
+<!--!cat ../src/Soros.js-->
+<!-- **************************************************************************************************** -->
+
+var keep = this
+
+language = {
+"af": "Afrikaans",
+"ca": "Català",
+"cs": "Česky",
+"da": "Dansk",
+"de": "Deutsch",
+"de-CH": "Deutsch&nbsp;(CH)",
+"el": "Ελληνικά",
+"en": "English",
+"en-GB": "English&nbsp;(GB)",
+"en-IN": "English&nbsp;(IN)",
+"es": "Español",
+"eo": "Esperanto",
+"fr": "Français",
+"fr-BE": "Français&nbsp;(BE)",
+"fr-CH": "Français&nbsp;(CH)",
+"he": "עברית",
+"hr": "Hrvatski",
+"hu": "Magyar",
+"id": "Bahasa Indonesia",
+"it": "Italiano",
+"ja": "日本語",
+"ja_JP_2": "大字",
+"ko": "한국어&nbsp;(KR)",
+"ko-KP": "한국어&nbsp;(KP)",
+"lb": "Luxembourgish",
+"lt": "Lietuvių",
+"lv": "Latviešu",
+"ms": "Bahasa Melayu",
+"nl": "Nederlands",
+"pl": "Polski",
+"pt": "Português",
+"pt-BR": "Português&nbsp;(BR)",
+"ro": "Română",
+"ru": "Русский",
+"sl": "Slovenščina",
+"fi": "Suomi",
+"sh": "Srpski",
+"sr": "Српски",
+"sv": "Svenska",
+"th": "ไทย",
+"tr": "Türkçe",
+"zh": "中文",
+"vi": "Tiếng Việt",
+"zh": "大写",
+"Hung": "𐲭𐲨𐲹𐲽𐲯𐲿𐲭𐲽𐲯*",
+"Roman-large": "Roman*",
+"Suzhou": "花碼*"
+}
+
+default_currency = {
+"af": "ZAR",
+"ca": "EUR",
+"cs": "CZK",
+"de": "EUR",
+"de-CH": "CHF",
+"da": "DKK",
+"el": "EUR",
+"en-GB": "GBP",
+"en-IN": "INR",
+"en": "USD",
+"es": "EUR",
+"eo": "-",
+"fr": "EUR",
+"fr-BE": "EUR",
+"fr-CH": "CHF",
+"id": "IDR",
+"it": "EUR",
+"ja": "JPY",
+"ko-KP": "KPW",
+"ko": "KRW",
+"lb": "EUR",
+"lt": "LTL",
+"lv": "LVL",
+"ms": "MYR",
+"he": "ILS",
+"hu": "HUF",
+"hr": "HRK",
+"nl": "EUR",
+"pl": "PLN",
+"pt": "EUR",
+"pt-BR": "BRL",
+"ro": "RON",
+"ru": "RUB",
+"sl": "EUR",
+"fi": "EUR",
+"sv": "SEK",
+"th": "THB",
+"tr": "TRY",
+"vi": "VND",
+"zh": "CNY",
+"Roman": "-",
+"Rovas": "-",
+"Suzhou": "CNY"
+}
+
+numlang=[]
+
+<!-- **************************************************************************************************** -->
+<!--!cd ../data;for i in *.sor; do name=`basename $i .sor`; echo "numlang['$name']=new Soros(document.getElementById('$name').value, '$name')"; done-->
+<!-- **************************************************************************************************** -->
+numlang['de-CH']=new Soros(document.getElementById('de').value, 'de-CH');
+numlang['en-GB']=new Soros(document.getElementById('en').value, 'en-GB');
+numlang['en-IN']=new Soros(document.getElementById('en').value, 'en-IN');
+numlang['fr-BE']=new Soros(document.getElementById('fr').value, 'fr-BE');
+numlang['fr-CH']=new Soros(document.getElementById('fr').value, 'fr-CH');
+numlang['ko-KP']=new Soros(document.getElementById('ko').value, 'ko-KP');
+numlang['pt-BR']=new Soros(document.getElementById('pt').value, 'pt-BR');
+numlang['Roman-large']=new Soros(document.getElementById('Roman').value, 'Roman-large');
+
+window.header = ""
+window.num = ""
+window.time = setTimeout("tim()", 1000);
+window.startDemo = true;
+
+window.currency = document.getElementById('money').value
+
+/*
+if (navigator.appName.indexOf("Microsoft")!=-1) {
+window.width = document.body.clientWidth
+window.height = document.body.clientHeight
+}else{
+window.width = window.innerWidth
+window.height = window.innerHeight
+}*/
+
+function usernum() {
+ clearTimeout(window.time)
+ window.num = document.getElementById('num').value
+ window.currency = document.getElementById('money').value
+ if (window.num != undefined && window.num != "") {
+ window.header = "x"
+ } else {
+ window.header = ""
+ }
+ tim()
+}
+
+function tim( ) {
+ var b = new Date()
+ var header = ""
+ if (window.header == "") {
+ window.num = Math.round(b.getTime()/1000) + ""
+ header = "Unix time in sec (" + num + ")"
+ window.time = setTimeout("tim()", 1000);
+ } else header = "Number (" + window.num + ")"
+ target = document.getElementById('result')
+ if (document.body.scrollTop < target.offsetTop + target.offsetHeight) target.innerHTML = "<table id='conv' width='100%'><tbody><tr id='header' style='text-align:left;background-color:rgba(100%, 100%, 100%, 0)'><td width='150px'>Language<td>" + header + "</td></tr>" +
+<!-- **************************************************************************************************** -->
+<!--!cd ../data; n=3; for i in `ls *.sor | awk '{print}/de/{print"de-CH.sor"}/en/{print"en-GB.sor\nen-IN.sor"}/pt/{print"pt-BR.sor"}/ko/{print"ko-KP.sor"}/fr/{print"fr-BE.sor\nfr-CH.sor"}' | grep -v ^[A-Z]` Hung.sor Roman-large.sor Suzhou.sor; do name=`basename $i .sor`; name2=`echo $name | tr _ -`; head=""; rtl=""; rovas=""; case $name in Hung) rovas="rovas"; rtl="align='right'";; he) rtl="align='right'";; esac; echo "\"$head<tr class='$rovas \"+ ($n%2?\"second\":\"\")+\"' style='text-align:left;' title='$name2'><td valign='top'>\" + language[\"$name\"] + \"</td><td $rtl>\" + numlang['$name'].run((window.currency == \"-\" ? \"\" : (window.currency == \"def\" ? default_currency[\"$name\"] : window.currency) + \" \") + window.num).replace(\"\\\n\",\"<br>\") + '</td></tr>' +";n=`echo $n+1 | bc`; done-->
+<!-- **************************************************************************************************** -->
+ "<tr><td colspan=2>*Old numeral systems (extended for large numbers) &ndash; Old Hungarian, Roman and Suzhou numerals</td></tr></tbody></table>";
+}
+tim()
+</script>
+</body>
+</html>
diff --git a/web/webroot/css/numbertext.css b/web/webroot/css/numbertext.css
new file mode 100644
index 0000000..6c799aa
--- /dev/null
+++ b/web/webroot/css/numbertext.css
@@ -0,0 +1,108 @@
+body {
+ margin: 0pt;
+ background-color: white;
+ font-family: "Verdana", "Tahoma", "Helvetica";
+}
+div#result {
+ border-style: solid;
+ border-width: 1px;
+ border-color: black;
+}
+div#header {
+ border-style: solid;
+ border-width: 0px 0px 1px 0px;
+ background-color: rgb(80%,60%,60%);
+}
+.hidden {
+ visibility:hidden;
+}
+.nowrap {
+ white-space: nowrap;
+ padding: 0;
+ border: 0;
+}
+.baseline {
+ vertical-align: baseline;
+}
+.title {
+ padding: 1pt;
+ padding-left: 5pt;
+ padding-right: 5pt;
+ background-color: white;
+}
+.big {
+ font-size: 24pt;
+ font-weight: bold;
+ padding-right: 5pt;
+}
+.menu {
+ padding-right: 5pt;
+}
+.menu2 {
+ padding-left: 5pt;
+}
+.row {
+ padding: 1pt;
+ padding-left: 5pt;
+ white-space: nowrap;
+}
+.lang {
+ width: 75pt;
+ display: inline-block;
+ text-align: left;
+}
+.input {
+ padding: 1pt;
+ padding-left: 5pt;
+ background-color: rgb(83%,65%,65%);
+}
+img {
+ border-width: 0px;
+/* border-style: solid; */
+}
+a:hover img {
+ border-color: black;
+}
+a:visited img {
+ border-color: white;
+}
+table.logos td {
+ padding-left: 5px;
+ padding-right: 5px;
+ text-align: center;
+}
+tr.text td {
+ padding: 5pt;
+}
+@font-face {
+ font-family: Hung;
+ src: url("../fonts/fonts/Hung.ttf") format("truetype");
+}
+.rovas {
+ font-family: Hung;
+ width: 100%;
+}
+table#conv {
+ width: 100%;
+ border-spacing: 0px;
+ border-collapse: collapse;
+}
+table#conv tr {
+ margin: 0px;
+}
+table#conv td {
+ margin: 0px;
+ padding: 2pt;
+ padding-left: 5pt;
+ padding-right: 5pt;
+ border-width: 0px;
+ border-style: solid;
+ white-space: nowrap;
+}
+
+table#conv td.sep {
+ border-width: 1px 0px 0px 0px;
+ border-color: black;
+ border-style: solid;
+}
+
diff --git a/web/webroot/favicon.ico b/web/webroot/favicon.ico
new file mode 100644
index 0000000..10c1683
--- /dev/null
+++ b/web/webroot/favicon.ico
Binary files differ
diff --git a/web/webroot/fonts/fonts/Hung.ttf b/web/webroot/fonts/fonts/Hung.ttf
new file mode 100644
index 0000000..40c35d8
--- /dev/null
+++ b/web/webroot/fonts/fonts/Hung.ttf
Binary files differ