Zemberek Turk Dili gelistirici belgesi
Zemberek kutuphanesi, uzerinde farkli Turk dillerinin calisabilmesine uygun bir yapida gelistirilmistir. Bu belgede yeni bir Turk dili icin yazim denetimi, oneri sistemi ve ascii donusturme islemlerinin cekirdek kutuphane uzerinden nasil gerceklestirilebilecegi basitce anlatilmaya calisilacaktir. Gecekleme tam olarak yapilmayip sadece yol gosterme amaciyla temel sinifi olusumlari ve bilgiler eklenecektir. Dil olarak Turkiye Turkcesi'ne en cok benzeyen Azerbaycan Turkcesi (ya da Azerice) secilmistir. Azerbaycan Turkcesine iliskin temel bilgilere http://tr.wikipedia.org/wiki/Azerice adresinden erisebilirsiniz.
Proje dizin yapisi hakkinda genel bilgi.
Bir dili gerceklemeye baslamadan once proje dizin yapisini tanimakta fayda var. Asagidaki ekran goruntusunde genel dizin yapisi gosterilmistir. Dizin isimlerinin bir kisminda genel Java yazilim gelistirme aliskanliklari goz onunde bulunduruldugundan ingilizce kisaltmalar kullanilmistir. Temel dizinler ve anlamlari sunlardir:
1- src: Yazilim icindeki tum kaynak kodlar bu dizin altinda bulunur. Bu dizin altinda mavi ile isaretli dizinler su kaynak kodlari tasir. Cekirdek icerisinde ana zemberek kutuphane kaynak kodu yer alir. tr, tm ve yeni olusturdugumuz az dizinlerinde sirasiyla Turkce, turkmence ve Azerice Turk dillerine ozgu kaynak kodlar yer alir. demo dizininde ise islemlerin ust seviye testi icin basit bir arayuz kodu bulunmaktadir.
2- kaynaklar: farkli dillere iliskin bilgi dosyalari bu dizinde yer alir. az/bilgi dizini altinda Azerice kelime kokleri ve ek bilgilerini tasiyan xml dosyasi yer alacak.
3- lib: burada gelistirme aninda kullanilabilecek bazi dis kutuphaneler yer alir. Su an temel islemler icin calisma aninda hic bir dis kutuphaneye ihtiyac duyulmamaktadir.
4- test: Burada ise test siniflari yer almaktadir. Dile gore yeni bir dizin altinda testler yer alacaktir. genellikle yazilan her sinifi icin bir de test sinifinin yazilmasi iyi bir yazilim gelistirme aliskanligi olarak bilinir.
Paket yapisi
Proje paket yapisi konusunda farkli yollar izlenebilir. Cekirdek kutuphane paket yapisi net.zemberek adi ile baslamaktadir. Yani cekirdek kutuphane siniflari net.zemberek.yapi.Kelime , net.zemberek.islemler.Heceleyici gibi isimlere sahiptir. Dile ozel siniflarin paket yapisi konusunda bir sinirlandirma yapilmamistir. Yani Azerice'ye iliskin siniflar gelistirme isini yapanlarin istegine gore farkli bir paket yapisina sahip olabilir. Ancak benzerligi korumak icin bu belgede net.zemberek.az ana paket yapisini kullanilmasi yeglendi. Temel paket dizin yapisi asagidaki sekildedir:
istenilirse takip edilecek baska bir paket yaklasimi da cekirdek ile ayni yapiyi kullanmaktir. Yani az dizini altinda da cekirdek dizin yapisi aynen taklit edilir. Bu sayede ayni paketteki siniflarin birbirini gorme ozelliginden faydalanilmis olur. Bu yaklasimin goturusu ise azericeye ozel sinif isimlerinin cekirdekteki ayni paketteki sinif isimlerinde farkli olmasi gerekir. Bu ornekte bu nedenle onceki yaklasim tercih edildi. Tabiki tamamen ilgisiz "azeri.dil" gibi bir ana paket adi da kullanilabilirdi. Sonucta azerica icin src dizini altinda az/net/zemberek/az ve onun altinda islemler, yapi/ek ve yapi/kok dizinleri olusturuldu. ileride bu dizinlere dile ozel siniflar yerlestirilecek.
Alfabe
Turk dilleri dunya uzerinde genellikle uc ana grupta alfabe kullanmakta. Turkiye, Turkmen, Azeri, Ozbek, Tatar Turkceleri Latin, Kazak, Kirgiz, Baskirt ve Cavus Turkceleri Kril, Uygurca ise Arap alfabesi kullaniyor. Latin alfabesi gercekleme ve gelistirici katilimi acisindan kolayliklar sagladigindan baslangicta bu alfabe yapisini kullanan dillerin gerceklenecegini umuyoruz. Kril alfabesinde de tipki latin lafabesi gibi her sese karsilik bir simge karsilik dustugunden uygulamada ciddi sorunlar cikacagini sanmiyoruz. Latin alfabesi kullanan turk dilleri de kendi iclerinde farkliliklar tasimaktadir. Bu nedenle her dile ozgi harf bilgilerinin tasindigi bir dosya harf_[iso dil kodu].txt formatinda ilgili kaynaklar/[iso dil kodu]/bilgi diizni altinda yer almaz zorundadir. Azerice icin Tipik bir harf bilgi dosyasi harf_az.txt asagidaki gibi olabilir:

