Koodannut Mikko Lounela Eino Koposen tavumallin mukaan.
Kyseessä on epätäydellinen luonnostelma,
lopullisen
muuntosäännöstön pitäisi valmistua vuoden sisällä.
Muunnin lukee sanoja, jotka on kirjoitettu Nielsenin ortografialla ja tulostaa ne nykyortografian mukaisessa asussa. Muunnos perustuu tavumalliin, jossa tavun ytimen muodostaa vokaalijono. Konsonanttiyhdistelmät toimivat rajoina (tai siirtyminä) ydinten välillä. Ytimiä on kahta typpiä (1 ja 2), ja siirtymiä puolestaan viittä tyyppiä, mikäli sanojen alut ja loput lasketan mukaan (sananvälin symboli seuraavassa on '0'). Siirtymätyypit ovat 0->1, 1->1, 1->2, 2->1, 1->0 ja 2->0. Merkkimuunnoksia tehdään sekä tavun ytimessä että siirtymässä. Sanan alussa tai lopussa oleva siirtymä voi reaalistua paitsi konsonanttiyhdistelmänä, myös tyhjänä merkkijonona. Sanan ensimmäinen tavu on aina tyyppiä yksi. Sanat koostuvat jaksoista, jotka ovat joko tyyppiä 1->2 tai 1->1->2. Jakson ensimmäisen siirtymän muunnoksen määrittäminen vaatii sen, että tässä vaiheessa tiedetään koko jakson rakenne (muunnokset siirtymissä 1->1 ja 1->2 ovat erilaiset).
Muunnin perustuu (ei-deterministiseen) äärelliseen automaattiin. Äärellisistä automaateista ks. viite. Deterministisessä perusautomaatissa on yhdellä hetkellä tieto vain siitä tilasta, missä automaatti on ja siitä syötteestä, minkä se seuraavaksi saa. Perusautomaatin lisäksi muuntimessa on käytetty kurkistusoperaattoria (lookahead), koska ortografiamuunnoksessa tulee eteen tehtäviä, joissa jonkin merkkijonon muuntamiseen tarvittava informaatio saadaan vasta esimerkiksi kaksi tavua edempänä sanassa.
Muunnin on implementoitu Flex-kielellä, joka on alunperin tarkoitettu tietokoneohjelmien leksikaalisten sekvenssien tunnistamiseen. Flex-ohjelma koostuu säännöistä, joissa kussakin määritellään tila, jossa ohjelman suoritus on, tilassa syötteeksi mahdolliset merkkijonot (säännöllisinä lausekkeina - ks. viite), toiminta, joka suoritetaan tietyssä tilassa tietyllä syötteellä ja tila, johon säännön suorittamisesta siirrytään. Säännössä voidaan myös määrätä syötettä seuraava kontekstiehto säännön toteutumiselle (kurkistus, lookahead).
Muuntimessa on alkutilan (INITIAL) lisäksi 12 tilaa:
%x C01 V1 V1B V2 V2B C11 C12 C21 C10 C20 FIN FAIL
Tilojen lisäksi Flexissä voi esimääritellä ja nimetä merkkijonoja myöhempää käyttöä varten. Tämä helpottaa sääntöjen kirjoittamista ja lukemista, joten määrittelemme kullekin tilalle kaikki sen mahdolliset syötteet:
V1 ((a)|(â)|(E)|(u)|(ú)|(O)|(oa)|(æ)|(i))
V2 ((a)|(â)|(e)|(è)|(i)|(o)|(ò)|(u))
C12 ((b'm)|(cc)|(fr)|(g'gj)|(i'g)|(it)|(i't)|(kk)|(l)|(m)|(mb)|(pp)|(st)|(tt)|(vv)|(v'v)|(ll))
C21 ((l)|(t)|(st)|(Z)|(g))
C10 ((m)|(k)|(st)|(t)|(id))
C20 ((m)|(k)|(st)|(t)|(id))
C01 i?['SZbcdfgjklmprstv]* C11 i?['SZbcdfgjklmprstv]*
FIN (\n|" ")
%%
Muuntimessa on muunnossäännöt kullekin tilalle, kullekin tässätilassa mahdolliselle syötteelle. Syötteet määritellään säännöllisinä lausekkeina, ja osa niistä on esimääritelty yllä määrittelyosassa.Syötettä voi seurata kurkistusosa, joka asettaa kontekstiehdon säännön toteutumiselle. Tämän jälkeen määrätään toiminta, joka säännön lauetessa suoritetaan (muuntimessa joko merkkijonon tulostaminen tai ei mitään), ja tila johon (BEGIN-funktiolla) siirrytään. Esimerkiksi sääntö <V1>a printf ("á"); BEGIN(V1B); sanoo, että tilassa V1, mikäli syöte on 'a', tulostetaan merkki 'á' ja siirrytään tilaan V1B. Sääntö <V1B>""/{C12}{V2}{C21}{V1} BEGIN(C12);sanoo, että tilassa V1B ei lueta syötettä (tyhjä jono ""), mutta jos seuraavana on järjestyksessä joukkoihin C12, V2, C21 ja V1 kuuluvat merkkijonot, siirrytään tilaan C12.
Sännöt luetellaan seuraavassa ryhmiteltynä alkutilan mukaan. Flex-ohjelmassa sääntöjen suoritusjärjestys määräytyy siten, että mikäli seuraavaan syötteeseen soveltuu useampi kuin yksi sääntö, muunnin soveltaaa sitä, jonka kattama merkkijono on pisin. Mikäli vaihtoehtoja vielä jää, Flex soveltaa ylinnä säännöstässä olevaa sääntöä.
Säännöt:
<INITIAL>{C01}* printf ("%s",yytext); BEGIN(V1);
<INITIAL>""/. printf ("%s",yytext); BEGIN(V1);
<V1>a printf ("á"); BEGIN(V1B);
<V1>â printf ("a"); BEGIN(V1B);
<V1>E printf ("e"); BEGIN(V1B);
<V1>u printf ("u"); BEGIN(V1B);
<V1>ú printf ("u"); BEGIN(V1B);
<V1>O printf ("o"); BEGIN(V1B);
<V1>oa printf ("oa"); BEGIN(V1B);
<V1>æ printf ("ea"); BEGIN(V1B);
<V1>i printf ("i"); BEGIN(V1B);
<V1B>""/{C12}{V2}{C21}{V1} BEGIN(C12);
<V1B>""/{C11}{V1}{C12}{V2} BEGIN(C11);
<V1B>""/{C10}?{FIN} BEGIN(C10);
<V1B>""/{C12}{V2} BEGIN(C12);
<C11>{C11}/{V1} printf ("%s",yytext); BEGIN(V1);
<C12>bm/{V2} printf ("pm"); BEGIN(V2);
<C12>b'm/{V2} printf ("bm"); BEGIN(V2);
<C12>cc/{V2} printf ("hc"); BEGIN(V2);
<C12>fr/{V2} printf ("frr"); BEGIN(V2);
<C12>g'gj/{V2} printf ("ddj"); BEGIN(V2);
<C12>i'g/{V2} printf ("ig"); BEGIN(V2);
<C12>it/{V2} printf ("itt"); BEGIN(V2);
<C12>i't/{V2} printf ("it"); BEGIN(V2);
<C12>kk/{V2} printf ("hk"); BEGIN(V2);
<C12>l/{V2} printf ("l"); BEGIN(V2);
<C12>m/{V2} printf ("m"); BEGIN(V2);
<C12>mb/{V2} printf ("mbb"); BEGIN(V2);
<C12>pp/{V2} printf ("hp"); BEGIN(V2);
<C12>st/{V2} printf ("stt"); BEGIN(V2);
<C12>tt/{V2} printf ("ht"); BEGIN(V2);
<C12>vv/{V2} printf ("vv"); BEGIN(V2);
<C12>v'v/{V2} printf ("vv"); BEGIN(V2);
<C12>ll/{V2} printf ("ll"); BEGIN(V2);
<V2>a printf ("á"); BEGIN(V2B);
<V2>â printf ("a"); BEGIN(V2B);
<V2>e printf ("i"); BEGIN(V2B);
<V2>è printf ("e"); BEGIN(V2B);
<V2>i printf ("e"); BEGIN(V2B);
<V2>o printf ("u"); BEGIN(V2B);
<V2>ò printf ("o"); BEGIN(V2B);
<V2>u printf ("o"); BEGIN(V2B);
<V2B>""/{C21} BEGIN(C21);
<V2B>""/{C20}?{FIN} BEGIN(C20);
<C21>l printf ("l"); BEGIN(V1);
<C21>t printf ("h"); BEGIN(V1);
<C21>st printf ("st"); BEGIN(V1);
<C21>Z printf ("Z"); BEGIN(V1);
<C21>g printf ("g"); BEGIN(V1);
<C20>m/{FIN} printf ("n"); BEGIN(FIN);
<C20>k/{FIN} printf ("t"); BEGIN(FIN);
<C20>st/{FIN} printf ("s"); BEGIN(FIN);
<C20>t/{FIN} printf ("t"); BEGIN(FIN);
<C20>id/{FIN} printf ("id"); BEGIN(FIN);
<C20>""/{FIN} BEGIN(FIN);
<C10>m/{FIN} printf ("n"); BEGIN(FIN);
<C10>k/{FIN} printf ("t"); BEGIN(FIN);
<C10>st/{FIN} printf ("s"); BEGIN(FIN);
<C10>t/{FIN} printf ("t"); BEGIN(FIN);
<C10>id/{FIN} printf ("id"); BEGIN(FIN);
<C10>""/{FIN} BEGIN(FIN);
<FAIL>. printf ("%s",yytext);
<*>. printf ("[!FAIL: %s",yytext); BEGIN(FAIL);
<FAIL>{FIN} printf ("]%s",yytext); BEGIN(INITIAL);
<*>{FIN} printf ("%s",yytext); BEGIN(INITIAL);
%%
main()
{
yylex();
}