# Suomi-malaga, suomen kielen muoto-opin kuvaus. # # Tekijänoikeus © 2006 Hannu Väisänen (Etunimi.Sukunimi@joensuu.fi) # 2006 - 2010 Harri Pitkänen (hatapitk@iki.fi) # # Tämä ohjelma on vapaa; tätä ohjelmaa on sallittu levittää # edelleen ja muuttaa GNU yleisen lisenssin (GPL lisenssin) # ehtojen mukaan sellaisina kuin Free Software Foundation # on ne julkaissut; joko Lisenssin version 2, tai (valinnan # mukaan) minkä tahansa myöhemmän version mukaisesti. # # Tätä ohjelmaa levitetään siinä toivossa, että se olisi # hyödyllinen, mutta ilman mitään takuuta; ilman edes # hiljaista takuuta kaupallisesti hyväksyttävästä laadusta tai # soveltuvuudesta tiettyyn tarkoitukseen. Katso GPL # lisenssistä lisää yksityiskohtia. # # Tämän ohjelman mukana pitäisi tulla kopio GPL # lisenssistä; jos näin ei ole, kirjoita osoitteeseen Free # Software Foundation Inc., 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301, USA. # # Tämän ohjeman linkittäminen staattisesti tai dynaamisesti # muihin moduuleihin on ohjelmaan perustuvan teoksen # tekemistä, joka on siis GPL lisenssin ehtojen alainen. # # # 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 2, or (at your option) # any later version. # # 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; see the file COPYING. If not, write to the # Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # # Linking this program statically or dynamically with other modules is # making a combined work based on this program. Thus, the terms and # conditions of the GNU General Public License cover the whole # combination. initial <>, rules erisnimi, laatusana, lukusana, sanan_alku, teonsana, laatusana_laatusanasta, paikannimen_lainen_johdos; include "config.inc"; include "suomi.inc"; include "mor.inc"; # Palauttaa yes, jos $sana voi liittyä listaan $vasen yhdyssanassa, # jossa yhdysviiva käyttö on sallittua ja pakollista täsmälleen silloin, # kun alkuosa päättyy samaan vokaaliin jolla loppuosa alkaa. # Listan $vasen on sisällettävä vähintään yksi elementti. subrule vokaaliehdollinen_yhdysviiva_ok($vasen, $sana): define $i := length($vasen); if ($vasen.$i.luokka = tavuviiva) then if ($i = 1) then return yes; end; if $vasen.$i.vokaaliehto = no then return yes; end; define $edellinen := $vasen.($i - 1); if (vokaali(first($sana)) and first($sana) = last($edellinen.alku)) then return yes; # is- ("teknillis-tieteellinen", "Kaakkois-Suomi") # FIXME: tämä ei ole tarkalleen ottaen oikein, mutta toistaiseksi riittävän hyvä elseif ($edellinen.alku matches ".*is") then return yes; elseif $edellinen.tiedot /= nil and sitlaina in $edellinen.tiedot then return yes; else return no; end; else if (vokaali(first($sana)) and first($sana) = last($vasen.$i.alku)) then return no; else return yes; end; end; end; define @ehtotapa := ; define @mahtotapa := ; define @käskytapa := ; define @nimitapa_1 := ; define @nimitapa_2 := ; define @nimitapa_3 := ; # Johtimet teonsanoista define @johdin_tU := ; define @johtimet_nimisana_teonsanasta := + @johdin_jA; define @johtimet_laatusana_teonsanasta := + @johdin_nUt + @johdin_tU; define @johtimet_seikkasana_teonsanasta := ; # esim. "pamahduksittain" define @johdin_teonsanasta := @johtimet_nimisana_teonsanasta + @johtimet_laatusana_teonsanasta + @johtimet_seikkasana_teonsanasta; # Johtimet nimisanoista define @johtimet_nimisana_nimisanasta := ; define @johtimet_laatusana_nimisanasta := ; define @johdin_nimisanasta := @johtimet_nimisana_nimisanasta + @johtimet_laatusana_nimisanasta + + @johdin_jA; #FIXME: onko tämä oikein? # Johtimet laatusanoista define @johtimet_nimisana_laatusanasta := ; define @johtimet_laatusana_laatusanasta := ; define @johtimet_laatusanasta := @johtimet_nimisana_laatusanasta + @johtimet_laatusana_laatusanasta; combi_rule sanan_alku ($vasen, $oikea, $sana): if $oikea.luokka = lyhenne then if (kaksoispiste in $oikea.jatko) then result <[alku: $sana] + $oikea>, rules kaksoispiste; end; if (tavuviiva in $oikea.jatko) then result <[alku: $sana] + $oikea>, rules yhdysmerkki_lyhenteen_jälkeen; end; if (loppu in $oikea.jatko) then result <[alku: $sana] + $oikea>, accept; end; elseif $oikea.luokka in then result <[alku: $sana] + $oikea>, accept; elseif $oikea.luokka = etuliite then if nimisana in $oikea.jatko and laatusana in $oikea.jatko then result <[alku: $sana] + $oikea>, rules inen_johdos_nimisanasta, laatusana, paikannimen_lainen_johdos; elseif nimisana in $oikea.jatko then result <[alku: $sana] + $oikea>, rules inen_johdos_nimisanasta, paikannimen_lainen_johdos; elseif laatusana in $oikea.jatko then result <[alku: $sana] + $oikea>, rules laatusana, paikannimen_lainen_johdos, inen_johdos_nimisanasta; end; if tavuviiva in $oikea.jatko then result <[alku: $sana] + $oikea>, rules yhdysmerkki_etuliitteen_jälkeen; else result <[alku: $sana] + $oikea>, accept; end; if teonsana in $oikea.jatko then result <[alku: $sana] + $oikea>, rules teonsana; elseif nimisana in $oikea.jatko then result <[alku: $sana] + $oikea>, rules nimisana_teonsanasta; end; if teonsanan_johdoksen_etuliite in $oikea.jatko then result <[alku: $sana] + $oikea>, rules nimisana_teonsanasta; end; result <[alku: $sana] + $oikea>, rules etuliite, nimisana; elseif $oikea.luokka = kieltosana then if kieltosanan_liitesana in $oikea.jatko then result <[alku: $sana] + $oikea>, rules kieltosanan_liitesana; end; result <[alku: $sana] + $oikea>, accept; elseif $oikea.luokka in then if (loppu in $oikea.jatko) then result <[alku: $sana] + $oikea>, accept; end; if (liitesana in $oikea.jatko) then result <[alku: $sana] + $oikea>, rules liitesana; end; if (omistusliite in $oikea.jatko) then result <[alku: $sana] + $oikea>, rules omistusliite; end; result <[alku: $sana] + $oikea>, rules ei_ys_sijapääte; # FIXME: esiehto testaamatta elseif $oikea.luokka = asemosana then if loppu in $oikea.jatko then result <[alku: $sana] + $oikea>, accept; end; if liitesana in $oikea.jatko then result <[alku: $sana] + $oikea>, rules liitesana; end; result <[alku: $sana] + $oikea>, rules asemosanan_sijapääte; elseif $oikea.luokka = kieltosanan_etuliite then result <[alku: $sana] + $oikea>, rules kieltosana; elseif $oikea.luokka = tavuviiva then result <[vokaaliehto: no, alku: "-"] + $oikea>, rules nimisana, erisnimi, laatusana, lyhennesääntö, etuliite, nimisana_teonsanasta, lukusanan_jälkiliite, inen_johdos_nimisanasta_ehdollinen, lukusana; elseif $oikea.luokka in then ? $oikea.tiedot = nil or not ysj in $oikea.tiedot; if ($oikea.luokka = nimisana and voittoaste in $oikea.jatko) then result <[alku: $sana] + $oikea>, rules voittoaste; end; if (tavuviiva in $oikea.jatko and ($oikea.tiedot = nil or (not ei_ysa in $oikea.tiedot and not ei_ys in $oikea.tiedot))) then result <[alku: $sana] + $oikea>, rules nimisana, nimisana_laatusanasta, nimisana_teonsanasta, nimi_laatusanan_etuliite, paikannimen_lainen_johdos, inen_johdos_nimisanasta, inen_päätteinen_laatusana_ei_nimisanajohdosta; # Kieli=poliittinen if ($oikea.luokka = nimisana or $oikea.aluetta_tarkentava_etuliite = nil) then result <[alku: $sana] + $oikea>, rules yhdysmerkki_yleisnimen_jälkeen; end; end; if loppu in $oikea.jatko then if $oikea.etuliite = yes then result <[alku: $sana] + $oikea + [luokka: etuliite]>, accept; else result <[alku: $sana] + $oikea>, accept; end; end; if omistusliite in $oikea.jatko then result <[alku: $sana] + $oikea>, rules omistusliite; end; if liitesana in $oikea.jatko then result <[alku: $sana] + $oikea>, rules liitesana; end; if $oikea.luokka = nimisana then result <[alku: $sana] + $oikea>, rules nimisanan_sijapääte, nimisanan_johdos; else result <$oikea + [alku: $sana, luokka: nimisana, jatko: $oikea.jatko - ]>, rules nimisanan_sijapääte, nimisanan_johdos; end; end; end; combi_rule etuliite ($vasen, $oikea, $sana, $index): ? $oikea.luokka = etuliite; ? $oikea.tiedot = nil or not ei_ysj in $oikea.tiedot; ? vokaaliehdollinen_yhdysviiva_ok($vasen, $sana); define $res := $vasen + <[alku: $sana] + $oikea>; if nimisana in $oikea.jatko and laatusana in $oikea.jatko then result $res, rules inen_johdos_nimisanasta, laatusana, paikannimen_lainen_johdos, nimisana_teonsanasta; elseif nimisana in $oikea.jatko then result $res, rules inen_johdos_nimisanasta, paikannimen_lainen_johdos, nimisana_teonsanasta; elseif laatusana in $oikea.jatko then result $res, rules laatusana, paikannimen_lainen_johdos, inen_johdos_nimisanasta; end; if (teonsana in $oikea.jatko) then result $res, rules teonsana; end; if teonsanan_johdoksen_etuliite in $oikea.jatko then result $res, rules nimisana_teonsanasta; end; if (kieltosana in $oikea.jatko) then result $res, rules kieltosana; else if tavuviiva in $oikea.jatko then result $res, rules yhdysmerkki_etuliitteen_jälkeen; else result $res, accept; end; result $res, rules etuliite, nimisana; end; end; ###### ETULIITESÄÄNNÖT ALKAVAT combi_rule nimisanan_etuliite ($vasen, $oikea, $sana, $index): ? $oikea.luokka = etuliite; ? $oikea.tiedot = nil or not ei_ysj in $oikea.tiedot; ? vokaaliehdollinen_yhdysviiva_ok($vasen, $sana); define $res := $vasen + <[alku: $sana] + $oikea>; if nimisana in $oikea.jatko then result $res, rules inen_johdos_nimisanasta, nimisana_laatusanasta; end; ? not kieltosana in $oikea.jatko; if tavuviiva in $oikea.jatko then result $res, rules yhdysmerkki_etuliitteen_jälkeen; end; result $res, rules etuliite, nimisana, nimisana_teonsanasta; end; combi_rule nimi_laatusanan_etuliite ($vasen, $oikea, $sana, $index): ? $oikea.luokka = etuliite; ? $oikea.tiedot = nil or not ei_ysj in $oikea.tiedot; ? vokaaliehdollinen_yhdysviiva_ok($vasen, $sana); define $res := $vasen + <[alku: $sana] + $oikea>; if nimisana in $oikea.jatko and laatusana in $oikea.jatko then result $res, rules inen_johdos_nimisanasta, laatusana, paikannimen_lainen_johdos; elseif nimisana in $oikea.jatko then result $res, rules inen_johdos_nimisanasta, paikannimen_lainen_johdos; elseif laatusana in $oikea.jatko then result $res, rules laatusana, paikannimen_lainen_johdos, inen_johdos_nimisanasta; end; if (kieltosana in $oikea.jatko) then result $res, rules kieltosana; else if tavuviiva in $oikea.jatko then result $res, rules yhdysmerkki_etuliitteen_jälkeen; else result $res, accept; end; result $res, rules etuliite, nimisana, nimisana_teonsanasta; end; end; ###### ETULIITESÄÄNNÖT PÄÄTTYVÄT combi_rule erisnimi ($vasen, $oikea, $sana, $index): ? $oikea.luokka in @erisnimi; ? ($oikea.tiedot = nil) or ($index = 1) or (not ei_ysj in $oikea.tiedot and not ei_ys in $oikea.tiedot); define $res := $vasen + <[alku: $sana] + $oikea>; if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; if tavuviiva in $oikea.jatko or loppu in $oikea.jatko then result $res, rules yhdysmerkki_erisnimen_jälkeen; end; result $res, rules erisnimen_sijapääte; end; # Esiehto: ei sanan alussa combi_rule nimisana ($vasen, $oikea, $sana, $index): if ($oikea.luokka = seikkasana and $oikea.tiedot /= nil and ys_perusosa in $oikea.tiedot) then if (loppu in $oikea.jatko) then result $vasen + <[alku: $sana] + $oikea>, accept; end; if (liitesana in $oikea.jatko) then result $vasen + <[alku: $sana] + $oikea>, rules liitesana; end; if (omistusliite in $oikea.jatko) then result $vasen + <[alku: $sana] + $oikea>, rules omistusliite; end; result $vasen + <[alku: $sana] + $oikea>, rules ei_ys_sijapääte; # FIXME: esiehto testaamatta end; ? $oikea.luokka in ; define $edellinen := $vasen.($index - 1); ? ((nimisana in $edellinen.jatko) or (tavuviiva in $edellinen.jatko and $edellinen.luokka in @nimisana + ) or ($edellinen.luokka = lukusana) or ($oikea.lähtöluokka = teonsana and (teonsana in $edellinen.jatko or teonsanan_johdoksen_etuliite in $edellinen.jatko))); ? ($oikea.tiedot = nil) or (not ei_ysj in $oikea.tiedot and not ei_ys in $oikea.tiedot); ? vokaaliehdollinen_yhdysviiva_ok($vasen, $sana) or ($oikea.tiedot /= nil and sitlaina in $oikea.tiedot and $edellinen.luokka = tavuviiva); define $res := $vasen + <[alku: $sana] + $oikea>; if $edellinen.luokka in then if $edellinen.luokka = laatusana then result $res, rules johdin_laatusana_nimisanasta; stop; end; elseif $edellinen.lukutyyppi /= nil then if tavuviiva in $oikea.jatko then result $res, rules etuliite, tavuviiva, nimisana, nimisana_laatusanasta, nimisana_teonsanasta; end; stop; end; if ($oikea.luokka = nimisana and voittoaste in $oikea.jatko) then result $res, rules voittoaste; end; if (tavuviiva in $oikea.jatko and ($oikea.tiedot = nil or (not ei_ysa in $oikea.tiedot and not ei_ys in $oikea.tiedot))) then result $res, rules nimisana, nimisana_laatusanasta, nimisana_teonsanasta, etuliite, paikannimen_lainen_johdos, yhdysmerkki_yleisnimen_jälkeen, inen_johdos_nimisanasta, inen_päätteinen_laatusana_ei_nimisanajohdosta; # Kieli=poliittinen end; $res := $vasen + <$oikea + [alku: $sana, luokka: nimisana, lähtöluokka: $oikea.luokka]>; if (loppu in $oikea.jatko) then result $res, accept; end; if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; result $res, rules nimisanan_sijapääte, nimisanan_johdos; if $oikea.erisnimen_pääte = yes and $vasen.(1).luokka /= tavuviiva then $res := $vasen + <$oikea + [alku: $sana, luokka: nimi]>; if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; result $res, rules erisnimen_sijapääte; end; end; ###### JOHDETTUJEN SANOJEN ALOITUSSÄÄNNÖT ALKAVAT # Teonsanasta johdettu nimisana, esim. sanoma <- sanoa. combi_rule nimisana_teonsanasta ($vasen, $oikea, $sana, $index): ? $oikea.luokka = teonsana; if ($index greater 1) then ? vokaaliehdollinen_yhdysviiva_ok($vasen, $sana); end; ? $oikea.tiedot = nil or not ei_ysj in $oikea.tiedot; define $res := $vasen + <[alku: $sana] + $oikea>; if nimitapa_45 in $oikea.jatko then result $res, rules nimitapa_4; end; result $res, rules teonsanan_johdos; # FIXME: johdetun muodon on oltava nimisana end; # Teonsanasta johdettu laatusana, esim. kasvattava <- kasvattaa. combi_rule laatusana_teonsanasta ($vasen, $oikea, $sana, $index): ? $oikea.luokka = teonsana; if ($index greater 1) then ? vokaaliehdollinen_yhdysviiva_ok($vasen, $sana); end; ? $oikea.tiedot = nil or not ei_ysj in $oikea.tiedot; define $res := $vasen + <[alku: $sana] + $oikea>; result $res, rules johdin_laatusana_teonsanasta; end; # Laatusanasta johdettu nimisana, esim. vapaus <- vapaa. combi_rule nimisana_laatusanasta ($vasen, $oikea, $sana, $index): ? $oikea.luokka in @laatusana; ? $oikea.tiedot = nil or (not ei_ys in $oikea.tiedot and not ei_ysj in $oikea.tiedot); ? vokaaliehdollinen_yhdysviiva_ok($vasen, $sana); result $vasen + <[alku: $sana] + $oikea>, rules johdin_nimisana_laatusanasta; end; # Laatusanasta johdettu laatusana, esim. paha+nlai+nen <- paha. combi_rule laatusana_laatusanasta ($vasen, $oikea, $sana): ? $oikea.luokka in @laatusana; if (omanto_n in $oikea.jatko) then result $vasen + <[alku: $sana] + $oikea>, rules johdin_nlainen; end; end; # inen-johdinta edeltävä nimisana # sääntö ei voi olla sanan alussa combi_rule inen_johdos_nimisanasta ($vasen, $oikea, $sana, $index): ? $oikea.luokka in ; ? johdin_inen in $oikea.jatko; ? $oikea.tiedot = nil or (not ei_ys in $oikea.tiedot and not ei_ysj in $oikea.tiedot); ? vokaaliehdollinen_yhdysviiva_ok($vasen, $sana); define $res := $vasen + <[alku: $sana] + $oikea>; define $edellinen := $vasen.($index - 1); if tavuviiva in $oikea.jatko and $edellinen.luokka /= etuliite then result $res, rules johdin_inen, inen_johdos_nimisanasta; else result $res, rules johdin_inen; end; end; # inen-johdinta edeltävä nimisana # sääntö ei voi olla sanan alussa eikä koske sanoja, joille inen-johdin on aina sallittu combi_rule inen_johdos_nimisanasta_ehdollinen ($vasen, $oikea, $sana, $index): ? $oikea.luokka in ; ? johdin_inen in $oikea.jatko; ? $oikea.tiedot = nil or (not ei_ys in $oikea.tiedot and not ei_ysj in $oikea.tiedot and not inen in $oikea.tiedot); ? vokaaliehdollinen_yhdysviiva_ok($vasen, $sana); define $res := $vasen + <[alku: $sana] + $oikea>; define $edellinen := $vasen.($index - 1); if tavuviiva in $oikea.jatko and $edellinen.luokka /= etuliite then result $res, rules johdin_inen, inen_johdos_nimisanasta; else result $res, rules johdin_inen; end; end; # Paikannimestä johdettu kansallisuuden nimi combi_rule paikannimen_lainen_johdos ($vasen, $oikea, $sana, $index): ? $oikea.luokka = paikannimi; ? johdin_lAinen in $oikea.jatko; if ($index greater 1) then ? vokaaliehdollinen_yhdysviiva_ok($vasen, $sana); end; result $vasen + <[alku: $sana] + $oikea>, rules paikannimen_lainen_johdin; end; ###### JOHDETTUJEN SANOJEN ALOITUSSÄÄNNÖT PÄÄTTYVÄT ###### JOHDINSÄÄNNÖT ALKAVAT combi_rule johdin_nlainen ($vasen, $oikea, $sana): ? $oikea.luokka = johdin_nlainen; define $res := $vasen + <[alku: $sana] + $oikea>; if tavuviiva in $oikea.jatko then result $res, rules nimisana, laatusana, tavuviiva, etuliite; end; if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; result $res, rules laatusanan_sijapääte, johdin_nimisana_laatusanasta, voitto_yliaste; end; combi_rule johdin_inen ($vasen, $oikea, $sana, $index): ? $oikea.luokka = johdin_inen; $oikea.äs := $vasen.($index - 1).äs; define $res := $vasen + <[alku: $sana] + $oikea>; if tavuviiva in $oikea.jatko then result $res, rules nimisana, laatusana, tavuviiva, etuliite, nimisana_teonsanasta; end; if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; result $res, rules laatusanan_sijapääte, johdin_nimisana_laatusanasta, voitto_yliaste; end; combi_rule johdettu_paikannimi ($vasen, $oikea, $sana): ? $oikea.paikannimen_jälkiliite = yes; ? vokaaliehdollinen_yhdysviiva_ok($vasen, $sana); define $res := $vasen + <[alku: $sana] + $oikea>; if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; if tavuviiva in $oikea.jatko then result $res, rules yhdysmerkki_erisnimen_jälkeen, johdettu_paikannimi; end; result $res, rules erisnimen_sijapääte; end; combi_rule paikannimen_lainen_johdin ($vasen, $oikea, $sana, $index): ? $oikea.luokka = johdin_lAinen; ? vokaalisointu_oikein_ei_aä($vasen.($index - 1), $oikea); define $res := $vasen + <[alku: $sana] + $oikea>; if tavuviiva in $oikea.jatko then result $res, rules nimisana, inen_johdos_nimisanasta_ehdollinen, yhdysmerkki_lainen_johdoksen_jälkeen, nimisana_teonsanasta, paikannimen_lainen_johdos, inen_päätteinen_laatusana_ei_nimisanajohdosta, nimisana_laatusanasta; end; if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; if loppu in $oikea.jatko then result $res, accept; end; if johdin_ittAin in $oikea.jatko then result $res, rules johdin_seikkasana_ittain; end; if voittoaste in $oikea.jatko or yliaste in $oikea.jatko then result $res, rules voitto_yliaste; end; result $res, rules laatusanan_sijapääte_omistusliitteellä, johdin_nimisana_laatusanasta; end; ###### JOHDINSÄÄNNÖT PÄÄTTYVÄT combi_rule laatusana ($vasen, $oikea, $sana, $index): ? $oikea.luokka in @laatusana; if ($index greater 1) then ? vokaaliehdollinen_yhdysviiva_ok($vasen, $sana); ? $oikea.tiedot = nil or (not ei_ys in $oikea.tiedot and not ei_ysj in $oikea.tiedot); else ? $oikea.tiedot = nil or not ysj in $oikea.tiedot; end; define $lähtöluokka := $oikea.luokka; define $res := $vasen + <$oikea + [alku: $sana, luokka: laatusana, lähtöluokka: $lähtöluokka]>; if $oikea.luokka = laatusana or ($index greater 1 and $vasen.($index - 1).luokka /= nimitapa_45) then if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; end; if tavuviiva in $oikea.jatko and ($oikea.tiedot = nil or not (ei_ys in $oikea.tiedot or ei_ysa in $oikea.tiedot)) then if $oikea.luokka /= laatusana or $oikea.inen_loppu = yes then result $res, rules laatusana; else result $res, rules inen_päätteinen_laatusana; end; if ($oikea.luokka = laatusana or $index greater 1) then result $res, rules etuliite, nimisana, inen_johdos_nimisanasta; end; if $oikea.aluetta_tarkentava_etuliite = yes then result $res, rules yhdysmerkki_laatusanan_jälkeen_ei_kansallisuutta; else result $res, rules yhdysmerkki_laatusanan_jälkeen; end; end; result $res, rules laatusanan_sijapääte, johdin_nimisana_laatusanasta, voitto_yliaste; end; combi_rule inen_päätteinen_laatusana ($vasen, $oikea, $sana, $index): ? $oikea.inen_loppu = yes; ? vokaaliehdollinen_yhdysviiva_ok($vasen, $sana); ? $oikea.tiedot = nil or (not ei_ys in $oikea.tiedot and not ei_ysj in $oikea.tiedot); # nimisana, laatusana ja etuliite jätetty pois, koska todennäköinen käyttö vähäistä # (teoriassa voi olla OK) define $res := $vasen + <$oikea + [alku: $sana, luokka: laatusana]>; if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if tavuviiva in $oikea.jatko then result $res, rules tavuviiva, paikannimen_lainen_johdos; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; result $res, rules laatusanan_sijapääte, johdin_nimisana_laatusanasta, voitto_yliaste; end; combi_rule inen_päätteinen_laatusana_ei_nimisanajohdosta ($vasen, $oikea, $sana, $index): ? $oikea.inen_loppu = yes; ? vokaaliehdollinen_yhdysviiva_ok($vasen, $sana); ? $oikea.tiedot = nil or (not ei_ys in $oikea.tiedot and not ei_ysj in $oikea.tiedot); # nimisana, laatusana ja etuliite jätetty pois, koska todennäköinen käyttö vähäistä # (teoriassa voi olla OK) define $res := $vasen + <$oikea + [alku: $sana, luokka: laatusana]>; if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if tavuviiva in $oikea.jatko then result $res, rules tavuviiva, paikannimen_lainen_johdos; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; result $res, rules laatusanan_sijapääte, voitto_yliaste; end; combi_rule lyhennesääntö ($vasen, $oikea, $sana, $index): ? $oikea.luokka = lyhenne; ? $oikea.alaluokka /= roomalainen; ? $index less 2 or $oikea.tiedot = nil or (not ei_ys in $oikea.tiedot and not ei_ysj in $oikea.tiedot); define $res := $vasen + <[alku: $sana] + $oikea>; if (kaksoispiste in $oikea.jatko) then result $res, rules kaksoispiste; end; if (tavuviiva in $oikea.jatko) then result $res, rules yhdysmerkki_lyhenteen_jälkeen; end; if (loppu in $oikea.jatko) then result $res, accept; end; end; combi_rule kaksoispiste ($vasen, $oikea, $sana, $index): ? $oikea.luokka = kaksoispiste; result $vasen + <[alku: $sana] + $oikea + [äs: $vasen.($index - 1).äs]>, rules kaksoispisteen_sijapääte, omistusliite, liitesana; end; combi_rule tavuviiva ($vasen, $oikea, $sana): ? $oikea.luokka = tavuviiva; define $res := $vasen + <[vokaaliehto: yes, alku: "-"] + $oikea>; result $res, accept; result $res, rules nimisana, erisnimi, laatusana, lyhennesääntö, etuliite, nimisana_teonsanasta; end; ###### YHDYSMERKKISÄÄNNÖT ALKAVAT combi_rule yhdysmerkki_yleisnimen_jälkeen ($vasen, $oikea, $sana): ? $oikea.luokka = tavuviiva; define $res := $vasen + <[vokaaliehto: yes, alku: "-"] + $oikea>; result $res, accept; result $res, rules nimisana, erisnimi, laatusana, lyhennesääntö, etuliite, nimisana_teonsanasta, inen_johdos_nimisanasta_ehdollinen; end; combi_rule yhdysmerkki_erisnimen_jälkeen ($vasen, $oikea, $sana, $index): ? $oikea.luokka = tavuviiva; define $edellinen := $vasen.($index - 1); define $res := $vasen + <[vokaaliehto: no, alku: "-"] + $oikea>; result $res, accept; result $res, rules erisnimi; if ($edellinen.sijamuoto in or ($edellinen.luokka /= sijapääte and ($edellinen.luokka /= nimi or tavuviiva in $edellinen.jatko or liitesana in $edellinen.jatko))) then result $res, rules nimisana, nimisana_laatusanasta, etuliite, nimisana_teonsanasta, inen_päätteinen_laatusana_ei_nimisanajohdosta, inen_johdos_nimisanasta_ehdollinen; end; end; combi_rule yhdysmerkki_teonsanan_jälkeen ($vasen, $oikea, $sana): ? $oikea.luokka = tavuviiva; define $res := $vasen + <[vokaaliehto: yes, alku: "-"] + $oikea>; result $res, accept; result $res, rules nimisana, erisnimi, lyhennesääntö, etuliite; end; combi_rule yhdysmerkki_lyhenteen_jälkeen ($vasen, $oikea, $sana): ? $oikea.luokka = tavuviiva; define $res := $vasen + <[vokaaliehto: no, alku: "-"] + $oikea>; result $res, accept; result $res, rules nimisana, erisnimi, laatusana, etuliite, nimisana_teonsanasta; end; combi_rule yhdysmerkki_laatusanan_jälkeen ($vasen, $oikea, $sana, $index): ? $oikea.luokka = tavuviiva; define $res := $vasen + <[vokaaliehto: yes, alku: "-"] + $oikea>; if $index /= 2 or $vasen.($index - 1).lähtöluokka /= nimi_laatusana then result $res, accept; result $res, rules nimisana, erisnimi; end; result $res, rules laatusana, lyhennesääntö, etuliite, nimisana_teonsanasta, inen_johdos_nimisanasta, paikannimen_lainen_johdos; end; combi_rule yhdysmerkki_inen_johdoksen_jälkeen ($vasen, $oikea, $sana): ? $oikea.luokka = tavuviiva; define $res := $vasen + <[vokaaliehto: yes, alku: "-"] + $oikea>; result $res, accept; result $res, rules nimisana, laatusana, etuliite, nimisana_teonsanasta, inen_johdos_nimisanasta, paikannimen_lainen_johdos; end; combi_rule yhdysmerkki_laatusanan_jälkeen_ei_kansallisuutta($vasen, $oikea, $sana): ? $oikea.luokka = tavuviiva; define $res := $vasen + <[vokaaliehto: yes, alku: "-"] + $oikea>; result $res, accept; result $res, rules nimisana, erisnimi, laatusana, lyhennesääntö, etuliite, nimisana_teonsanasta, inen_johdos_nimisanasta; end; combi_rule yhdysmerkki_sanan_lopussa ($vasen, $oikea, $sana): ? $oikea.luokka = tavuviiva; result $vasen + <[vokaaliehto: no, alku: "-"] + $oikea>, accept; end; combi_rule yhdysmerkki_lainen_johdoksen_jälkeen ($vasen, $oikea, $sana): ? $oikea.luokka = tavuviiva; define $res := $vasen + <[vokaaliehto: no, alku: "-"] + $oikea>; result $res, accept; result $res, rules erisnimi, paikannimen_lainen_johdos, inen_päätteinen_laatusana, inen_johdos_nimisanasta; end; combi_rule merkki_numeron_jälkeen ($vasen, $oikea, $sana): ? $oikea.luokka in ; define $res := $vasen + <[vokaaliehto: no, alku: "-"] + $oikea>; if $oikea.luokka = tavuviiva then result $res, accept; result $res, rules lukusanan_jälkiliite, inen_johdos_nimisanasta, inen_päätteinen_laatusana; else result $res, rules lukusana_numero, kaksoispisteen_sijapääte; end; end; combi_rule yhdysmerkki_etuliitteen_jälkeen ($vasen, $oikea, $sana, $index): ? $oikea.luokka = tavuviiva; define $res := $vasen + <[vokaaliehto: yes, alku: "-"] + $oikea>; result $res, accept; define $jatko := $vasen.($index - 1).jatko; if teonsana in $jatko then if nimisana in $jatko or laatusana in $jatko then result $res, rules nimisana, laatusana, erisnimi; end; result $res, rules etuliite, teonsana; else result $res, rules nimisana, laatusana, etuliite, erisnimi, nimisana_teonsanasta; end; if nimisana in $jatko then result $res, rules lyhennesääntö; end; end; combi_rule yhdysmerkki_ennen_paikannimea ($vasen, $oikea, $sana): ? $oikea.luokka = tavuviiva; define $res := $vasen + <[vokaaliehto: yes, alku: "-"] + $oikea>; result $res, accept; result $res, rules erisnimi; end; ###### YHDYSMERKKISÄÄNNÖT PÄÄTTYVÄT define @sti_edeltäjä := + @johdin_nUt + @johdin_tU + @johtimet_laatusana_nimisanasta + @johtimet_laatusana_laatusanasta; ###### SIJAPÄÄTESÄÄNNÖT ALKAVAT combi_rule erisnimen_sijapääte ($vasen, $oikea, $sana, $index): ? $oikea.luokka = sijapääte; define $edellinen := $vasen.($index - 1); ? $oikea.sija in $edellinen.jatko; if $oikea.sija = sisätulento_Vn then ? sisätulento_Vn_oikein(last($edellinen.alku), $sana); elseif $oikea.sija = sisätulento_hVn then ? sisätulento_hVn_oikein(last($edellinen.alku), $sana); else ? vokaalisointu_oikein($edellinen, $oikea); end; if $oikea.äs = aä then $oikea.äs := $edellinen.äs; end; define $res := $vasen + <[alku: $sana] + $oikea>; if ($oikea.sija = kerronto_sti) then ? $edellinen.luokka in @sti_edeltäjä; elseif ($oikea.sijamuoto = omanto and $oikea.luku = yksikkö) then if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if $edellinen.luokka = paikannimi then result $res, rules paikannimen_lainen_johdos, inen_päätteinen_laatusana; end; result $res, rules yhdysmerkki_erisnimen_jälkeen, johdettu_paikannimi; else if omistusliite in $oikea.jatko and ($oikea.sija /= omanto_n or $edellinen.ei_yks = nil) then result $res, rules omistusliite; end; if tavuviiva in $oikea.jatko and $oikea.sijamuoto in then result $res, rules yhdysmerkki_erisnimen_jälkeen; end; if $oikea.sijamuoto = omanto and $edellinen.luokka = sukunimi and tavuviiva in $oikea.jatko then result $res, rules johdettu_paikannimi; end; end; if $oikea.sija /= omanto_n or $edellinen.ei_yks = nil then if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; end; end; combi_rule voitto_yliasteen_sijapääte ($vasen, $oikea, $sana, $index): ? $oikea.luokka = sijapääte; define $edellinen := $vasen.($index - 1); ? $oikea.sija in $edellinen.jatko; ? $oikea.sija /= kerronto_sti or $edellinen.luokka in @sti_edeltäjä; if $oikea.sija = sisätulento_Vn then ? sisätulento_Vn_oikein(last($edellinen.alku), $sana); elseif $oikea.sija = sisätulento_hVn then ? sisätulento_hVn_oikein(last($edellinen.alku), $sana); else ? vokaalisointu_oikein($edellinen, $oikea); end; if $oikea.äs = aä then $oikea.äs := $edellinen.äs; end; define $res := $vasen + <[alku: $sana] + $oikea>; if ($oikea.sija = kerronto_sti) then result $res, accept; result $res, rules liitesana; else if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; define $kantasana := $vasen.(length($vasen)-1); if ($oikea.sijamuoto = omanto and ($kantasana.tiedot = nil or not (ei_ysa in $kantasana.tiedot and ei_ys in $kantasana.tiedot))) then result $res, rules inen_johdos_nimisanasta; end; end; if $vasen.($index - 2).luokka in and $oikea.sijamuoto = omanto then result $res, rules nimisana, nimisana_teonsanasta, nimisana_laatusanasta, yhdysmerkki_yleisnimen_jälkeen, nimisanan_etuliite; end; end; combi_rule nimisanan_sijapääte ($vasen, $oikea, $sana, $index): ? $oikea.luokka = sijapääte; ? $oikea.sija /= kerronto_sti; define $edellinen := $vasen.($index - 1); ? $oikea.sija in $edellinen.jatko; if $oikea.sija = sisätulento_Vn then ? sisätulento_Vn_oikein(last($edellinen.alku), $sana); elseif $oikea.sija = sisätulento_hVn then ? sisätulento_hVn_oikein(last($edellinen.alku), $sana); else ? vokaalisointu_oikein($edellinen, $oikea); end; if $oikea.äs = aä then $oikea.äs := $edellinen.äs; end; define $res := $vasen + <[alku: $sana] + $oikea>; if ($oikea.sija = kerronto_sti) then ? $edellinen.luokka in @sti_edeltäjä; result $res, accept; result $res, rules liitesana; else if $oikea.sija /= omanto_n or $edellinen.ei_yks = nil then if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; end; if (tavuviiva in $oikea.jatko and ($edellinen.tiedot = nil or (not ei_ysa in $edellinen.tiedot and not ei_ys in $edellinen.tiedot))) then # "kissan+karva", "työhön+otto" if $oikea.sijamuoto = omanto then result $res, rules nimisana, nimisana_teonsanasta, yhdysmerkki_yleisnimen_jälkeen, nimisanan_etuliite; end; if $oikea.sijamuoto = nimentö and $oikea.luku = yksikkö then result $res, rules nimisana_teonsanasta; end; if $edellinen.luokka in then result $res, rules yhdysmerkki_laatusanan_jälkeen; end; if $oikea.sijamuoto = omanto then if $oikea.luku = yksikkö then result $res, rules laatusana, inen_johdos_nimisanasta; else result $res, rules nimisana_laatusanasta; end; end; end; end; end; combi_rule laatusanan_sijapääte ($vasen, $oikea, $sana, $index): ? $oikea.luokka = sijapääte; define $edellinen := $vasen.($index - 1); ? $oikea.sija in $edellinen.jatko; if $oikea.sija = sisätulento_Vn then ? sisätulento_Vn_oikein(last($edellinen.alku), $sana); elseif $oikea.sija = sisätulento_hVn then ? sisätulento_hVn_oikein(last($edellinen.alku), $sana); else ? vokaalisointu_oikein($edellinen, $oikea); end; if $oikea.äs = aä then $oikea.äs := $edellinen.äs; end; define $res := $vasen + <[alku: $sana] + $oikea>; if ($oikea.sija = kerronto_sti) then ? $edellinen.luokka in @sti_edeltäjä; result $res, accept; result $res, rules liitesana; else if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; if (tavuviiva in $oikea.jatko and ($edellinen.tiedot = nil or (not ei_ysa in $edellinen.tiedot and not ei_ys in $edellinen.tiedot))) then if $edellinen.aluetta_tarkentava_etuliite = yes then result $res, rules yhdysmerkki_ennen_paikannimea; end; if $oikea.sijamuoto = omanto and $edellinen.lähtöluokka /= nimi_laatusana then result $res, rules laatusana, laatusana_teonsanasta, tavuviiva; if $oikea.luku = yksikkö then result $res, rules inen_johdos_nimisanasta; end; end; end; end; end; combi_rule laatusanan_sijapääte_omistusliitteellä ($vasen, $oikea, $sana, $index): ? $oikea.luokka = sijapääte; define $edellinen := $vasen.($index - 1); ? $oikea.sija in $edellinen.jatko; if $oikea.sija = sisätulento_Vn then ? sisätulento_Vn_oikein(last($edellinen.alku), $sana); elseif $oikea.sija = sisätulento_hVn then ? sisätulento_hVn_oikein(last($edellinen.alku), $sana); else ? vokaalisointu_oikein($edellinen, $oikea); end; if $oikea.äs = aä then $oikea.äs := $edellinen.äs; end; define $res := $vasen + <[alku: $sana] + $oikea>; if ($oikea.sija = kerronto_sti) then ? $edellinen.luokka in @sti_edeltäjä; result $res, accept; result $res, rules liitesana; else if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; if (tavuviiva in $oikea.jatko and ($edellinen.tiedot = nil or (not ei_ysa in $edellinen.tiedot and not ei_ys in $edellinen.tiedot))) then if $oikea.sijamuoto = omanto then result $res, rules laatusana, nimisana_teonsanasta, tavuviiva; if $oikea.luku = yksikkö then result $res, rules inen_johdos_nimisanasta; end; end; if $edellinen.luokka in then result $res, rules yhdysmerkki_laatusanan_jälkeen; end; end; end; end; combi_rule ttU_sijapääte ($vasen, $oikea, $sana, $index): ? $oikea.luokka = sijapääte; define $edellinen := $vasen.($index - 1); ? $oikea.sija in $edellinen.jatko; if $oikea.sija = sisätulento_Vn then ? sisätulento_Vn_oikein(last($edellinen.alku), $sana); elseif $oikea.sija = sisätulento_hVn then ? sisätulento_hVn_oikein(last($edellinen.alku), $sana); else ? vokaalisointu_oikein($edellinen, $oikea); end; if $oikea.äs = aä then $oikea.äs := $edellinen.äs; end; define $res := $vasen + <[alku: $sana] + $oikea>; if ($oikea.sija = kerronto_sti) then ? $edellinen.luokka in @sti_edeltäjä; result $res, accept; result $res, rules liitesana; else if $oikea.sija = osanto_A and omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; if (tavuviiva in $oikea.jatko and ($edellinen.tiedot = nil or (not ei_ysa in $edellinen.tiedot and not ei_ys in $edellinen.tiedot))) then if $oikea.sijamuoto = omanto then result $res, rules laatusana, nimisana_teonsanasta, tavuviiva; if $oikea.luku = yksikkö then result $res, rules inen_johdos_nimisanasta; end; end; if $edellinen.luokka in then result $res, rules yhdysmerkki_laatusanan_jälkeen; end; end; end; end; combi_rule asemosanan_sijapääte ($vasen, $oikea, $sana, $index): ? $oikea.luokka = sijapääte; define $edellinen := $vasen.($index - 1); ? $oikea.sija in $edellinen.jatko; if $oikea.sija = sisätulento_Vn then ? sisätulento_Vn_oikein(last($edellinen.alku), $sana); elseif $oikea.sija = sisätulento_hVn then ? sisätulento_hVn_oikein(last($edellinen.alku), $sana); else ? vokaalisointu_oikein($edellinen, $oikea); end; if $oikea.äs = aä then $oikea.äs := $edellinen.äs; end; define $res := $vasen + <[alku: $sana] + $oikea>; if ($oikea.sija = kerronto_sti) then ? $edellinen.luokka in @sti_edeltäjä; result $res, accept; result $res, rules liitesana; else if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko and $oikea.sija /= omanto_nkA and $oikea.sija /= nimentö_tkA then result $res, rules liitesana; end; if $oikea.sijamuoto = omanto then result $res, rules inen_johdos_nimisanasta; end; end; end; # Sijapääte, jota ei voi käyttää yhdyssanan sisällä combi_rule ei_ys_sijapääte ($vasen, $oikea, $sana, $index): ? $oikea.luokka = sijapääte; define $edellinen := $vasen.($index - 1); ? $oikea.sija in $edellinen.jatko; if $oikea.sija = sisätulento_Vn then ? sisätulento_Vn_oikein(last($edellinen.alku), $sana); elseif $oikea.sija = sisätulento_hVn then ? sisätulento_hVn_oikein(last($edellinen.alku), $sana); else ? vokaalisointu_oikein($edellinen, $oikea); end; if $oikea.äs = aä then $oikea.äs := $edellinen.äs; end; define $res := $vasen + <[alku: $sana] + $oikea>; if ($oikea.sija = kerronto_sti) then ? $edellinen.luokka in @sti_edeltäjä; result $res, accept; result $res, rules liitesana; else if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; end; end; combi_rule kaksoispisteen_sijapääte ($vasen, $oikea, $sana, $index): ? $oikea.luokka = sijapääte; # sisätulento_Vn kielletty, koska kaksoispisteellä taivutettaessa pitkä vokaali # laitetaan aina näkyviin. ? not $oikea.sija in ; ? not ei_kaksoispisteen_jälkeen in $oikea; define $edellinen := $vasen.($index - 1); ? vokaalisointu_oikein($edellinen, $oikea); if $oikea.äs = aä then $oikea.äs := $edellinen.äs; end; define $res := $vasen + <[alku: $sana] + $oikea>; if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; end; ###### SIJAPÄÄTESÄÄNNÖT PÄÄTTYVÄT ###### LUKUSANASÄÄNNÖT ALKAVAT combi_rule lukusana ($vasen, $oikea, $sana, $index): ? $oikea.luokka = lukusana; define $sijamuoto := nil; define $luku := nil; if ($oikea.alaluokka = erikoisluku) then define $erikoisres := $vasen + <[alku: $sana] + $oikea>; if (loppu in $oikea.jatko) then result $erikoisres, accept; end; if (liitesana in $oikea.jatko) then result $erikoisres, rules liitesana; end; if (lukusanan_jälkiliite in $oikea.jatko) then result $erikoisres, rules lukusanan_jälkiliite; end; stop; end; if ($index greater 1) then define $edellinen := $vasen.($index - 1); ? $edellinen.lukutyyppi = nil or $edellinen.lukutyyppi = $oikea.lukutyyppi; $sijamuoto := $edellinen.sijamuoto; $luku := $edellinen.luku; # Estetään peräkkäiset "satasata", "tuhattuhat" jne. if ($edellinen.luokka = lukusana) then ? not ($oikea.alaluokka = $edellinen.alaluokka); end; end; define $res := $vasen + <[alku: $sana, sijamuoto: $sijamuoto, luku: $luku] + $oikea>; if ($oikea.alaluokka = yksiyhdeksän) then if (nimentö in $oikea.jatko) then if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; if tavuviiva in $oikea.jatko then result $res, rules lukusana_toista, lukusana_sisäkerroin, lukusanan_jälkiliite, nimisana, inen_johdos_nimisanasta, inen_päätteinen_laatusana; end; end; if ($oikea.lukutyyppi = järjestysluku and omistusliite in $oikea.jatko) then result $res, rules omistusliite; end; elseif ($oikea.alaluokka in ) then if (nimentö in $oikea.jatko) then if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; result $res, rules lukusana_sisäkerroin, lukusanan_jälkiliite, nimisana, inen_johdos_nimisanasta, inen_päätteinen_laatusana; end; elseif ($oikea.alaluokka in and nimentö in $oikea.jatko) then if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; result $res, rules lukusanan_jälkiliite, nimisana, inen_johdos_nimisanasta, inen_päätteinen_laatusana; elseif ($oikea.alaluokka = numeromerkki) then $res := $vasen + <[alku: $sana, pilkku: no, rakenne: "q"] + $oikea>; result $res, rules lukusana_numero, merkki_numeron_jälkeen; result $res, accept; end; if ($oikea.alaluokka in ) then if (nimentö in $oikea.jatko) then result $res, rules lukusana; end; end; result $res, rules lukusana_sijapääte; end; combi_rule lukusana_sijapääte ($vasen, $oikea, $sana, $index): ? $oikea.luokka = sijapääte; define $edellinen := $vasen.($index - 1); ? $oikea.sija in $edellinen.jatko; ? vokaalisointu_oikein($edellinen, $oikea); if $oikea.äs = aä then $oikea.äs := $edellinen.äs; end; ? $edellinen.sijamuoto = nil or $edellinen.sijamuoto = $oikea.sijamuoto; ? $edellinen.luku = nil or $edellinen.luku = $oikea.luku; ? $oikea.sija /= sisätulento_Vn or sisätulento_Vn_oikein(last($edellinen.alku), $sana); ? $edellinen.lukutyyppi /= järjestysluku or $oikea.sija /= kerronto_sti; define $res := $vasen + <[alku: $sana, lukutyyppi: $edellinen.lukutyyppi] + $oikea>; if ($edellinen.alaluokka = yksiyhdeksän) then if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; result $res, rules lukusana_toista, lukusana_sisäkerroin, lukusanan_jälkiliite, nimisana, inen_johdos_nimisanasta, inen_päätteinen_laatusana; elseif ($edellinen.alaluokka = kymmenen) then if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; result $res, rules lukusana_sisäkerroin, lukusanan_jälkiliite; else result $res, rules nimisana, lukusanan_jälkiliite, inen_johdos_nimisanasta, inen_päätteinen_laatusana; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; if loppu in $oikea.jatko then result $res, accept; end; if ($edellinen.alaluokka in ) then result $res, rules lukusana; end; end; combi_rule lukusana_sisäkerroin ($vasen, $oikea, $sana, $index): ? $oikea.luokka = lukusana; ? $oikea.alaluokka in ; define $edellinen := $vasen.($index - 1); ? $edellinen.lukutyyppi = $oikea.lukutyyppi; define $res := $vasen + <[alku: $sana, sijamuoto: $edellinen.sijamuoto, luku: $edellinen.luku] + $oikea>; if ($edellinen.sijamuoto in ) then result $res, rules lukusana_sisäkerroin_osanto; else result $res, rules lukusana_sisäkerroin_sijapääte; end; if ($oikea.lukutyyppi = järjestysluku) then result $res, rules lukusana; end; if ($oikea.lukutyyppi = järjestysluku and loppu in $oikea.jatko) then if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; result $res, accept; end; end; combi_rule lukusana_sisäkerroin_sijapääte ($vasen, $oikea, $sana, $index): ? $oikea.luokka = sijapääte; define $edellinen := $vasen.($index - 1); ? $oikea.sija in $edellinen.jatko; ? vokaalisointu_oikein($edellinen, $oikea); if $oikea.äs = aä then $oikea.äs := $edellinen.äs; end; ? $edellinen.sijamuoto = nil or $edellinen.sijamuoto = $oikea.sijamuoto; ? $edellinen.luku = nil or $edellinen.luku = $oikea.luku; define $res := $vasen + <[alku: $sana, lukutyyppi: $edellinen.lukutyyppi] + $oikea>; if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; result $res, rules lukusana, lukusanan_jälkiliite, nimisana, inen_johdos_nimisanasta, inen_päätteinen_laatusana; end; combi_rule lukusana_sisäkerroin_osanto ($vasen, $oikea, $sana, $index): ? $oikea.luokka = sijapääte; define $edellinen := $vasen.($index - 1); ? $oikea.sija in $edellinen.jatko; ? $oikea.sijamuoto = osanto; ? vokaalisointu_oikein($edellinen, $oikea); if $oikea.äs = aä then $oikea.äs := $edellinen.äs; end; define $res := $vasen + <$oikea + [alku: $sana, lukutyyppi: $edellinen.lukutyyppi, sijamuoto: nil]>; if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; result $res, rules lukusana, lukusanan_jälkiliite, nimisana, inen_johdos_nimisanasta, inen_päätteinen_laatusana; end; combi_rule lukusana_toista ($vasen, $oikea, $sana, $index): ? $oikea.luokka = lukusana; ? $oikea.alaluokka = toista; define $edellinen := $vasen.($index - 1); define $res := $vasen + <[alku: $sana, sijamuoto: $edellinen.sijamuoto, luku: $edellinen.luku, lukutyyppi: $edellinen.lukutyyppi] + $oikea>; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; result $res, rules lukusana_sisäkerroin, lukusanan_jälkiliite, nimisana, inen_johdos_nimisanasta, inen_päätteinen_laatusana; end; combi_rule lukusanan_jälkiliite ($vasen, $oikea, $sana, $index): ? $oikea.luokka in ; # FIXME: yhdysviivan käyttöä ei vielä tueta lukusanan ja sen jälkiliitteen välissä define $res := $vasen + <[alku: $sana] + $oikea>; define $edellinen := $vasen.($index - 1); if $oikea.luokka = tavuviiva then if $edellinen.luokka /= tavuviiva then result $res, accept; end; else ? $edellinen.lukutyyppi = nil or $edellinen.lukutyyppi = $oikea.lukutyyppi; if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if tavuviiva in $oikea.jatko then result $res, rules yhdysmerkki_yleisnimen_jälkeen; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; result $res, rules ei_ys_sijapääte, nimisana, etuliite, nimisanan_johdos, nimisana_laatusanasta, nimisana_teonsanasta; end; end; combi_rule lukusana_numero ($vasen, $oikea, $sana, $index): ? $oikea.luokka = lukusana; define $edellinen := $vasen.($index - 1); $oikea :=+ [pilkku: $edellinen.pilkku]; define $res := $vasen + <[alku: $sana] + $oikea>; if $oikea.alaluokka = numeromerkki then result $res, rules lukusana_numero, merkki_numeron_jälkeen; result $res, accept; elseif $oikea.alaluokka = pilkku and $oikea.pilkku /= yes then $oikea :=+ [pilkku: yes]; result $vasen + <[alku: $sana] + $oikea>, rules lukusana_numero; elseif $oikea.alaluokka = piste and $oikea.pilkku /= yes then result $res, rules lukusana_pvm_kk; end; end; combi_rule lukusana_pvm_kk($vasen, $oikea, $sana, $index): ? $oikea.luokka = lukusana; define $edellinen := $vasen.($index - 1); define $res := $vasen + <[alku: $sana] + $oikea>; if $oikea.alaluokka = numeromerkki then result $res, rules lukusana_pvm_kk; elseif $oikea.alaluokka = piste then # sallitaan enemmänkin pisteitä, esim. IP-osoitteet result $res, rules lukusana_numero_tai_piste; # sallitaan päivämäärä ilman vuotta (12.4.) result $res, accept; end; end; combi_rule lukusana_numero_tai_piste($vasen, $oikea, $sana, $index): ? $oikea.luokka = lukusana; define $edellinen := $vasen.($index - 1); define $res := $vasen + <[alku: $sana] + $oikea>; if $oikea.alaluokka = numeromerkki then result $res, rules lukusana_numero_tai_piste; result $res, accept; elseif $oikea.alaluokka = piste then result $res, rules lukusana_numero_tai_piste; end; end; ###### LUKUSANASÄÄNNÖT PÄÄTTYVÄT combi_rule teonsana ($vasen, $oikea, $sana, $index): ? $oikea.luokka = teonsana; if ($index greater 1) then ? tavuviiva in $vasen.($index - 1).jatko; ? vokaaliehdollinen_yhdysviiva_ok($vasen, $sana); ? $oikea.tiedot = nil or (not ei_ysj in $oikea.tiedot and not ei_ys in $oikea.tiedot); else ? $oikea.tiedot = nil or (not ysj in $oikea.tiedot); end; define $res := $vasen + <[alku: $sana] + $oikea>; if tavuviiva in $oikea.jatko then result $res, rules yhdysmerkki_teonsanan_jälkeen; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; if liitesana_pi in $oikea.jatko then result $res, rules liitesana_pi; end; result $res, rules tekijämuodot, nimitavat, teonsanan_johdos; end; combi_rule tekijämuodot ($vasen, $oikea, $sana, $index): ? $oikea.luokka in @kestämän_tekijäpääte + @tositavan_tekijäpääte_4 + @kertoman_tekijäpääte + @ehtotapa + @mahtotapa + @käskytapa; define $edellinen := $vasen.($index - 1); ? $oikea.luokka in $edellinen.jatko; ? vokaalisointu_oikein($edellinen, $oikea); ? $oikea.luokka /= kestämän_tekijäpääte_y3 or taivutusvokaali(last($edellinen.alku)) = $sana; ? $oikea.tekijä = nil or $edellinen.tiedot = nil or ( ((not yt in $edellinen.tiedot) or (not $oikea.tekijä in and not $oikea.luku = monikko)) and ((not ym3 in $edellinen.tiedot) or (not $oikea.tekijä in )) ); if $oikea.äs = aä then $oikea.äs := $edellinen.äs; end; if $edellinen.tapaluokka = mahtotapa and $oikea.luokka in @kestämän_tekijäpääte then $oikea.tapaluokka := mahtotapa; end; define $res := $vasen + <[alku: $sana] + $oikea>; result $res, accept; if (liitesana in $oikea.jatko) then result $res, rules liitesana; end; if (liitesana_pi in $oikea.jatko) then result $res, rules liitesana_pi; end; end; ###### NIMITAPASÄÄNNÖT ALKAVAT combi_rule nimitapa_4 ($vasen, $oikea, $sana, $index): ? $oikea.luokka = nimitapa_45 and $oikea.tapaluokka = nimitapa_4; if $oikea.äs = aä then $oikea.äs := $vasen.($index - 1).äs; end; define $res := $vasen + <[alku: $sana] + $oikea>; if (tavuviiva in $oikea.jatko) then result $res, rules nimisana, nimisana_laatusanasta, yhdysmerkki_sanan_lopussa; end; if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; result $res, rules nimisanan_sijapääte; end; ###### NIMITAPASÄÄNNÖT PÄÄTTYVÄT combi_rule nimitavat ($vasen, $oikea, $sana, $index): ? $oikea.luokka in @nimitapa_1 + @nimitapa_2 + @nimitapa_3 + ; define $edellinen := $vasen.($index - 1); ? $oikea.luokka in $edellinen.jatko; ? vokaalisointu_oikein($edellinen, $oikea); if $oikea.äs = aä then $oikea.äs := $edellinen.äs; end; define $res := $vasen + <[alku: $sana] + $oikea>; if (tavuviiva in $oikea.jatko) then result $res, rules yhdysmerkki_sanan_lopussa, nimisana, laatusana, nimisana_teonsanasta, inen_johdos_nimisanasta_ehdollinen; end; if (nimitapa_1_pitkä in $oikea.jatko) then result $res, rules nimitapa_1_pitkä; end; if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; result $res, rules nimisanan_sijapääte; end; combi_rule nimitapa_1_pitkä ($vasen, $oikea, $sana, $index): ? $oikea.luokka = nimitapa_1_pitkä; if $oikea.äs = aä then $oikea.äs := $vasen.($index - 1).äs; end; result $vasen + <[alku: $sana] + $oikea>, rules omistusliite; end; combi_rule kieltosana ($vasen, $oikea, $sana): # Esiehto: tämä sääntö on aina järjestyksessä toisen allomorfin sääntö, # ensimmäinen allomorfi on kieltosanan_etuliite. ? $oikea.luokka = kieltosana; ? $oikea.tapaluokka = tositapa; define $äs := ä; if $oikea.äs /= nil then $äs := $oikea.äs; elseif ($vasen.1).äs /= nil then $äs := ($vasen.1).äs; end; define $res := $vasen + <[alku: $sana] + $oikea + [äs: $äs]>; if kieltosanan_liitesana in $oikea.jatko then result $res, rules yhdyskieltosanan_liitesana; end; if loppu in $oikea.jatko then result $res, accept; end; end; ###### LIITESANASÄÄNNÖT ALKAVAT combi_rule liitesana ($vasen, $oikea, $sana, $index): ? $oikea.luokka = liitesana; define $edellinen := $vasen.($index - 1); ? vokaalisointu_oikein($edellinen, $oikea); if ($edellinen.tapaluokka = käskytapa) then ? not ($sana in <"ko", "kö">); if (($edellinen.tekijä /= tekijä_2) or ($edellinen.luku /= yksikkö)) then ? not ($sana in <"kaan", "kään">); end; end; if ($edellinen.kielto /= nil and $oikea.kielto /= no) then result $vasen + <$oikea + [alku: $sana, kielto: $edellinen.kielto]>, accept; else result $vasen + <$oikea + [alku: $sana]>, accept; end; end; cimbi_rule liitesana_pi ($vasen, $oikea, $sana, $index): ? $oikea.luokka = liitesana_pi; result $vasen + <[alku: $sana] + $oikea>, accept; end; ###### LIITESANASÄÄNNÖT PÄÄTTYVÄT combi_rule kieltosanan_liitesana ($vasen, $oikea, $sana, $index): ? $oikea.luokka = kieltosanan_liitesana; define $edellinen := $vasen.($index - 1); ? ($edellinen.äs = $oikea.äs) or ($oikea.äs = ä and $edellinen.äs /= a); if loppu in $oikea.jatko then result $vasen + <[alku: $sana] + $oikea>, accept; end; end; combi_rule yhdyskieltosanan_liitesana ($vasen, $oikea, $sana, $index): ? $oikea.luokka = liitesana; ? vokaalisointu_oikein($vasen.($index - 1), $oikea); if loppu in $oikea.jatko then result $vasen + <[alku: $sana] + $oikea>, accept; end; end; combi_rule omistusliite ($vasen, $oikea, $sana, $index): ? $oikea.luokka = omistusliite; define $edellinen := $vasen.($index - 1); ? vokaalisointu_oikein($edellinen, $oikea); if $oikea.äs = aä then $oikea.äs := $edellinen.äs; end; define $result := $vasen + <[alku: $sana] + $oikea>; if ($sana in <"ni", "si", "nsa", "nsä", "mme", "nne">) then result $result, accept; result $result, rules liitesana; elseif (omistusliite3_oikein(last($edellinen.alku), $sana)) then if ($edellinen.luokka in ) or ($edellinen.luokka = nimisana and $edellinen.sijamuoto /= nil) then if (not ($edellinen.alku matches ".*(aa|ee|ii|oo|uu|yy|ää|öö)")) then result $result, accept; result $result, rules liitesana; end; elseif ($edellinen.luokka = sijapääte) then if (($edellinen.sija in )) or ($edellinen.sija = osanto_A and not last($vasen.($index - 2).alku) in <"a", "ä">) then result $result, accept; result $result, rules liitesana; end; elseif ($edellinen.luokka in or $edellinen.tapaluokka = nimitapa_5) then result $result, accept; # "puhuakseen" result $result, rules liitesana; end; end; end; combi_rule voittoaste ($vasen, $oikea, $sana, $index): ? $oikea.luokka = voittoaste; define $edellinen := $vasen.($index - 1); ? vokaalisointu_oikein($edellinen, $oikea); if $oikea.äs = aä then $oikea.äs := $edellinen.äs; end; define $res := $vasen + <[alku: $sana] + $oikea>; if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; result $res, rules voitto_yliasteen_sijapääte, inen_johdos_nimisanasta; end; combi_rule voitto_yliaste ($vasen, $oikea, $sana, $index): ? $oikea.luokka in ; define $edellinen := $vasen.($index - 1); ? $oikea.luokka in $edellinen.jatko; ? vokaalisointu_oikein($edellinen, $oikea); if $oikea.äs = aä then $oikea.äs := $edellinen.äs; end; define $res := $vasen + <[alku: $sana] + $oikea>; if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; result $res, rules voitto_yliasteen_sijapääte; if ($oikea.luokka = voittoaste) then result $res, rules inen_johdos_nimisanasta, inen_päätteinen_laatusana; end; if johdin_UUs in $oikea.jatko then result $res, rules johdin_nimisana_laatusanasta; end; end; combi_rule johdin_seikkasana_ittain($vasen, $oikea, $sana, $index): ? $oikea.luokka = johdin_ittAin; define $edellinen := $vasen.($index - 1); ? vokaalisointu_oikein($edellinen, $oikea); define $res := $vasen + <[alku: $sana] + $oikea>; result $res, rules liitesana; result $res, accept; end; combi_rule teonsanan_johdos ($vasen, $oikea, $sana, $index): ? $oikea.luokka in @johdin_teonsanasta + ; define $edellinen := $vasen.($index - 1); ? $oikea.luokka in $edellinen.jatko; ? $oikea.luokka /= johdin_inen or not $edellinen.luokka in or $index greater 3; ? vokaalisointu_oikein($edellinen, $oikea); if $oikea.äs = aä then $oikea.äs := $edellinen.äs; end; if ($edellinen.luokka = teonsana) then $vasen.($index - 1) :=+ [lähtöluokka: teonsana]; if $oikea.luokka in @johtimet_laatusana_teonsanasta then $vasen.($index - 1).luokka := laatusana; else $vasen.($index - 1).luokka := nimisana; end; end; define $res := $vasen + <[alku: $sana] + $oikea>; if ($oikea.luokka in + @johdin_jA) or $oikea.jluokka = nimisana then result $res, rules nimisanan_sijapääte; elseif $oikea.luokka = johdin_lUt then result $res, rules laatusanan_sijapääte; elseif $oikea.laatutapa = johdin_ttU then result $res, rules ttU_sijapääte; else result $res, rules laatusanan_sijapääte_omistusliitteellä; end; if tavuviiva in $oikea.jatko then if ($oikea.luokka in + @johdin_jA) or $oikea.jluokka in then result $res, rules nimisana, nimisana_teonsanasta, inen_päätteinen_laatusana_ei_nimisanajohdosta, nimisana_laatusanasta, inen_johdos_nimisanasta_ehdollinen, nimisanan_etuliite, yhdysmerkki_yleisnimen_jälkeen; else result $res, rules inen_johdos_nimisanasta, yhdysmerkki_laatusanan_jälkeen, inen_päätteinen_laatusana; end; end; if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; result $res, rules teonsanan_johdos, voitto_yliaste; end; combi_rule nimisanan_johdos ($vasen, $oikea, $sana, $index): ? $oikea.luokka in @johdin_nimisanasta + ; define $edellinen := $vasen.($index - 1); ? $oikea.luokka in $edellinen.jatko; ? $oikea.luokka /= johdin_UUs or (not $edellinen.luokka in and $edellinen.lähtöluokka /= nimi_laatusana); ? vokaalisointu_oikein($edellinen, $oikea); if $oikea.äs = aä then $oikea.äs := $edellinen.äs; end; define $res := $vasen + <[alku: $sana] + $oikea>; if ($oikea.luokka = johdin_inen) then if ($edellinen.tiedot /= nil and inen in $edellinen.tiedot) and (($index = 2) or (not ($vasen.($index - 2).luokka in ) and ($vasen.($index - 2).sijamuoto /= omanto or $vasen.($index - 2).luku /= yksikkö)) or ($index greater 3 and $vasen.($index - 3).lukutyyppi /= nil)) then if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if tavuviiva in $oikea.jatko then result $res, rules yhdysmerkki_inen_johdoksen_jälkeen; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; result $res, rules laatusanan_sijapääte_omistusliitteellä, inen_johdos_nimisanasta, voitto_yliaste, johdin_nimisana_laatusanasta; end; stop; end; if tavuviiva in $oikea.jatko then result $res, rules nimisana, nimisana_teonsanasta, etuliite, tavuviiva, inen_johdos_nimisanasta; end; if omistusliite in $oikea.jatko and not $oikea.luokka in @johtimet_laatusana_nimisanasta then result $res, rules omistusliite; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; if $oikea.luokka in @johtimet_nimisana_nimisanasta + then result $res, rules nimisanan_sijapääte, nimisanan_johdos; elseif $oikea.luokka in @johtimet_laatusana_nimisanasta then result $res, rules laatusana, laatusanan_sijapääte, voitto_yliaste, johdin_nimisana_laatusanasta; elseif $oikea.luokka in @johdin_jA then result $res, rules nimisanan_sijapääte, johdin_nimisana_laatusanasta, nimisanan_johdos; if tavuviiva in $oikea.jatko then result $res, rules inen_päätteinen_laatusana_ei_nimisanajohdosta, nimisana_laatusanasta; end; end; end; combi_rule johdin_laatusana_teonsanasta ($vasen, $oikea, $sana, $index): ? $oikea.luokka in @johtimet_laatusana_teonsanasta + ; define $edellinen := $vasen.($index - 1); ? $oikea.luokka in $edellinen.jatko; ? vokaalisointu_oikein($edellinen, $oikea); if $oikea.äs = aä then $oikea.äs := $edellinen.äs; end; if ($edellinen.luokka = teonsana) then $vasen.($index - 1) :=+ [lähtöluokka: teonsana]; if $oikea.luokka in @johtimet_laatusana_teonsanasta then $vasen.($index - 1).luokka := laatusana; else $vasen.($index - 1).luokka := nimisana; end; end; define $res := $vasen + <[alku: $sana] + $oikea>; if $oikea.luokka = johdin_lUt then result $res, rules laatusanan_sijapääte; else result $res, rules laatusanan_sijapääte_omistusliitteellä; end; if tavuviiva in $oikea.jatko then result $res, rules inen_johdos_nimisanasta, yhdysmerkki_laatusanan_jälkeen, inen_päätteinen_laatusana; end; if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; result $res, rules teonsanan_johdos, voitto_yliaste; end; combi_rule johdin_laatusana_nimisanasta ($vasen, $oikea, $sana, $index): ? $oikea.luokka in @johtimet_laatusana_nimisanasta; define $edellinen := $vasen.($index - 1); ? $oikea.luokka in $edellinen.jatko; ? vokaalisointu_oikein($edellinen, $oikea); if $oikea.äs = aä then $oikea.äs := $edellinen.äs; end; define $res := $vasen + <[alku: $sana] + $oikea>; if ($oikea.luokka = johdin_inen) then if ($edellinen.tiedot /= nil and inen in $edellinen.tiedot) and (($index = 2) or (not ($vasen.($index - 2).luokka in ) and ($vasen.($index - 2).sijamuoto /= omanto or $vasen.($index - 2).luku /= yksikkö)) or ($index greater 3 and $vasen.($index - 3).lukutyyppi /= nil)) then if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if tavuviiva in $oikea.jatko then result $res, rules yhdysmerkki_yleisnimen_jälkeen; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; result $res, rules laatusanan_sijapääte_omistusliitteellä, inen_johdos_nimisanasta, voitto_yliaste, johdin_nimisana_laatusanasta; end; stop; end; if tavuviiva in $oikea.jatko then result $res, rules nimisana, laatusana, nimisana_teonsanasta, etuliite, tavuviiva, inen_johdos_nimisanasta; end; if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; result $res, rules laatusanan_sijapääte, voitto_yliaste, johdin_nimisana_laatusanasta; end; combi_rule johdin_nimisana_laatusanasta ($vasen, $oikea, $sana, $index): ? $oikea.luokka in @johtimet_nimisana_laatusanasta; define $edellinen := $vasen.($index - 1); ? $oikea.luokka in $edellinen.jatko; ? vokaalisointu_oikein($edellinen, $oikea); if $oikea.äs = aä then $oikea.äs := $edellinen.äs; end; define $res := $vasen + <[alku: $sana] + $oikea>; if tavuviiva in $oikea.jatko and ($edellinen.tiedot = nil or (not ei_ysa in $edellinen.tiedot and not ei_ys in $edellinen.tiedot)) then result $res, rules nimisana, laatusana, nimisana_teonsanasta, etuliite, tavuviiva, inen_johdos_nimisanasta; end; if $index greater 2 and johdin_inen in $oikea.jatko then result $res, rules johdin_inen; end; if omistusliite in $oikea.jatko then result $res, rules omistusliite; end; if loppu in $oikea.jatko then result $res, accept; end; if liitesana in $oikea.jatko then result $res, rules liitesana; end; result $res, rules nimisanan_sijapääte, nimisanan_johdos; end; subrule sisätulento_Vn_oikein ($ed_kirjain, $sana): return ((($ed_kirjain matches @a) and ($sana matches "an?")) or (($ed_kirjain matches @e) and ($sana matches "en?")) or (($ed_kirjain matches @i) and ($sana matches "in?")) or (($ed_kirjain matches @o) and ($sana matches "on?")) or (($ed_kirjain matches @u) and ($sana matches "un?")) or (($ed_kirjain matches @y) and ($sana matches "yn?")) or (($ed_kirjain matches @ä) and ($sana matches "än?")) or (($ed_kirjain matches @ö) and ($sana matches "ön?"))); end; subrule sisätulento_hVn_oikein ($ed_kirjain, $sana): return ((($ed_kirjain matches @a) and ($sana matches "han?")) or (($ed_kirjain matches @e) and ($sana matches "hen?")) or (($ed_kirjain matches @i) and ($sana matches "hin?")) or (($ed_kirjain matches @o) and ($sana matches "hon?")) or (($ed_kirjain matches @u) and ($sana matches "hun?")) or (($ed_kirjain matches @y) and ($sana matches "hyn?")) or (($ed_kirjain matches @ä) and ($sana matches "hän?")) or (($ed_kirjain matches @ö) and ($sana matches "hön?")) or (($ed_kirjain = "'"))); # Parfait'hen yms. end; # Onko vokaalisointu oikein silloin, kun tiedetään, että $oikea.äs ei ole aä subrule vokaalisointu_oikein_ei_aä($edellinen, $oikea): return ($edellinen.äs = aä or $oikea.äs = $edellinen.äs); end; # Onko vokaalisointu oikein silloin, kun $oikea.äs voi olla aä subrule vokaalisointu_oikein($edellinen, $oikea): return ($oikea.äs = aä or $edellinen.äs = aä or $oikea.äs = $edellinen.äs); end; subrule omistusliite3_oikein ($kirjain, $liite): return ((($liite = "an") and ($kirjain matches @a)) or (($liite = "en") and ($kirjain matches @e)) or (($liite = "in") and ($kirjain matches @i)) or (($liite = "on") and ($kirjain matches @o)) or (($liite = "un") and ($kirjain matches @u)) or (($liite = "yn") and ($kirjain matches @y)) or (($liite = "än") and ($kirjain matches @ä)) or (($liite = "ön") and ($kirjain matches @ö))); end; # Taivutuspäätteessä annettua kirjainta vastaava pidennetty vokaali subrule taivutusvokaali($kirjain): if ($kirjain matches @a) then return "a"; elseif ($kirjain matches @e) then return "e"; elseif ($kirjain matches @i) then return "i"; elseif ($kirjain matches @o) then return "o"; elseif ($kirjain matches @u) then return "u"; elseif ($kirjain matches @y) then return "y"; elseif ($kirjain matches @ä) then return "ä"; elseif ($kirjain matches @ö) then return "ö"; end; return ""; end; ##################################################### output_filter tulosta ($tulos): foreach $j in length ($tulos): result tulostus_v2($tulos.$j); end; end; # Palauttaa tietueen rakenne-kentän mukaisen rakennekuvauksen oikean mittaisena. # Jos $pienet_kirjaimet = yes, niin rakenteen i-merkit muutetaan p-merkeiksi. subrule rakenne ($tietue, $pienet_kirjaimet): define $alen := length($tietue.alku); define $i := 0; define $tuloste := "="; define $kirjain := ""; foreach $k in length($tietue.rakenne): $kirjain := substring($tietue.rakenne, $k); if $i less $alen then if $kirjain = "=" then $tuloste :=+ "="; else if $pienet_kirjaimet and $kirjain = "i" then $tuloste :=+ "p"; else $tuloste :=+ $kirjain; end; $i :=+ 1; end; end; end; if $i less $alen then foreach $j in $alen - $i: $tuloste :=+ "p"; end; end; return $tuloste; end; subrule tulostus_rakenne ($tietue): define $tuloste := ""; define $tlen := length($tietue); define $tind := 0; define $arvattu_erisnimi := no; foreach $t in $tietue: $tind :=+ 1; if $t.rakenne /= nil then if ($t.luokka = paikannimi and ( ($tlen greater $tind and $tietue.($tind+1).luokka = johdin_lAinen) or ($tlen greater $tind + 2 and $tietue.($tind+3).luokka = johdin_lAinen) ) ) then $tuloste :=+ rakenne($t, yes); else $tuloste :=+ rakenne($t, no); end; elseif $t.luokka in or ($t.luokka = lukusana and not $t.alaluokka in ) then $tuloste :=+ "="; if $t.aluetta_tarkentava_etuliite = yes and (($tind + 1 = $tlen and $tietue.($tind+1).luokka = tavuviiva) or ($tlen + 1 greater $tind and $tietue.($tind+1).luokka = tavuviiva and $tietue.($tind+2).luokka = paikannimi) or ($tlen + 2 greater $tind and $tietue.($tind+1).luokka in and $tietue.($tind+2).luokka = tavuviiva and $tietue.($tind+3).luokka = paikannimi)) then $tuloste :=+ "i"; else $tuloste :=+ "p"; end; foreach $i in length($t.alku) - 1: $tuloste :=+ "p"; end; elseif $t.luokka in then $tuloste :=+ "="; if ($t.luokka = paikannimi and ( ($tlen greater $tind and $tietue.($tind+1).luokka = johdin_lAinen) or ($tlen greater $tind + 2 and $tietue.($tind+3).luokka = johdin_lAinen) or ($tlen greater $tind + 1 and $tietue.($tind+1).luokka = sijapääte and $tietue.($tind+2).inen_loppu = yes) ) ) or $t.erisnimen_pääte = yes then foreach $i in length($t.alku): $tuloste :=+ "p"; end; if $t.erisnimen_pääte = yes then $arvattu_erisnimi := yes; end; else $tuloste :=+ "i"; foreach $i in length($t.alku) - 1: $tuloste :=+ "p"; end; end; elseif $t.luokka = lyhenne then $tuloste :=+ "="; foreach $i in length($t.alku): $tuloste :=+ "q"; end; elseif $t.luokka = tavuviiva then $tuloste :=+ "-"; elseif $t.luokka = kaksoispiste then $tuloste :=+ ":"; elseif $t.luokka = lukusana then $tuloste :=+ "q"; else foreach $i in length($t.alku): $tuloste :=+ "p"; end; end; end; if $arvattu_erisnimi = yes then return "=i" + substring($tuloste, 3, length($tuloste)); end; return $tuloste; end; subrule tulostus_luokka($tietue): define $tlen := length($tietue); define $omistusliite := no; foreach $i in $tlen: define $allomorfi := $tietue.($tlen + 1 - $i); if $allomorfi.jluokka /= nil then return $allomorfi.jluokka; end; if $allomorfi.luokka = johdin_inen then return laatusana; end; if $allomorfi.luokka in @johtimet_laatusana_nimisanasta then if $omistusliite then return nimisana; else return laatusana; end; end; if $allomorfi.luokka in then return $allomorfi.luokka; end; if $allomorfi.luokka = tavuviiva then return etuliite; end; if $allomorfi.luokka = lyhenne then if $allomorfi.alaluokka = roomalainen then return lukusana; end; return lyhenne; end; if $allomorfi.luokka in @johtimet_nimisana_laatusanasta then return nimisana; end; if $allomorfi.luokka = johdin_ittAin then return seikkasana; end; if $allomorfi.luokka = johdin_lAinen then return laatusana; end; if $allomorfi.luokka = omistusliite then $omistusliite := yes; end; end; return nil; end; subrule tulostus_sijamuoto($tietue): define $tlen := length($tietue); foreach $i in $tlen: define $allomorfi := $tietue.($tlen + 1 - $i); if $allomorfi.sijamuoto /= nil then return $allomorfi.sijamuoto; end; if $allomorfi.luokka in then return nil; end; if $allomorfi.alaluokka = erikoisluku then return nil; end; if $allomorfi.tapaluokka = nimitapa_5 then return nil; end; if $allomorfi.luokka in then return nimentö; end; end; return nil; end; subrule tulostus_luku($tietue): define $tlen := length($tietue); foreach $i in $tlen: define $allomorfi := $tietue.($tlen + 1 - $i); if $allomorfi.luku /= nil then return $allomorfi.luku; end; if $allomorfi.luokka in then return nil; end; if $allomorfi.sija = kerronto_sti then return nil; end; if $allomorfi.alaluokka = erikoisluku then return nil; end; if $allomorfi.tapaluokka = nimitapa_5 then return nil; end; if $allomorfi.luokka in then return yksikkö; end; end; return nil; end; subrule tulostus_tekijä($tietue): define $tlen := length($tietue); foreach $i in $tlen: define $allomorfi := $tietue.($tlen + 1 - $i); if $allomorfi.tekijä /= nil then return $allomorfi.tekijä; end; end; return nil; end; subrule tulostus_tapaluokka($tietue): define $tlen := length($tietue); foreach $i in $tlen: define $allomorfi := $tietue.($tlen + 1 - $i); if $allomorfi.tapaluokka /= nil then return $allomorfi.tapaluokka; end; end; return nil; end; subrule tulostus_aikamuoto($tietue): define $tlen := length($tietue); foreach $i in $tlen: define $allomorfi := $tietue.($tlen + 1 - $i); if $allomorfi.aikamuoto /= nil then return $allomorfi.aikamuoto; end; if $allomorfi.luokka in @kestämän_tekijäpääte then return kestämä; end; if $allomorfi.luokka in @kertoman_tekijäpääte then return kertoma; end; end; return nil; end; subrule tulostus_vertailu($tietue): define $tlen := length($tietue); foreach $i in $tlen: define $allomorfi := $tietue.($tlen + 1 - $i); if $allomorfi.luokka in then return $allomorfi.luokka; end; if $allomorfi.luokka = nimisana then return perusaste; end; end; return perusaste; end; subrule tulostus_partisiipit($tietue): define $tlen := length($tietue); foreach $i in $tlen: define $allomorfi := $tietue.($tlen + 1 - $i); if $allomorfi.laatutapa /= nil then return [laatutapa: $allomorfi.laatutapa]; end; if $allomorfi.jluokka = nimisana then return []; end; if $allomorfi.luokka = johdin_vA then return [laatutapa: johdin_vA]; end; if $allomorfi.luokka in then return [laatutapa: johdin_tAvA]; end; if $allomorfi.luokka in @johdin_nUt then return [laatutapa: johdin_nUt]; end; if $allomorfi.luokka = johdin_tOn and $i less $tlen and ($tietue.($tlen - $i).luokka = johdin_mA or $tietue.($tlen - $i).johdin_mA = yes) then return [laatutapa: johdin_tOn]; end; if $allomorfi.luokka = johdin_mA or $allomorfi.johdin_mA = yes then return [laatutapa: johdin_mA]; end; if $allomorfi.luokka in then return [laatutapa: johdin_ttU]; end; if $allomorfi.luokka in then return []; end; end; return []; end; subrule tulostus_omistusliitteet($tietue): define $tlen := length($tietue); foreach $i in $tlen: define $allomorfi := $tietue.($tlen + 1 - $i); if $allomorfi.omistusliite /= nil then return [omistusliite: $allomorfi.omistusliite]; end; end; return []; end; subrule tulostus_liitepartikkelit($tietue): define $tlen := length($tietue); define $res := []; foreach $i in $tlen: define $allomorfi := $tietue.($tlen + 1 - $i); if $allomorfi.kysymysliite /= nil then $res :=+ [kysymysliite: yes]; end; if $allomorfi.fokus /= nil then $res :=+ [fokus: $allomorfi.fokus]; end; end; return $res; end; subrule tulostus_kielto($tietue): define $tlen := length($tietue); foreach $i in $tlen: define $allomorfi := $tietue.($tlen + 1 - $i); if $allomorfi.kielto /= nil then if $tlen greater $i then define $edellinen := $tietue.($tlen - $i); if $edellinen.luokka in or ($edellinen.luokka = teonsana and $edellinen.tapaluokka = tositapa and $edellinen.aikamuoto = kestämä and $allomorfi.kielto = yes) then return no; end; end; return $allomorfi.kielto; end; if $allomorfi.tapaluokka = käskytapa or $allomorfi.luokka = omistusliite then return molemmat; end; if $allomorfi.luokka /= liitesana then return no; end; end; return no; end; subrule tulostus_nimisanan_attribuutit($tietue): define $tlen := length($tietue); foreach $i in $tlen: define $allomorfi := $tietue.($tlen + 1 - $i); if $allomorfi.paikannimen_jälkiliite = yes then return [paikannimen_jälkiliite: yes]; end; if $allomorfi.luokka in then return []; end; end; return []; end; subrule debug_sanan_perusmuodon_osa ($tietue, $vain_alku): define $res := "+"; if ($vain_alku or $tietue.perusmuoto = nil) then $res :=+ $tietue.alku; else foreach $i in length($tietue.perusmuoto): define $c := substring($tietue.perusmuoto, $i, $i); if not $c in <"=", "|"> then $res :=+ $c; end; end; end; if ($tietue.lähtösana /= nil) then $res :=+ "(p=" + $tietue.lähtösana + ")"; elseif ($tietue.perusmuoto /= nil and $tietue.luokka in ) then $res :=+ "(p=" + $tietue.perusmuoto + ")"; elseif ($tietue.luokka in @johdin_teonsanasta + @johdin_nimisanasta + @johtimet_laatusanasta) then $res :=+ "(p=+"; if ($tietue.perusmuoto /= nil) then $res :=+ $tietue.perusmuoto; else $res :=+ $tietue.alku; end; $res :=+ ")"; end; if ($tietue.sourceid /= nil) then $res :=+ "(s=" + $tietue.sourceid + ")"; end; return $res; end; subrule debug_lukusanan_perusmuodon_osa ($tietue): if ($tietue.perusmuoto = "kymmenen") then return "+kymmentä"; elseif ($tietue.perusmuoto = "tuhat") then return "+tuhatta"; elseif ($tietue.alaluokka in and $tietue.lukutyyppi = perusluku) then return "+" + $tietue.perusmuoto + "a"; else return debug_sanan_perusmuodon_osa($tietue, no); end; end; subrule debug_lukusanan_perusmuoto ($tietue, $i, $k, $s): # Kopioitu Hannu Väisäsen Sukija-versiosta if ($i = 1 and $tietue.$i.alaluokka in ) then return "+" + $tietue.$i.perusmuoto; end; if ($tietue.$i.luokka = lukusanan_jälkiliite) then return "+" + $tietue.$i.perusmuoto; end; if ($tietue.$i.alaluokka = yksiyhdeksän) then if (($k greater 2) and ($i less $k) and ($tietue.($i+1).luokka = sijapääte) and ($tietue.($i+2).luokka /= lukusana)) then return "+" + $tietue.$i.alku; else return "+" + $tietue.$i.perusmuoto; end; elseif ($tietue.$i.perusmuoto = "kymmenen") then if (($i = $k) and (($s matches ".+sataa") or ($s = "sata"))) then return "+" + "kymmenen"; else return "+" + "kymmentä"; end; elseif ($tietue.$i.alaluokka in ) then if ($tietue.($i+1).luokka in ) then return debug_lukusanan_perusmuodon_osa($tietue.$i); else return "+" + $tietue.$i.perusmuoto; end; elseif ($tietue.$i.luokka = sijapääte) then if ($i less $k and $tietue.($i+1).luokka in ) then return ""; else return "+" + $tietue.$i.alku; end; end; return debug_sanan_perusmuodon_osa($tietue.$i, no); end; subrule tulostus_debug_perusmuoto($tietue, $luokka): # Kopioitu Hannu Väisäsen Sukija-versiosta define $n := length ($tietue); define $k := $n; # Poistetaan sanan lopusta osat, jotka eivät vaikuta perusmuotoon. # repeat while ($tietue.$k.luokka in + @tositavan_tekijäpääte_4 + @kertoman_tekijäpääte + @kestämän_tekijäpääte + @ehtotapa + @mahtotapa + @käskytapa + @nimitapa_1 + @nimitapa_2 + @nimitapa_3); $k :=- 1; end; define $s := ""; define $skip := no; foreach $i in $k - 1: if $skip then $skip := no; else if ($tietue.$i.lukutyyppi /= nil and $luokka = lukusana) then $s :=+ debug_lukusanan_perusmuoto ($tietue, $i, $k, $s); elseif (($i+3) less $n and $tietue.$i.luokka = laatusana and $tietue.($i+1).luokka = sijapääte and $tietue.($i+2).luokka = tavuviiva and $tietue.($i+3).luokka = paikannimi) then # Uudessa-Seelannissa -> Uusi-Seelanti $s :=+ debug_sanan_perusmuodon_osa($tietue.$i, no); $skip := yes; else $s :=+ debug_sanan_perusmuodon_osa($tietue.$i, yes); end; end; end; if ($k = 1) then $s :=+ debug_sanan_perusmuodon_osa($tietue.$k, no); elseif ($tietue.$k.lukutyyppi /= nil and $tietue.$k.lukutyyppi = perusluku) then $s :=+ debug_lukusanan_perusmuoto ($tietue, $k, $k, $s); else $s :=+ debug_lukusanan_perusmuodon_osa($tietue.$k); end; return $s; end; subrule tulostus_teonsanan_attribuutit($tietue): define $tlen := length($tietue); foreach $i in $tlen: define $allomorfi := $tietue.($tlen + 1 - $i); if $allomorfi.tapaluokka in then return []; end; if $allomorfi.vaatii_tapaluokan /= nil then return [vaatii_tapaluokan: $allomorfi.vaatii_tapaluokan, kielto: tulostus_kielto($tietue)]; end; end; return [kielto: tulostus_kielto($tietue)]; end; subrule tulostus_v2($tietue): define $res := nil; if @voikko_debug then define $luokka := tulostus_luokka($tietue); $res := [rakenne: tulostus_rakenne($tietue), luokka: $luokka, luku: tulostus_luku($tietue), sijamuoto: tulostus_sijamuoto($tietue), perusmuoto: tulostus_debug_perusmuoto($tietue, $luokka)] + tulostus_partisiipit($tietue) + tulostus_omistusliitteet($tietue) + tulostus_liitepartikkelit($tietue); if $res.luokka = teonsana then $res :=+ [aikamuoto: tulostus_aikamuoto($tietue)]; elseif $res.luokka in then $res :=+ [vertailu: tulostus_vertailu($tietue)]; end; else $res := [rakenne: tulostus_rakenne($tietue), luokka: tulostus_luokka($tietue), luku: tulostus_luku($tietue), sijamuoto: tulostus_sijamuoto($tietue)]; end; if $res.luokka = teonsana then $res :=+ [tekijä: tulostus_tekijä($tietue), tapaluokka: tulostus_tapaluokka($tietue)] + tulostus_teonsanan_attribuutit($tietue); elseif $res.luokka = nimisana then $res :=+ tulostus_nimisanan_attribuutit($tietue); elseif $res.luokka = kieltosana then $res :=+ [tekijä: tulostus_tekijä($tietue), tapaluokka: tulostus_tapaluokka($tietue)]; end; define $tlen := length($tietue); if $tietue.<1, luokka> /= tavuviiva then foreach $i in $tlen: define $allomorfi := $tietue.($tlen + 1 - $i); if $allomorfi.vapaa_jälkiosa = yes then $res :=+ [vapaa_jälkiosa: yes]; break; end; end; end; return $res; end; pruning_rule prune ($list): define $alut := <>; define $filter := <>; define $j := 0; foreach $an in $list: $alut :=+ <($an.1).alku>; end; $alut := set($alut); foreach $an in $list: if $j = 30 then $filter :=+ ; else if (length($an) greater 1) and ($an.1).alku + ($an.2).alku in $alut then $filter :=+ ; else $filter :=+ ; $j :=+ 1; end; end; end; return $filter; end;