harfler=a,b,c,ç,d,e,ə,f,g,ğ,h,x,ı,i,j,k,q,l,m,n,o,ö,p,r,s,ş,t,u,ü,v,y,z,â,î,û,w,.,-,'," sesli=a,e,ə,ı,i,o,ö,u,ü ince-sesli=e,ə,i,ö,ü duz-sesli=a,e,ə,ı,i yuvarlak-sesli=o,ö,u,ü sert=f,s,t,k,ç,ş,h,p ascii-disi=ç,ə,ğ,ı,ö,ş,ü ascii-turkce=c-ç,g-ğ,i-ı,I-İ,e-Ə,o-ö,s-ş,u-ü,â-a,î-i,û-ü yumusama-donusum=ç-c,g-ğ,k-ğ,p-b,t-d ayiklama=.,-,'," ayiklama-donusum=â-a,î-i,û-ü

Azeri alfabesinde su farkli karakterler yer alir: Əə, Çç, Ğğ, ı, İ, Öö, Şş, Üü
Bu karakterlerin char karsiliklarina istenirse Alfabe sinifindan Alfabe.CHAR_ii , Alfabe.CHAR_ee seklinde erismek mumkundur. Eger ekleyeceginiz turk dili icerisnde yeni ingilizce tus takimi disi karakterler yer aliyorsa bunlari benzer sekilde Alfabe sinifina ya da ayri bir sinifa ekleyebilirisniz. Karakterlerin unicode karsiliklari internetteki cesitli tablolardan elde edilebilir (http://unicode.coeurlumiere.com/ gibi).
Zemberek icerisinde harflere sadece char degil ozellikle cozumleme gibi islemler sirasinda TurkceHarf nesnesi olarak erisilir. TurkceHarf nesnesinden biraz bahsetmekte yarar var. Zemberek icerisindeki en alt seviye nesnelerden birisi TurkceHarf nesnesidir. Temelde amaci turkce harfe iliskin ince, kalin, dar , yuvarlak, sesli, sert gibi cesitli bilgileri uzerinde tasimaktir. TurkceHarf nesnesi ile calismak turkceye ozgu islemeler sirasinda kolaylik saglamaktadir. Normalde harflere ozel bilgiler Alfabe sinifi icerisindeki ozel tablolar uzerinden de saglanabilirsi ancak nesneye yonelik programamaya daha elverisli oldugunu dusundugumuzden harflere ozellikleri baglamayi baslangicta daha uygun bulduk.
Kokler
Zemberek kok listesi tabanli bir yapiya sahiptir. Yani kelime cozumleme isleminin basari ile tamamlanabilmesi icin dildeki kelime koklerinin biliniyor olmasi gerekir. Bu nedenle her dil icin kok bilgisinin olusturulmasi gerekir. Kok bilgisinin girilmesi icin cok basit bir duz yazi dosya yapisi kullanilmaktadir. Bunun nedeni bu dosya uzerinde el ile oynama yapmanin kolay olmasidir. Ileride iliskisel ya da nesne veri tabani uzerinden gelistirilen bir yapi kullanilmasi dusunulebilir.
Azerice kokleri kaynaklar/az/bilgi dizininde kokler.txt dosyasinda tanimlayalim. Kok dosya kodlamasi olarak utf-8 kullanilmasi gerekir, aksi halde farkli isletim sistemi - IDE kombinasyonlarinda problemler ortaya cikabilir. Dosyanin icerisindeki koklerin tnaimlanmasinda uyulmasi gereken kurallar:
- Her kok tek satirda yazilir.
- Her kokun bir tipi olmasi gerekir (isim, fiil, zamir, sayi vs..). Tip bilgisi kok iceriginin yanina yazilir. Tip belirtme kelimesinin nasil olacagi gene dil gelistiricisi tarafindan belirlenir. TurkiyeTurkcesi icin "IS, FI, ZA, ZAMAN, SA..." gibi kelimeleri kullanilmistir.
- Belirtilen kok icin bir ya da daha fazla ozel durum olabilir. bu ozel durumlari gene belirtici bir kelime ile tip bilgisinden sonra girilmesi gerekir. Ozel durum belirten simgenin ne oldugu da dil gelistiricisi tarafindan bleirlenir. (Turkiye Turkcesi icin YUM, DUS.. vs. )
- islenmesi istenmeyen satirlarin basina # isareti koyulur.
Asagida ornek bazi kokler gosterilmistir.

su AD sağlıq AD YUM al EY gel EY tuz AD #biber -> istiot istiot AD et AD balıg AD meyve AD bir RA iki RA üç RA dörd RA dünen ZAMAN sabah ZAMAN ahşam ZAMAN

Bu sekilde tum kokler tanimlanir. Goruldugu gibi Turkiye Turkcesinden farkli olarak kok tiplerini tanimlamada "AD, EY, RA, ZAMAN" secildi. Elbette bunlarin yerine gercek azerice kelime kisaltmalari da koyulabilir. Kok tiplerini tanimlarken sifat tipi yerine baslangicta isim kullanilabilir.
goruldugu gibi yapilan is bir Map nesnesi olusturulup icerisine kok dosyasinda kullanilan kok tip adlarinin "KelimeTipi" sinifidaki asil dil bilgisi esleniklerine karislik dustugu belirleniyor. Bu sinif duz yazi kok dosyasinin okunmasi sirasinda kullanilacak.
Kok listesinde alfabetik siraya uyulmasi sonradan ekleme ve cikarma yapacaklar icin faydali olacaktir. Istenilirse fiiller icin koklere mastar eki eklenebilir, ancak bu durumda bu ekin okuma sirasinda temizlenmesi gerekir (ornek kodu TurkceKokOzelDurumBilgisi sinifindaki kokIcerikBelirle metodunda gorebilirsiniz.). Koklerin okunmasi ve kok ozel durumlarina birazdan devam edecegiz.
Ekler
Farkli Turk dillerinin kutuphane uzerinden gerceklenmesindeki en zorlayici yerlerden birisi ek bilgilerinin girilmesidir. Ekler ozel yapidaki bir xml dosyasinda tanimlanir. kaynaklar/az/bilgi dizininde ek_az.xml dosyasini uretelim. Dosya iki ana kisimdan olusur. ek kume tanimlamasi ve ek tanimlamasi.

    <?xml version="1.0" encoding="UTF-8" ?>

    <ek-bilgisi>

        <!-- ek kumeleri -->
        <ek-kumeleri>

            <ek-kumesi ..."/>
            <ek-kumesi ..."/>

            ....

        </ek-kumeleri>

        <!-- ekler -->
        <ekler>

            <ek .... />
            <ek .... />

            ....

        </ekler>

    </ek-bilgisi>

Xml etiket (tag) ve ozellik (attribute) isimlerinin Turkiye Turkcesindekilerle ayni olmasi gerekir.
Ek kumeleri ek tanimlamalarinda kolaylik saglamasi amaciyla kullanilir. Asil onemli olan kisim ek tanimlamasi oldugundan o kisma agirlik verilecektir. Ekler kendi icinde farkli alanlara sahiptir. En basit anlamd bir ek tanimlamasi asagidaki gibi olabilir.

            <!-- isim cogul eki _ler. "qız_lar.." -->
            <ek ad="AD_COGUL_LER" uretim="lAr">
            </ek>

ek icerisindeki "ad" ve "uretim" mecburi alanlardir. Ek adini kullanirken dile ozel isimler kullanilabilir. Nitekim Turkmencede ayni ek icin "AT_KOPLUK_LER" adi tercih edilmistir. Bununla birlikte su tur bir isimlendirme onerilir: "kok tipi + ek adi + ekin kullanilisi" ekin kullanilisi Turkiye turkcesi icin isimlerde "sey" kokune eklenilmesi ile olusan halidir.
Ikinci onemli ozellik ise "uretim" bilgisidir. "lAr" ile belirtilen uretim bilgisi bir ekin nasil uretilecegini ifade eder. uretim kurallari gene dilden dile farkliliklar gosterebilir, ancak cozgu zaman Turk dillerinde benzer kurallar mevcut oldugundan genellikle buyuk degisiklikler yapmak gerekmemektedir. Turkiye turkcesi icin ek uretim kurallari su sekildedir:

A:son seslinin ince_kalin olmasina gore a ya da e harfi uretilir. I:son seslinin durumuna gore i,ı,u ya da ü uretilir. +x: son harf sesli ise x harfi (ya da kural ise ilgili harfler) eklenir. >x: son harf sert ise gore x harfinin sert hali kullanilir. kucuk harfler: dogrudan uretime eklenir.

Ornegin "?y+(A)" ek uretim kelimesi bu ekin sesli ile biten bir kelimeye eklendiginde "y" harfi ile baslayacagi ve sonraki ek harfinin kelimenin son seslisi ince ise "e" degil ise "a" olacagi anlamina gelir. Bu ek {e,a,ye,ya} seklinde olusabilir.
Azerice icin ise bu kurallarda cok kucuk bir kac degisiklik gerektigini fazredelim. Ornegin son kurali isletmeyelim, yani dogrudan Azeri alfabesi karakterlerini ek dosyasinda kullanalim (ek dosyasi utf-8 oldugundan bu bir soruna yol acmaz.). Bu konuya daha sonra tekrar donecegiz,
Simdi bir kac tane daha ek olusturalim (turkce ek dosyasindan kopyalayip)

            <!-- ad cogul eki _ler. "qýz_lar.." -->
            <ek ad="AD_COGUL_LER" uretim="lAr">
                <ardisil-ekler>
                    <aek>AD_YONELME_E</aek>
                    <aek>AD_KALMA_DE</aek>
                </ardisil-ekler>
            </ek>

            <!-- cegiz: "kedi_ceGiz -->
            <ek ad="AD_KUCULTME_CEGIZ" uretim="cAğIz">
                <ardisil-ekler>
                    <aek>AD_COGUL_LER</aek>
                    <aek>AD_YONELME_E</aek>
                    <aek>AD_KALMA_DE</aek>
                </ardisil-ekler>
            </ek>

            <!-- isim yonelme : "kedi_ye bak"  -->
            <ek ad="AD_YONELME_E" uretim="+yA"/>

            <!-- isim kalma : "ev_de yemek var."  -->
            <ek ad="AD_KALMA_DE" uretim=">dA"/>

Bu defa sisteme uc yeni ek ekledik ve bir degisiklik yapip cogul eki icine <ardisil-ek> bilgisi eklendi. Ardisil ek bilgisi kelime cozumlemenin temelini olusturur. Yani her ek kendi icinde kendinden sonra gelebilecek eklerin bir listesini tasir.
Ardisil ekler uc sekilde belirlenebilir.
- <aek> etiketi icinde tek ek adi yazilarak
- ek kumesleri olusturulursa <kume> etiketi icinde ek kume adi yazilarak
- dogrudan baska bir ekin tum ardisil ekleri "kopya-ek" ozelligine kopyalanacak ekin adi eklenerek. Asagida tum sekilleri gosteren bir ornek verilmistir.

            <ek ad="AD_TEST_EK" uretim="lAr">
                <ardisil-ekler  kopya-ek="ISIM_ANDIRMA_IMSI" >
                    <kume>AD_SAHIPLIK</kume>
                    <aek>AD_YONELME_E</aek>
                    <aek>AD_KALMA_DE</aek>
                </ardisil-ekler>
            </ek>

su anda sadece tek ek ardisil ek belirleme ozelligini kullaniyoruz.
Baslangic ekleri: zemberek icerisinde tanimlanmasi gereken bir ek turu baslangic ekleri. Bu ekler belli bir kok tipinden sonra gelebilecek ekler icin baslangic noktasi temsil ediyorular. TurkiyeTurkcesi ek belirtme dosyasinda her bir (cogu demek daha dogru) kok tipi icin bir de baslangic eki tanimlanmistir. Bu ekin ardisil ekleri yalin bir koke eklenebilecek ekleri temsil eder. Biz de azeri ek tanimlama dosyasina bu ekin bir benzerini, ama farkli bir ad ile olusturalim..

            <!-- ad baslangic. -->
            <ek ad="AD_BASLANGIC_BOS" uretim="">
                <ardisil-ekler>
                    <aek>AD_COGUL_LER</aek>
                    <aek>AD_YONELME_E</aek>
                    <aek>AD_KALMA_DE</aek>
                    <aek>AD_KUCULTME_CEGIZ</aek>
                </ardisil-ekler>
            </ek>

Bu sekilde en temel ek bilgisi dosyasini uretmis olduk. Simdilik sadece bes tane ek var ve ozel durumlar henuz sistemde yer almiyor. Bu ekler sistem tarafindan okunduktan sonra cesitli islemlerden gecirilirler. Ornegin ek uretim kural kelimeleri cekirdekteki EkKuralCozumleyici icerisinde cozumlenip kurallar EkUretimBileseni listesi haline getirilir. EkUretimBileseni nesnesi icerisinde bir adet TurkceHarf ve EkUretimKurali enum degeri tasir.

    /**
     * uretim bilesen sinifi, uretim kural kelimesindeki bilesenleri temsil eder.
     * degistirilemez, thread safe.
     *
     */
    public class EkUretimBileseni {

        private final EkUretimKurali kural;
        private final TurkceHarf harf;

    .....

EkUretimKurali bir enumerasyon yapisidir, yani icerisinde sabit degerler tasir. Su anda icerisinde Turk Dilleri icinde olabilecek cesitli kirallar mevcuttur. Gerekirse yenilerinin ihtiyaca gore eklenmesi mumkundur.

    /**
     * Turk dilleri icin uretim kurallarini belirler. Bazi kurallar sadece belli dillerde
     * kullanilir.
     */
    public enum EkUretimKurali {
            SESLI_AE,
            SESLI_AA,
            SESLI_IU,
            SESSIZ_Y,
            SERTLESTIR,
            KAYNASTIR,
            HARF
    }

Bu kurallarin nasil isletilecegi ise gene dil gelistiricisi tarafindan belirlenir. Bu konuyu anlamak icin Ek uretim islemini gozden gecirelim.
Ek uretici
Her dil icin ek uretimi farkli bir yapida olaiblir. Bu nedenle EkUretici arayuzune sahip bir sinifa ihtiyacimiz var. Bu arayuzun yapisi asagidaki gibidir.

     1 public interface EkUretici {
     2
     3     /**
     4      * Kelime Cozumleme islemi icin ek uretimi.
     5      * @param ulanacak
     6      * @param giris
     7      * @param bilesenler
     8      * @return uretilen ek, HarfDizisi cinsinden.
     9      */
    10     HarfDizisi cozumlemeIcinEkUret(HarfDizisi ulanacak,
    11                                    HarfDizisi giris,
    12                                    List<EkUretimBileseni> bilesenler);
    13
    14     /**
    15      * Kelime uretimi icin ek uretimi.
    16      * @param ulanacak
    17      * @param sonrakiEk
    18      * @param bilesenler
    19      * @return uretilen ek, HarfDizisi cinsinden.
    20      */
    21     HarfDizisi olusumIcinEkUret(HarfDizisi ulanacak,
    22                                 Ek sonrakiEk,
    23                                 List<EkUretimBileseni> bilesenler);
    24
    25     /**
    26      * Ek bilesenlerini kullarak bir ekin hangi harflerle baslayacagini kestirip sonuclari
    27      * bir set icerisinde dondurur.
    28      * @param bilesenler
    29      * @return olasi baslangic harfleri bir Set icerisinde.
    30      */
    31     Set<TurkceHarf> olasiBaslangicHarfleri(List<EkUretimBileseni> bilesenler);
    32 }

EkUreticiAz sinifini net.zemberek.az.yapi.ek paketinde olusturalim. simdilik icindeki metodlar bos. Bu sinif icinde azerice bir ekin nasil uretilecegini yazmamiz gerekiyor.

      1 public class EkUreticiAz implements EkUretici {
      2
      3     private AzericeSesliUretici sesliUretici;
      4
      5     public EkUreticiAz(Alfabe alfabe) {
      6         this.sesliUretici = new AzericeSesliUretici(alfabe);
      7     }
      8
      9     public HarfDizisi cozumlemeIcinEkUret(HarfDizisi ulanacak,
     10                                           HarfDizisi giris,
     11                                           List<EkUretimBileseni> bilesenler) {
     12         HarfDizisi sonuc = new HarfDizisi();
     13         TurkceHarf sonSesli = ulanacak.sonSesli();
     14         for (int i = 0; i < bilesenler.size(); i++) {
     15             EkUretimBileseni ekUretimBileseni = bilesenler.get(i);
     16             final TurkceHarf harf = ekUretimBileseni.harf();
     17             switch (ekUretimBileseni.kural()) {
     18                 case HARF:
     19                     sonuc.ekle(harf);
     20                     break;
     21                 case KAYNASTIR:
     22                     if (ulanacak.sonHarf().sesliMi())
     23                         sonuc.ekle(harf);
     24                     break;
     25                 case SERTLESTIR:
     26                     if (ulanacak.sonHarf().sertMi())
     27                         sonuc.ekle(harf.sertDonusum());
     28                     else
     29                         sonuc.ekle(harf);
     30                     break;
     31                 case SESLI_AE:
     32                     if (i == 0 && ulanacak.sonHarf().sesliMi())
     33                         break;
     34                     else {
     35                         sonSesli = sesliUretici.sesliBelirleAE(sonSesli);
     36                         sonuc.ekle(sonSesli);
     37                     }
     38                     break;
     39                 case SESLI_IU:
     40                     if (i == 0 && ulanacak.sonHarf().sesliMi())
     41                         break;
     42                     else {
     43                         sonSesli = sesliUretici.sesliBelirleIU(sonSesli);
     44                         sonuc.ekle(sonSesli);
     45                     }
     46                     break;
     47             }
     48         }
     49         return sonuc;
     50     }
     51
     52     public HarfDizisi olusumIcinEkUret(HarfDizisi ulanacak,
     53                                        Ek sonrakiEk,
     54                                        List<EkUretimBileseni> bilesenler) {
     55         //TODO: gecici olarak bu sekilde
     56         return cozumlemeIcinEkUret(ulanacak, null, bilesenler);
     57     }
     58
     59     public Set<TurkceHarf> olasiBaslangicHarfleri(List<EkUretimBileseni> bilesenler) {
     60         return null;
     61     }

koda biraz goz gezdirilirse ne yaptigini anlamak cok zor degil. cozumlemeIcinEkUret metodu kelime cozumleme islemi sirasinda kullanilir. Temelde elimizde ekin ulancagi kelime (ulanacak), cozumleme yapidigina gore cozumlesi yapilan kelime (giris), ve ekin uretim bilesenleri listesi (bilesenler) mevcut. Gercek bir ornek vermek gerekirse, "meyvelere" kelimesi giris, cozumleme sirasinda elimizdeki kelime "meyve" ve cogul eki uretimi icin gerekli uretim bilesenleri ({HARF,l}, {SESLI_AE}, {HARF,r}) metod icerisinde elimizde hazir vaziyette. Once ulancak kelimenin son seslisi bulunuyor ('meyve' icin 'e'). Daha sonra sirasi ile uretim bilesenleri taraniyor. bilesn icindeki kurala gore yapilamsi gerken islem belirleniyor. ornegin ilk kural 'HARF'. bu durumda sonuc ek olusumuna ilgili harf yani 'l' dogrudan ekleniyor. ikinci kural 'SESLI_AE' bu durumda AzericeSesliUretici adindaki bir sinifin sesliBelirleAE metodu cagriliyor. Bu sinif Turk dillerindeki sesli uretim kurallarini uygulamada yardimci olmak amaciyla uretilmistir. Bu sinifi yazmadan once AzericeAlfabe sinifina kucuk bir ekleme yapiyoruz. TurkceHarf cinsinden sesli harflere kolay erisim saglamak amaciyla sesli harflerin TurkceHarf karsiliklarini alfabe tanimlamasindan hemen once sabit olarak ekliyoruz. Sadece kucuk harfleri tanimlamak yeterli.

        public static final TurkceHarf HARF_a = harfler.get('a');
        public static final TurkceHarf HARF_ee = harfler.get(CHAR_ee);
        public static final TurkceHarf HARF_e = harfler.get('e');
        public static final TurkceHarf HARF_i = harfler.get('i');
        public static final TurkceHarf HARF_ii = harfler.get(CHAR_ii);
        public static final TurkceHarf HARF_o = harfler.get('o');
        public static final TurkceHarf HARF_oo = harfler.get(CHAR_oo);
        public static final TurkceHarf HARF_u = harfler.get('u');
        public static final TurkceHarf HARF_uu = harfler.get(CHAR_uu);

Simdi AzericeSesliUretici yardimci sinifini yazalim. (Azerice bilmedigimden kurallari yanlis yazmis olabilirim.). Bu kurallar dil bilgisinin genel ek sesli harf uretimi konusu ile iliskili ve istisnai durumlari burada belirtmemek gerekiyor. Temelde bu sinifin yaptigi si basit, bir kelimenin son seslisine gore hangi seslinin uretilecegi belirleniyor. Ornegin sesliBelirleAE metodu eger kelimenin son seslisi ince ise 'e' degile 'a' seslisini donduruyor. baslangictaki tanimlanan HARF_a, HARF_e parametreleri hiz ve kodlamayi kolaylastirmak amaciyla yazilmistir.

     1 public class AzericeSesliUretici {
     2
     3     private final TurkceHarf
     4             HARF_a,
     5             HARF_e,
     6             HARF_ee,
     7             HARF_i,
     8             HARF_ii,
     9             HARF_u,
    10             HARF_uu;
    11
    12     public AzericeSesliUretici(Alfabe alfabe) {
    13         HARF_a = alfabe.harf('a');
    14         HARF_e = alfabe.harf('e');
    15         HARF_ee = alfabe.harf(Alfabe.CHAR_ee);
    16         HARF_i = alfabe.harf('i');
    17         HARF_ii = alfabe.harf(Alfabe.CHAR_ii);
    18         HARF_u = alfabe.harf('u');
    19         HARF_uu = alfabe.harf(Alfabe.CHAR_uu);
    20     }
    21
    22     public TurkceHarf sesliBelirleAE(TurkceHarf sonSesli) {
    23         if (sonSesli == HARF_ee)
    24             return HARF_ee;
    25         if (sonSesli.inceSesliMi())
    26             return HARF_e;
    27         return HARF_a;
    28     }
    29
    30     public TurkceHarf sesliBelirleIU(TurkceHarf sonSesli) {
    31         if (sonSesli.inceSesliMi() && sonSesli.duzSesliMi())
    32             return HARF_i;
    33         if (!sonSesli.inceSesliMi() && sonSesli.duzSesliMi())
    34             return HARF_ii;
    35         if (!sonSesli.inceSesliMi() && sonSesli.yuvarlakSesliMi())
    36             return HARF_u;
    37         if (sonSesli.inceSesliMi() && sonSesli.yuvarlakSesliMi())
    38             return HARF_uu;
    39         return Alfabe.TANIMSIZ_HARF;
    40     }
    41 }

Ek uretim kurallarini bu sekilde tamamlamis olduk.
Kok ozel durumlari
Yukaridaki kok listesinde tanimlanan bir kok "sağlıq AD YUM" idi. Burada belirtilen YUM, bu kokun yumusama ozel durumuna sahip oldugunu gosteriyor. Yani "sağlıq" kokunden sonra sesli ile baslayan bir ek geldiginde sonraki q harfi yumusak g harfine donusur. "sağlığa" seklinde. Normalde bu ozelligin calisma aninnda tespiti mumkun olsa bile, Istisnalari olabileceginden duz yazi kokler uzerinde belirtilmesinde bir mahsur yoktur. Kok ozel durumlarinin islendigi sinifin adina AzericeKokOzelDurumlari adini verelim. Bu sinif KokOzelDurumlari ayayuzunu kullanir (Interface)
Ek Ozel Durumlari