Vikisözlük
trwiktionary
https://tr.wiktionary.org/wiki/Vikis%C3%B6zl%C3%BCk:Anasayfa
MediaWiki 1.47.0-wmf.8
case-sensitive
Ortam
Özel
Tartışma
Kullanıcı
Kullanıcı mesaj
Vikisözlük
Vikisözlük tartışma
Dosya
Dosya tartışma
MediaWiki
MediaWiki tartışma
Şablon
Şablon tartışma
Yardım
Yardım tartışma
Kategori
Kategori tartışma
Portal
Portal tartışma
YeniKurum
YeniKurum tartışma
Ek
Ek tartışma
Alıntılar
Alıntılar tartışma
TimedText
TimedText talk
Modül
Modül tartışma
Event
Event talk
anahtar
0
6663
5672659
5253839
2026-06-29T22:36:56Z
Satirdan kahraman
37401
TurkceMaddePanel
5672659
wikitext
text/x-wiki
{{Haftanın kelimesi|2|2007}}
==Türkçe==
===Köken===
*{{k|dil=tr|ota}} {{z|ota|آنهار|anlam=anahtar}}. O da {{köken|dil=tr|el}} {{b|el|ανοιχτήριον|ç=aniχtíri(on)||açkı, açacak}} sözcüğünden alıntıdır. Bu sözcük {{b|grc|ανοίγω|ç=anoígō, ánoíksis||açmak}} fiilinden +ion ekiyle türetilmiştir. Eski Yunanca fiil {{b|grc|οίγω|ç=oígō||açmak}} fiilinden ana+ önekiyle türetilmiştir.
===Söyleniş===
*{{tr-IPA}}
*{{h|dil=tr||a|nah|tar}}
===Ad===
{{tr-ad}}
[[resim:Diverse sleutels.jpg|küçükresim|300 px|{{mânâ|kilit açar}} Muhtelif '''anahtarlar''' (1)]]
# {{t|dil=tr|aletler}} Kilidi açıp kapamak için kullanılan araç; [[açacak]], [[açar]], [[açkı]], [[miftah]], [[dil]]
# [[kurgu]].
# {{t|dil=tr|iletişim}}Şifre yazmak ve çözmek için kararlaştırılmış olan yol.
# {{t|dil=tr|aletler}} Somunları veya vidaları çevirerek sıkıştırıp gevşetmek için kullanılan çelik saplı araç.
# {{t|dil=tr|aletler}} Konserve kutularının kapağını keserek açmaya yarayan alet; [[açacak]].
# {{t|dil=tr|elektrik}} İİstenilen yere veya aygıta, isteğe göre elektrik akımının geçmesini sağlamak için kullanılan düzen; [[çevirici]], [[çevirgeç]], [[şalter]], [[komütatör]]
# {{t|dil=tr|müzik}} Notaların müzik merdivenindeki yükseklik derecelerini göstermek ve buna göre okunmasını sağlamak için portenin başına konulan işaret.
# {{t|dil=tr|müzik}} Piyano, ut, kanun gibi çalgılarda ayar aleti.
#{{t|dil=tr|argo|suç}} [[rüşvet]].
# {{t|dil=tr|eğitim}} {{kısa|tr|cevap anahtarı}}
====Çekimleme====
{{tr-ad-tablo}}
===Ön ad===
{{tr-ön ad}}
#{{t|dil=tr|mecaz }} Herhangi bir olayda belirleyici olan.
#* Anahtar parti.
====Deyimler====
[[anahtarı beline takmak]], [[anahtar uydurmak]], [[anahtar vermek]]
====Türetilmiş kavramlar====
[[anahtar ağızlığı]], [[anahtar bitkiler]], [[anahtar deliği]], [[anahtar dili]], [[anahtar dişi]], [[anahtar kelime]], [[anahtar kovanı]], [[anahtar sözcük]], [[anahtar taşı]], [[erkek anahtar]], [[kovan anahtar]], [[lokma anahtar]], [[alyan anahtarı]], [[basınç anahtarı]], [[bijon anahtarı]], [[cevap anahtarı]], [[do anahtarı]], [[elektrik anahtarı]], [[fa anahtarı]], [[hırsız anahtarı]], [[İngiliz anahtarı]], [[kontak anahtarı]], [[papağan anahtarı]], [[sol anahtarı]], [[şifre anahtarı]], [[tavşan anahtarı]]
====Çeviriler====
{{Üst|tip=çeviriler}}
*Afrikanca: {{ç|af|}}
*Almanca: {{ç|de|Schlüssel|m}}
*Arapça: {{ç|ar|مِفْتَاح|m}}, {{ç|ar|مِقْلَاد|e}}
*Arnavutça: {{ç|sq|}}
*Azerice: {{ç|az|açar}}
*Baskça: {{ç|eu|}}
*Başkurtça: {{ç|ba|}}
*Bretonca: {{ç|br|}}
*Bulgarca: {{ç|bg|}}
*Çekçe: {{ç|cs|}}
*Danca: {{ç|da|nøgle}}
*Endonezce: {{ç|id|}}
*Estonca: {{ç|et|võti}}
*Felemenkçe: {{ç|nl|sleutel|m}}
*Fince: {{ç|fi|avain}}, {{ç|fi|kommutaattori}}, {{ç|fi|kytkin}}
*Fransızca: {{ç|fr|clé|f}}, {{ç|fr|clef|f}}, {{ç|fr|commutateur}}
*Gagavuzca: {{ç|gag|}}
*Gürcüce: {{ç|ka|}}
*İngilizce: {{ç|en|key}}
*İspanyolca: {{ç|es|}}
*İsveççe: {{ç|sv|}}
*İtalyanca: {{ç|it|}}
*İzlandaca: {{ç|is|}}
*Karaçay-Balkarca: {{ç|krc|açhıç}}
*Kazakça: {{ç|kk|кілт}}
*Kırgızca: {{ç|ky|ачқе}}*Katalanca: {{ç|ca|}}
*Kırım Tatarcası: {{ç|crh|anahtar}}
*Lehçe: {{ç|pl|klucz}}
*Marathi dili: {{ç|mr|चावी}}
*Mokşa dili: {{ç|mdf|панжема}}
*Norveççe: {{ç|no|}}
*Osmanlı Türkçesi: {{ç|ota|آنهار}}
*Özbekçe: {{ç|uz|калит}}
*Portekizce: {{ç|pt|}}
*Rumence: {{ç|ro|}}
*Rusça: {{ç|ru|}}
*Slovakça: {{ç|sk|}}
*Slovence: {{ç|sl|}}
*Somalice: {{ç|so|fure magac}}
*Tabasaran dili: {{ç|tab|}}
*Tacikçe: {{ç|tg|}}
*Tatarca: {{ç|tt|açkıç}}, {{ç|tt|açqıç}}
*Türkmence: {{ç|tk|ачар}}, {{ç|tk|açar}}
*Uygurca: {{ç|ug|ئاچقۇچ}}
*Ukraynaca: {{ç|uk|}}
*Yunanca: {{ç|el|}}
{{Alt}}
===Kaynakça===
* {{KYK:TDK}}
* {{KYK:Kubbealtı}}
* {{KYK:Nişanyan}}
===Ek okumalar===
*{{proje bağlantısı|Vikipedi}}
==Kırım Tatarcası==
===Söyleniş===
* {{h|dil=crh||a|nah|tar}}
===Ad===
{{başlık başı|crh|ad}}
# {{t|dil=crh|aletler}} {{b|tr|anahtar}}
9n31x7rzvmdl25bglcf2lnr4m1fcijc
Yılmaz
0
42132
5672513
5254748
2026-06-29T17:50:29Z
Satirdan kahraman
37401
/* */ [[MediaWiki:Gadget-AjaxEdit.js|AjaxDüzenle]] kullanılarak değiştirildi
5672513
wikitext
text/x-wiki
{{bakınız|yılmaz}}
==Türkçe==
===Özel ad===
{{tr-özel ad|k=1}}
{{tr-ad}}
# {{t|dil=tr|beldeler}} [[Manisa]] ili [[Salihli]] ilçesine bağlı belde
# {{özel ad|dil=tr|erkek adı}} [[erkek]] adı
# {{t|dil=tr|köyler}} [[Mardin]] ili [[Dargeçit]] ilçesine bağlı [[köy]]
# {{özel ad|dil=tr|soyadı}} [[soyadı]]
====Söyleniş====
* {{IPA|dil=tr|j/ɯlˈmaz/|ç=/jɯlmazˈlaɾ/}}
* {{h|dil=tr|a|Yıl|maz|k=1}}
===Köken===
{{köken|dil=tr|tr}} yılmaz
===Kaynakça===
* {{proje bağlantısı|vikipedi|{{PAGENAME}}, Dargeçit}}
* {{Yurtsever-TAD-1997}}
4afkviynwfhat3yym90l720tj3k29b1
çizgili
0
48926
5672715
4865849
2026-06-30T06:18:19Z
Satirdan kahraman
37401
TurkceMaddePanel
5672715
wikitext
text/x-wiki
==Türkçe==
====Köken====
{{ek|dil=tr|çizgi|li}}
===Söyleniş===
*{{tr-IPA}}
* {{h|dil=tr||çiz|gi|li}}
===Ön ad===
{{tr-ön ad}}
[[File:Striped hyena in Bhigwan August 2025 by Tisha Mukherjee 12.jpg|küçükresim|'''Çizgili''' sırtlan ]]
# Üzerinde çizgi bulunan
====Çeviriler====
{{üst|tip=çeviriler}}
*İngilizce: {{ç|en|striped}}
*Kırım Tatarca: {{ç|crh|çizgili}}, {{ç|crh|yolaqlı}}
{{alt}}
===Kaynakça===
* {{KYK:TDK}}
==Kırım Tatarca==
===Ön ad===
{{başlık başı|crh|ön ad}}
# çizgili
76s1w6xqtvujwsp768lnrtrpow49vz4
katı
0
52344
5672713
5343508
2026-06-30T06:16:51Z
Satirdan kahraman
37401
TurkceMaddePanel
5672713
wikitext
text/x-wiki
{{bakınız|kat'î|kati}}
==Türkçe==
===Söyleniş===
*{{tr-IPA}}
* {{h|dil=tr||ka|tı}}
===Ön ad===
{{tr-ön ad}}
[[File:Smoky quartz 15.jpg|küçükresim|{{mana|ön ad}} Bu taş çok '''katı''' (1) Taş, maddenin katı hâlinde. (4)]]
# sert, [[yumuşak]] karşıtı.
#*Bu hâl, onu ilk defa giyilen katı gömlek gibi sıkıyordu." - Falih Rıfkı Atay
# {{t|dil=tr|mecaz}}Hoşgörüsüz, acımasız, merhametsiz, zalim olan.
#* Katı yürekli. Katı davranış.
# {{t|dil=tr|mecaz}} Düşünce ve davranışlarında belli ilkelere sıkı sıkıya bağlı olan, hoşgörüsü olmayan; [[sıkı]].
# {{t|dil=tr|fizik}}Sıvıların ve gazların tersine, içinde bulunduğu kabın veya üstünde bulunduğu yerin biçimini almayan; [[sulp]].
# {{t|dil=tr|anatomi}} [[taşlık]]
====Sözcük birliktelikleri====
[[katı atık]], [[katı kalpli]], [[katı sabun]], [[katı söz]], [[katı yağ]], [[katı yumurta]], [[katı yürekli]], [[yüreği katı]]
===Belirteç===
{{tr-belirteç}}
# {{t|dil=tr|eskimiş}} Çok, aşırı derecede.
#* "Susadım ol dem hararetten katı / Sundular bir cam dolusu şerbeti" - Süleyman Çelebi
===Ad===
{{başlık başı|tr|çekimli ad}}
# {{tr-çekim|kat|söz=ad}}
====Çeviriler====
{{Üst|anatomi|tip=çeviriler}}
* Danca: {{ç|da|muskelmave}}
* Fince: {{ç|fi|kiinteä olomuoto}}, {{ç|fi|kivipiira}}, {{ç|fi|lihasmaha}}
* Fransızca: {{ç|fr|gésier|m}}
* İngilizce: {{ç|en|gizzard}}
* İsveççe: {{ç|sv|muskelmage}}
* Kürtçe: {{ç|ku|req}}
* Macarca: {{ç|hu|zúza}}
{{Alt}}
===Ek okumalar===
* {{proje bağlantısı|Vikipedi}}
====Çeviriler====
{{Üst|belirteç|tip=çeviriler}}
* Almanca: {{ç|de|fest}}
* Fince: {{ç|fi|kovin}}
{{Alt}}
====Çeviriler====
{{Üst|fizik|tip=çeviriler}}
* Almanca: {{ç|de|fest}}
* Azerice: {{ç|az|bərk}}, {{ç|az|möhkəm}}
* Çekçe: {{ç|cs|pevný}}
* Fince: {{ç|fi|kova}}, {{ç|fi|jähmeä}}, {{ç|fi|kiinteä}}, {{ç|fi|luja}}
* İngilizce: {{ç|en|solid}}
* Fransızca: {{ç|fr|solide}}
* İsveççe: {{ç|sv|fast}}
* Kırgızca: {{ç|ky|katuu}}
* Portekizce: {{ç|pt|sólido}}
* Rumence: {{ç|ro|fix}}
* Rusça: {{ç|ru|твёрдый}}, {{ç|ru|жёсткий}}
* Türkçe:
*: Eski Türkçe: {{ç|otk|katgı}}, {{ç|otk|katıg}}, {{ç|otk|kurç}}, {{ç|otk|tıgramak}}
* Vietnamca: {{ç|vi|chắc}}
* Yunanca:
*: Modern Yunanca: {{ç|el|στερεός}}
{{Alt}}
===Kaynakça===
* {{Kaynak-TDK}}
==Karaçay-Balkarca==
{{düzenle|alfabe=Karaçay-Balkarca}}
===Ön ad===
{{başlık başı|krc|ön ad}}
# [[kuvvetli]]
# [[sağlam]]
# [[sert]]
==Kumanca==
===Söyleniş===
* {{h|dil=qwm||ka|tı}}
===Ön ad===
{{başlık başı|qwm|ön ad}}
# [[kuvvetli]]
# [[sağlam]]
f6ueyhyw38guhb29zsame7sh5cizvm6
5672714
5672713
2026-06-30T06:17:30Z
Satirdan kahraman
37401
TurkceMaddePanel
5672714
wikitext
text/x-wiki
{{bakınız|kat'î|kati}}
==Türkçe==
===Söyleniş===
*{{tr-IPA}}
* {{h|dil=tr||ka|tı}}
===Ön ad===
{{tr-ön ad}}
[[File:Smoky quartz 15.jpg|küçükresim|{{mana|ön ad}} Bu taş çok '''katı''' (1) Taş, maddenin katı hâlinde. (4)]]
# sert, [[yumuşak]] karşıtı.
#*Bu hâl, onu ilk defa giyilen katı gömlek gibi sıkıyordu." - Falih Rıfkı Atay
# {{t|dil=tr|mecaz}}Hoşgörüsüz, acımasız, merhametsiz, zalim olan.
#* Katı yürekli. Katı davranış.
# {{t|dil=tr|mecaz}} Düşünce ve davranışlarında belli ilkelere sıkı sıkıya bağlı olan, hoşgörüsü olmayan; [[sıkı]].
# {{t|dil=tr|fizik}}Sıvıların ve gazların tersine, içinde bulunduğu kabın veya üstünde bulunduğu yerin biçimini almayan; [[sulp]].
# {{t|dil=tr|anatomi}} [[taşlık]]
====Türetilmiş kavramlar====
[[katı atık]], [[katı kalpli]], [[katı sabun]], [[katı söz]], [[katı yağ]], [[katı yumurta]], [[katı yürekli]], [[yüreği katı]]
===Belirteç===
{{tr-belirteç}}
# {{t|dil=tr|eskimiş}} Çok, aşırı derecede.
#* "Susadım ol dem hararetten katı / Sundular bir cam dolusu şerbeti" - Süleyman Çelebi
===Ad===
{{başlık başı|tr|çekimli ad}}
# {{tr-çekim|kat|söz=ad}}
====Çeviriler====
{{Üst|anatomi|tip=çeviriler}}
* Danca: {{ç|da|muskelmave}}
* Fince: {{ç|fi|kiinteä olomuoto}}, {{ç|fi|kivipiira}}, {{ç|fi|lihasmaha}}
* Fransızca: {{ç|fr|gésier|m}}
* İngilizce: {{ç|en|gizzard}}
* İsveççe: {{ç|sv|muskelmage}}
* Kürtçe: {{ç|ku|req}}
* Macarca: {{ç|hu|zúza}}
{{Alt}}
{{Üst|belirteç|tip=çeviriler}}
* Almanca: {{ç|de|fest}}
* Fince: {{ç|fi|kovin}}
{{Alt}}
{{Üst|fizik|tip=çeviriler}}
* Almanca: {{ç|de|fest}}
* Azerice: {{ç|az|bərk}}, {{ç|az|möhkəm}}
* Çekçe: {{ç|cs|pevný}}
* Fince: {{ç|fi|kova}}, {{ç|fi|jähmeä}}, {{ç|fi|kiinteä}}, {{ç|fi|luja}}
* İngilizce: {{ç|en|solid}}
* Fransızca: {{ç|fr|solide}}
* İsveççe: {{ç|sv|fast}}
* Kırgızca: {{ç|ky|katuu}}
* Portekizce: {{ç|pt|sólido}}
* Rumence: {{ç|ro|fix}}
* Rusça: {{ç|ru|твёрдый}}, {{ç|ru|жёсткий}}
* Türkçe:
*: Eski Türkçe: {{ç|otk|katgı}}, {{ç|otk|katıg}}, {{ç|otk|kurç}}, {{ç|otk|tıgramak}}
* Vietnamca: {{ç|vi|chắc}}
* Yunanca:
*: Modern Yunanca: {{ç|el|στερεός}}
{{Alt}}
===Kaynakça===
* {{KYK:TDK}}
===Ek okumalar===
*{{proje bağlantısı|Vikipedi}}
==Karaçay-Balkarca==
{{düzenle|alfabe=Karaçay-Balkarca}}
===Ön ad===
{{başlık başı|krc|ön ad}}
# [[kuvvetli]]
# [[sağlam]]
# [[sert]]
==Kumanca==
===Söyleniş===
* {{h|dil=qwm||ka|tı}}
===Ön ad===
{{başlık başı|qwm|ön ad}}
# [[kuvvetli]]
# [[sağlam]]
aqg3mo6sq8uuiwzfnahwzuobn6huru6
marşandiz
0
53482
5672527
5635170
2026-06-29T19:17:19Z
Satirdan kahraman
37401
TurkceMaddePanel
5672527
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{köken|dil=tr|fr}} {{b|fr|marchandise|anlam=ticari eşya, kargo}} sözcüğünden. Bu sözcük Fransızca {{b|fr|marchand|anlam=tüccar}} sözcüğünden türetilmiştir. Fransızca sözcük Latince aynı anlama gelen {{b|la|mercāns, mercant-}} sözcüğünden evrilmiştir. Bu sözcük Latince {{b|la|mercari|anlam=alıp satmak}} fiilinden {{b|la|+ent}} ekiyle türetilmiştir.
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||mar|şan|diz}}
===Ad===
{{tr-ad}}
[[File:TCDD DE 33 075 Konak - Murat.jpg|küçükresim|Bir '''marşandiz.''']]
#{{t|dil=tr}} [[yük treni]].
#*{{kt|başlık=Yarım Kalan Yürüyüş|yazar=Mehmet EROĞLU|yayıncı=İletişim Yayınları|yıl=2020|sayfa=57|tanıklık=Peron boş, ileride, ikinci hatta yorgun bir '''marşandiz''', banliyö trenini bekliyor.|dil=tr}}
====Çekimleme====
{{tr-ad-tablo}}
====Deyimler====
====Türetilmiş kavramlar====
===Kaynakça===
* {{KYK:TDK}}
* {{KYK:Kubbealtı}}
* {{KYK:Nişanyan}}
===Ek okumalar===
*{{proje bağlantısı|Vikipedi}}
rtaaxn12qx05be8crz5am7v7g9kvww6
5672528
5672527
2026-06-29T19:18:00Z
Satirdan kahraman
37401
/* */ [[MediaWiki:Gadget-AjaxEdit.js|AjaxDüzenle]] kullanılarak değiştirildi
5672528
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{köken|dil=tr|fr}} {{b|fr|marchandise|anlam=ticari eşya, kargo}} sözcüğünden. Bu sözcük Fransızca {{b|fr|marchand|anlam=tüccar}} sözcüğünden türetilmiştir. Fransızca sözcük Latince aynı anlama gelen {{b|la|mercāns, mercant-}} sözcüğünden evrilmiştir. Bu sözcük Latince {{b|la|mercari|anlam=alıp satmak}} fiilinden {{b|la|+ent}} ekiyle türetilmiştir.
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||mar|şan|diz}}
===Ad===
{{tr-ad}}
[[File:TCDD DE 33 075 Konak - Murat.jpg|küçükresim|Bir '''marşandiz.''']]
#{{t|dil=tr|demiryolu taşıtları}} [[yük treni]].
#*{{kt|başlık=Yarım Kalan Yürüyüş|yazar=Mehmet EROĞLU|yayıncı=İletişim Yayınları|yıl=2020|sayfa=57|tanıklık=Peron boş, ileride, ikinci hatta yorgun bir '''marşandiz''', banliyö trenini bekliyor.|dil=tr}}
====Çekimleme====
{{tr-ad-tablo}}
====Deyimler====
====Türetilmiş kavramlar====
===Kaynakça===
* {{KYK:TDK}}
* {{KYK:Kubbealtı}}
* {{KYK:Nişanyan}}
===Ek okumalar===
*{{proje bağlantısı|Vikipedi}}
e9skmb7fmdj121me39aebgpr90dizb7
5672529
5672528
2026-06-29T19:18:06Z
Satirdan kahraman
37401
/* */ [[MediaWiki:Gadget-AjaxEdit.js|AjaxDüzenle]] kullanılarak değiştirildi
5672529
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{köken|dil=tr|fr}} {{b|fr|marchandise|anlam=ticari eşya, kargo}} sözcüğünden. Bu sözcük Fransızca {{b|fr|marchand|anlam=tüccar}} sözcüğünden türetilmiştir. Fransızca sözcük Latince aynı anlama gelen {{b|la|mercāns, mercant-}} sözcüğünden evrilmiştir. Bu sözcük Latince {{b|la|mercari|anlam=alıp satmak}} fiilinden {{b|la|+ent}} ekiyle türetilmiştir.
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||mar|şan|diz}}
===Ad===
{{tr-ad}}
[[File:TCDD DE 33 075 Konak - Murat.jpg|küçükresim|Bir '''marşandiz.''']]
#{{t|dil=tr|demiryolu taşıtları}} [[yük treni]].
#*{{kt|başlık=Yarım Kalan Yürüyüş|yazar=Mehmet EROĞLU|yayıncı=İletişim Yayınları|yıl=2020|sayfa=57|tanıklık=Peron boş, ileride, ikinci hatta yorgun bir '''marşandiz''', banliyö trenini bekliyor.|dil=tr}}
====Çekimleme====
{{tr-ad-tablo}}
===Kaynakça===
* {{KYK:TDK}}
* {{KYK:Kubbealtı}}
* {{KYK:Nişanyan}}
===Ek okumalar===
*{{proje bağlantısı|Vikipedi}}
le7bwu7iiwk3y9wcyou7svuq6x9e5z4
nişan halkası
0
54666
5672629
4415692
2026-06-29T22:15:31Z
Satirdan kahraman
37401
TurkceMaddePanel
5672629
wikitext
text/x-wiki
==Türkçe==
===Köken===
*{{birleşik|dil=tr|nişan|halka}}
===Söyleniş===
*{{tr-IPA}}
*{{h|dil=tr||ni|şan|hal|ka|sı}}
===Ad===
{{tr-ad}}
[[File:Engagement rings.JPG|küçükresim|'''Nişan halkası''' takan bir çift.]]
#{{t|dil=tr|takılar|evlilik}} [[nişan yüzüğü]].
====Çekimleme====
{{tr-ad-tablo}}
===Kaynakça===
* {{KYK:TDK}}
===Ek okumalar===
*{{proje bağlantısı|Vikipedi}}
rpr2ltsl4wudh74bka416bznr9mkg18
5672630
5672629
2026-06-29T22:15:44Z
Satirdan kahraman
37401
/* */ [[MediaWiki:Gadget-AjaxEdit.js|AjaxDüzenle]] kullanılarak değiştirildi
5672630
wikitext
text/x-wiki
==Türkçe==
===Köken===
*{{birleşik|dil=tr|nişan|halka}}
===Söyleniş===
*{{tr-IPA}}
*{{h|dil=tr||ni|şan|hal|ka|sı}}
===Ad===
{{tr-ad}}
[[File:Engagement rings.JPG|küçükresim|'''Nişan halkası''' takan bir çift.]]
#{{t|dil=tr|takılar|evlilik|sembol adları}} [[nişan yüzüğü]].
====Çekimleme====
{{tr-ad-tablo}}
===Kaynakça===
* {{KYK:TDK}}
===Ek okumalar===
*{{proje bağlantısı|Vikipedi}}
02k792h3why55zoztfkilkw7fiwr3qt
suikastçı
0
56363
5672553
5258285
2026-06-29T20:03:47Z
Satirdan kahraman
37401
TurkceMaddePanel
5672553
wikitext
text/x-wiki
==Türkçe==
===Köken===
*{{ek|dil=tr|suikast|çı}}
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||su|i|kast|çı}}
===Ad===
{{tr-ad}}
[[File:DC-1914-27-d-Sarajevo-cropped.jpg|küçükresim|Tablodaki '''suikastçı''' siyah giyinmiş ve elinde tabanca var.]]
#{{t|dil=tr|suç}} Suikast yapan kimse.
====Çekimleme====
{{tr-ad-tablo}}
====Çeviriler====
{{üst|tip=çeviriler}}
*İngilizce: {{ç|en|assassin}}
*Almanca: {{ç|de|Meuchelmörder}}
*İngilizce: {{ç|en|assassin}}
*Fransızca: {{ç|fr|assassin}}
* Macarca: {{ç|hu|merénylő}}
{{alt}}
===Kaynakça===
* {{KYK:TDK}}
* {{KYK:Kubbealtı}}
2yvg1vglcpml5kfkjqyic1h5lht6cky
yalın ayak
0
57777
5672722
4910084
2026-06-30T07:21:43Z
Satirdan kahraman
37401
TurkceMaddePanel
5672722
wikitext
text/x-wiki
==Türkçe==
===Köken===
*{{birleşik|dil=tr|yalın|ayak }}
===Söyleniş===
*{{tr-IPA}}
* {{h|dil=tr||ya|lın|a|yak}}
===Ön ad===
{{başlık başı|tr|ön ad}}
# Ayakları çıplak.
[[File:Barefoot girl3.jpg|küçükresim|{{mana|ön ad}} Bankta, '''yalın ayak''' bir kadın oturuyor. <p> {{mana|belirteç}} Kadın, banka '''yalın ayak''' oturmuş.]]
#*'Soldan dört ayak üzerinde, yalın ayak, başı kabak bir adam görülür.'' - N. F. Kısakürek
===Belirteç===
{{tr-belirteç}}
# Çıplak ayakla
#*''Sonra kalktım, yalın ayak, örtüsüz tahta masaya gittim.'' - H. E. Adıvar
====Çeviriler====
{{Üst|belirteç|tip=çeviriler}}
*Fince: {{ç|fi|paljain jaloin}}, {{ç|fi|paljasjaloin}}, {{ç|fi|avojaloin}}
*Özbekçe: {{ç|uz|yalan oyoq}}, {{ç|uz|yalangoyoq}}
{{Alt}}
{{Üst|ön ad|tip=çeviriler}}
*Fince: {{ç|fi|paljasjalkainen}}
{{Alt}}
====Kaynakça====
*{{kaynak-TDK}}
1amcrldkpzf8qxfd1mycdndgnvxnw1o
yorumlama
0
58163
5672542
4327603
2026-06-29T19:36:34Z
Satirdan kahraman
37401
TurkceMaddePanel
5672542
wikitext
text/x-wiki
{{bakınız|yorum}}
==Türkçe==
===Söyleniş===
*{{tr-IPA}}
* {{h|dil=tr||yo|rum|la|ma}}
===Ad===
{{tr-ad}}
[[File:Olaus Magnus - On the Art of Prophecy.jpg|thumb|Kral, adamın ölü balıkları '''yorumlamasını''' dinliyor.]]
# [[yorumlamak]] işi; [[tefsir]]
====Çekimleme====
{{tr-ad-tablo}}
====Çeviriler====
{{üst|tip=çeviriler}}
*Fince: {{ç|fi|tulkitseminen}}
*İngilizce: {{ç|en|interpretation}}
Kürtçe: {{ç|ku|şîrovekirin}}
{{alt}}
===Kaynakça===
* {{KYK:TDK}}
kqbx9gmwxqoh9gtq9pzfnlhcmtzkhay
yük katarı
0
58214
5672526
4328155
2026-06-29T19:15:49Z
Satirdan kahraman
37401
TurkceMaddePanel
5672526
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{birleşik|dil=tr|yük|katar}}
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||yük|ka|ta|rı}}
===Ad===
{{tr-ad}}
[[File:TCDD DE 33 075 Konak - Murat.jpg|küçükresim|Bir yük katarı.]]
#{{t|dil=tr|demiryolu taşıtları}} [[yük treni]].
====Çekimleme====
{{tr-ad-tablo}}
===Kaynakça===
* {{KYK:TDK}}
===Ek okumalar===
*{{proje bağlantısı|Vikipedi}}
jv0enoxd6jwthvhfrdjcjviohmpv5zg
peron
0
67328
5672530
5259451
2026-06-29T19:22:37Z
Satirdan kahraman
37401
TurkceMaddePanel
5672530
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{köken|dil=tr|fr}} {{b|fr|perron|anlam=1. binek taşı, 2. trene biniş platformu}} sözcüğünden. Bu sözcük Fransızca {{b|fr|pierre|anlam=taş}} sözcüğünden {{b|fr|+on}} ekiyle türetilmiştir. Fransızca sözcük Latince {{b|la|petra|anlam=taş}} sözcüğünden evrilmiştir. Bu sözcük Eski Yunanca {{b|grc|πέτρα|ç=pétra|anlam=taş}} sözcüğünden alıntıdır.
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||pe|ron}}
===Ad===
{{tr-ad}}
[[File:Izmir Coach Terminal 5932.jpg|küçükresim|Otobüs, '''peronda''' bekliyor. (1)]]
[[File:Alamnagar Railway Station.jpg|küçükresim|Peron (2).]]
# {{t|dil=tr|kara ulaşımı}} Otobüs terminallerinde aracın yanaştığı, yolcuların inip binmesine yarayan bölüm.
# {{t|dil=tr|demiryolu ulaşımı}} Tren, tramvay, metro istasyonlarında yol boyunca uzanan, inilip binilen özel bölüm.
#* "Peronla yolcu vagonlarını ayıran parmaklığın otomatik demiri kapanıyordu." - Sait Faik Abasıyanık
====Çekimleme====
{{tr-ad-tablo}}
====Çeviriler====
{{üst|tip=çeviriler}}
*Türkmence: {{ç|tk|perron}}
{{alt}}
===Kaynakça===
* {{KYK:TDK}}
* {{KYK:Nişanyan}}
jnioe9dr7ekrario09a07dfvdpuvfo7
suikast
0
69317
5672551
5659823
2026-06-29T19:56:15Z
Satirdan kahraman
37401
TurkceMaddePanel
5672551
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{birleşik|dil=tr|sui|kast}} Arapça √swˀ kökünden gelen sūˀ سؤ “kötülük, fenalık, habaset” ve Arapça ḳaṣd قصد “kasıt, maksat” sözcüklerinin bileşiğidir. Daha fazla bilgi için [sui+](/kelime/sui%2B) ve [kasıt](/kelime/kas%C4%B1t) maddelerine bakınız.
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||su|i|kast}}
===Ad===
[[File:DC-1914-27-d-Sarajevo-cropped.jpg|küçükresim|Bir suikasti anlatan tablo. (2)]]
{{tr-ad|istisna=incelme}}
#{{t|dil=tr|cinayet}} Gizlice cana kıyma ve kötülük etmeye kalkışma.
#* "Bir nefes alayım derken iğrenç bir suikasta uğradım." - Sait Faik Abasıyanık
# Bir devlet büyüğünü veya önemli bir kişiyi plan kurarak öldürme.
====Çekimleme====
{{tr-ad-tablo|istisna=incelme}}
====Deyimler====
* [[suikastta parmağı olmak]]
====Çeviriler====
{{Üst|suikast|tip=çeviriler}}
* Almanca: {{ç|de|ْAttentat|n}}
* Azerice: {{ç|az|sui-qəsd}}
* Arapça: {{ç|ar|ْصُوءِقَصْد|m}}
* Fransızca: {{ç|fr|complot|e}}, {{ç|fr|conjuration|d}}, {{ç|fr|assassinat|e}}
* İngilizce: {{ç|en|assassination}}
* Macarca: {{ç|hu|merénylet}}
* Türkçe:
*: Osmanlı Türkçesi: {{ç|ota|صوءقصد}}
{{Alt}}
===Kaynakça===
* {{KYK:TDK}}
* {{KYK:Nişanyan}}
===Ek okumalar===
* {{proje bağlantısı|dil=tr|Vikipedi}}
qe07nv80672lmu0g83v44i1qei80v4h
5672552
5672551
2026-06-29T20:01:07Z
Satirdan kahraman
37401
TurkceMaddePanel
5672552
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{köken|dil=tr|otk}} {{b|ar|سوء قصد|}}. O da Arapça {{b|ar|سؤ||anlam=kötülük, fenalık, habaset}} ve Arapça {{b|ar|قصد ||anlam=kasıt, maksat}} sözcüklerinin birleşimidir.
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||su|i|kast}}
===Ad===
[[File:DC-1914-27-d-Sarajevo-cropped.jpg|küçükresim|Bir suikasti anlatan tablo. (2)]]
{{tr-ad|istisna=incelme}}
#{{t|dil=tr|cinayet}} Gizlice cana kıyma ve kötülük etmeye kalkışma.
#* "Bir nefes alayım derken iğrenç bir suikasta uğradım." - Sait Faik Abasıyanık
# Bir devlet büyüğünü veya önemli bir kişiyi plan kurarak öldürme.
====Çekimleme====
{{tr-ad-tablo|istisna=incelme}}
====Deyimler====
* [[suikastta parmağı olmak]]
====Çeviriler====
{{Üst|suikast|tip=çeviriler}}
* Almanca: {{ç|de|ْAttentat|n}}
* Azerice: {{ç|az|sui-qəsd}}
* Arapça: {{ç|ar|ْصُوءِقَصْد|m}}
* Fransızca: {{ç|fr|complot|e}}, {{ç|fr|conjuration|d}}, {{ç|fr|assassinat|e}}
* İngilizce: {{ç|en|assassination}}
* Macarca: {{ç|hu|merénylet}}
* Türkçe:
*: Osmanlı Türkçesi: {{ç|ota|صوءقصد}}
{{Alt}}
===Kaynakça===
* {{KYK:TDK}}
* {{KYK:Nişanyan}}
===Ek okumalar===
* {{proje bağlantısı|dil=tr|Vikipedi}}
afc6rhd6dios4cey5jbokhb2z8j5czh
5672554
5672552
2026-06-29T20:04:56Z
Satirdan kahraman
37401
/* */ [[MediaWiki:Gadget-AjaxEdit.js|AjaxDüzenle]] kullanılarak değiştirildi
5672554
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{köken|dil=tr|otk}} {{b|ar|سوء قصد|}}. O da Arapça {{b|ar|سؤ||anlam=kötülük, fenalık, habaset}} ve Arapça {{b|ar|قصد ||anlam=kasıt, maksat}} sözcüklerinin birleşimidir.
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||su|i|kast}}
===Ad===
[[File:DC-1914-27-d-Sarajevo-cropped.jpg|küçükresim|Bir suikasti anlatan tablo. (2)]]
{{tr-ad|istisna=incelme}}
#{{t|dil=tr|cinayet}} Gizlice cana kıyma ve kötülük etmeye kalkışma.
#* "Bir nefes alayım derken iğrenç bir suikasta uğradım." - Sait Faik Abasıyanık
#{{t|dil=tr|cinayet|politika}} Bir devlet büyüğünü veya önemli bir kişiyi plan kurarak öldürme.
====Çekimleme====
{{tr-ad-tablo|istisna=incelme}}
====Deyimler====
* [[suikastta parmağı olmak]]
====Çeviriler====
{{Üst|suikast|tip=çeviriler}}
* Almanca: {{ç|de|ْAttentat|n}}
* Azerice: {{ç|az|sui-qəsd}}
* Arapça: {{ç|ar|ْصُوءِقَصْد|m}}
* Fransızca: {{ç|fr|complot|e}}, {{ç|fr|conjuration|d}}, {{ç|fr|assassinat|e}}
* İngilizce: {{ç|en|assassination}}
* Macarca: {{ç|hu|merénylet}}
* Türkçe:
*: Osmanlı Türkçesi: {{ç|ota|صوءقصد}}
{{Alt}}
===Kaynakça===
* {{KYK:TDK}}
* {{KYK:Nişanyan}}
===Ek okumalar===
* {{proje bağlantısı|dil=tr|Vikipedi}}
h7idqvx8xwebmy4w6gr72vo4j1ehhnh
meczup
0
127568
5672487
5254091
2026-06-29T14:22:30Z
RamazanBayram94
67950
Düzeltme
5672487
wikitext
text/x-wiki
==Türkçe==
===Köken===
{{k|dil=tr|ota}} {{z|ar|مجذوب}}, o da [[Arapça]] {{z|ar|مَجْذُوب}} kelimesinden gelmektedir.
===Söyleniş===
* {{IPA|dil=tr|/med͡ʒ.ˈzup/}}
* {{h|dil=tr||mec|zup}}
===Ön ad===
{{tr-ön ad}}
# [[akli|Aklî]] [[denge]]sini [[kaybetmek|kaybetmiş]] [[insan]]lara verilen genel ad
#:{{örnek|dil=tr|"Bunlardan başka köyün iki '''meczubu''', bir cücesi vardır."|Yakup Kadri Karaosmanoğlu}}
# {{t|dil=tr|İslâm|tarikat}} Genellikle [[din]]e olan bağlılığı yüzünden [[aklî denge]]sini [[kaybetmek|kaybetmiş]] olan [[insan]]lara yahut [[dergâh]] [[âyin]]lerinde kendilerinden geçen [[derviş]].
===Kaynakça===
* {{kaynak-TDK}}
kl2efaixefbgf4lfwae9045zjgnwps5
nouveau
0
130166
5672736
4417595
2026-06-30T08:48:41Z
MustafaCavlak
59368
/* Fransızca */
5672736
wikitext
text/x-wiki
==Fransızca==
===Ön ad===
{{fr-ön ad|e2=nouvel|d=nouvelle|eç=nouveaux}}
# [[yeni]]
ishry3rlb30mcsimr9vs4iy1tqeo8if
говорить
0
131590
5672591
3793194
2026-06-29T21:13:22Z
MustafaCavlak
59368
/* Rusça */
5672591
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{ru-eylem|говори́ть|impf|pf=сказа́ть|pf2=поговори́ть}}
# [[konuşmak]] (tamamlanmış: поговорить)
# [[demek]], [[söylemek]] (tamamlanmış: сказать)
evlzm2qp5c2gmflx3z47ivuyerca55h
5672592
5672591
2026-06-29T21:14:25Z
MustafaCavlak
59368
5672592
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{ru-eylem|говори́ть|impf|pf=сказа́ть|pf2=поговори́ть}}
# [[konuşmak]]
# [[demek]], [[söylemek]]
qaqyctxmmgz52ka0nwxsgxrtsj1gos8
5672593
5672592
2026-06-29T21:15:19Z
MustafaCavlak
59368
/* Rusça */
5672593
wikitext
text/x-wiki
==Rusça==
===Köken===
{{devralınan|ru|sla-pro|*govoriti}}.
===Eylem===
{{ru-eylem|говори́ть|impf|pf=сказа́ть|pf2=поговори́ть}}
# [[konuşmak]]
# [[demek]], [[söylemek]]
rdea7m1dm7ju24n9zaqasnwa1v35lbg
ნომერი
0
148204
5672733
4541372
2026-06-30T08:08:52Z
MustafaCavlak
59368
/* Gürcüce */
5672733
wikitext
text/x-wiki
==Gürcüce==
===Söyleniş===
* {{IPA|dil=ka|[no̞me̞ɾi]}}
===Ad===
{{başlık başı|ka|ad}}
# [[sayı]]
shaicc0qiy43eqyzy9ktl0lkutma6zf
bakalorya
0
169535
5672560
5656356
2026-06-29T20:36:35Z
Satirdan kahraman
37401
TurkceMaddePanel
5672560
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{köken|dil=tr|fr}} {{b|fr|baccalauréat|anlam=üniversite giriş sınavı}} sözcüğünden. Bu sözcük Geç Latince {{b|la|baccalarius|anlam=genç adam, şövalye adayı, bekâr}} sözcüğünden türetilmiştir. Geç Latince sözcük Eski Fransızca {{b|fro|bacheler|anlam=genç adam}} sözcüğünden alıntıdır.
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||ba|ka|lo|rya}}
===Ad===
{{tr-ad}}
# {{t|dil=tr|eğitim}} Üniversitelere girebilmek için lise öğreniminden sonra verilen olgunluk sınavı.
#*{{kt|başlık=Acı Lokma|yazar=Fahri ERDİNÇ|yayıncı=Yordam Kitap |yıl=2006|sayfa=150|tanıklık='''Bakalorlayada''' edebiyattan takılıp diploma alamıyan bir arkadaşı da, yerli gazete «Bir ışık daha söndü» diye bir ağıt yayınladı...|dil=tr}}
#*{{kt|dil=tr|başlık=Huzur|yazar=Ahmet Hamdi TANPINAR|yayıncı=Dergâh Yayınları|yıl=2022|baskı=39|sayfa=203|tanıklık= Mümtaz daha on sekiz yaşında '''bakaloryasını''' vermeğe hazırlanan lise talebesiyken, bu fikirlerin ocağına atılmıştı.}}
====Çekimleme====
{{tr-ad-tablo}}
====Çeviriler====
{{Üst|tip=çeviriler}}
*Fince: {{ç|fi|ylioppilastutkinto}}
*Fransızca: {{ç|fr|baccalauréat}}
*İngilizce: {{ç|en|baccalauréat}}
{{Alt}}
===Kaynakça===
* {{KYK:TDK}}
* {{KYK:Kubbealtı}}
* {{KYK:Nişanyan}}
l35mp2btuzr2jf95xl27udxsd45yx8t
muhtarlık
0
169895
5672523
4386705
2026-06-29T19:08:06Z
Satirdan kahraman
37401
TurkceMaddePanel
5672523
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{ek|dil=tr|muhtar|lık}}
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||muh|tar|lık}}
===Ad===
{{tr-ad}}
[[File:Konakmersinli.jpg|küçükresim|Bir '''muhtarlık''' binası. (2)]]
#{{t|dil=tr|kamu yönetimi}} Muhtarın görevi veya makamı.
# Muhtarın görevini yaptığı yer.
====Çekimleme====
{{tr-ad-tablo}}
===Kaynakça===
* {{KYK:TDK}}
ogmcl8xqgvocc7fqal4hrwx6nk6011m
yorgun
0
180935
5672531
5636846
2026-06-29T19:27:31Z
Satirdan kahraman
37401
TurkceMaddePanel
5672531
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{ek|dil=tr|yorul|gun}}
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||yor|gun}}
===Ön ad===
{{tr-ön ad}}
[[File:A tired worker.jpg|küçükresim|'''Yorgun''' adam, dinleniyor.]]
#Çalışma vb. sebeplerle beden veya zihin etkinliği yavaşlayan, yorulmuş olan
#*{{kt|başlık=Erbain|yazar=İsmet ÖZEL|yayıncı=TİYO|yıl=2016|sayfa=23|tanıklık='''Yorgun''' olamazdım çok uzaklardaydı yurdum çünkü|dil=tr}}
====Atasözleri====
* [[yorgun eşeğin çüş canına minnet]]
====Çeviriler====
{{Üst|tip=çeviriler}}
*Almanca: {{ç|de|ermüdet}}, {{ç|de|müde}}
*Azerice: {{ç|az|yorğun}}
*Eski Türkçe: {{ç|otk|aruk}}
*İngilizce: {{ç|en|tired}}, {{ç|en|weary}}
*İsveççe: {{ç|sv|däven}}, {{ç|sv|trött}}
*Norveççe: {{ç|no|trett}}, {{ç|no|trøtt}}
*Tatarca: {{ç|tt|arığan}}
*Türkmence: {{ç|tk|ýadaw}}
{{Alt}}
===Kaynakça===
* {{KYK:TDK}}
==Gagavuzca==
===Köken===
{{köken|otk|dil=gag}} jor
===Ön ad===
{{başlık başı|gag|ön ad}}
# [[yorgun#Türkçe|yorgun]]
===Kaynakça===
* {{kaynak-EtymDict}}
ksab6bj89ufxsvf9lg2jshaoyuo0fy5
5672536
5672531
2026-06-29T19:31:53Z
Satirdan kahraman
37401
/* */ [[MediaWiki:Gadget-AjaxEdit.js|AjaxDüzenle]] kullanılarak değiştirildi
5672536
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{ek|dil=tr|yorulmak|gun}}
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||yor|gun}}
===Ön ad===
{{tr-ön ad}}
[[File:A tired worker.jpg|küçükresim|'''Yorgun''' adam, dinleniyor.]]
#Çalışma vb. sebeplerle beden veya zihin etkinliği yavaşlayan, yorulmuş olan
#*{{kt|başlık=Erbain|yazar=İsmet ÖZEL|yayıncı=TİYO|yıl=2016|sayfa=23|tanıklık='''Yorgun''' olamazdım çok uzaklardaydı yurdum çünkü|dil=tr}}
====Atasözleri====
* [[yorgun eşeğin çüş canına minnet]]
====Çeviriler====
{{Üst|tip=çeviriler}}
*Almanca: {{ç|de|ermüdet}}, {{ç|de|müde}}
*Azerice: {{ç|az|yorğun}}
*Eski Türkçe: {{ç|otk|aruk}}
*İngilizce: {{ç|en|tired}}, {{ç|en|weary}}
*İsveççe: {{ç|sv|däven}}, {{ç|sv|trött}}
*Norveççe: {{ç|no|trett}}, {{ç|no|trøtt}}
*Tatarca: {{ç|tt|arığan}}
*Türkmence: {{ç|tk|ýadaw}}
{{Alt}}
===Kaynakça===
* {{KYK:TDK}}
==Gagavuzca==
===Köken===
{{köken|otk|dil=gag}} jor
===Ön ad===
{{başlık başı|gag|ön ad}}
# [[yorgun#Türkçe|yorgun]]
===Kaynakça===
* {{kaynak-EtymDict}}
9dhdiatqllbpvxap2hh86pj56mkheay
yük treni
0
182980
5672525
5264896
2026-06-29T19:14:25Z
Satirdan kahraman
37401
TurkceMaddePanel
5672525
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{birleşik|dil=tr|yük|tren}}
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||yük|tre|ni}}
===Ad===
{{tr-ad}}
[[File:TCDD DE 33 075 Konak - Murat.jpg|küçükresim|Bir yük treni.]]
#{{t|dil=tr|demiryolu taşıtları}} Yük taşımada kullanılan tren; [[yük katarı]], [[marşandiz]].
====Çekimleme====
{{tr-ad-tablo}}
===Kaynakça===
* {{KYK:TDK}}
===Ek okumalar===
*{{proje bağlantısı|Vikipedi}}
lyj55tzixl3bbpy5nvxsm37ycn0rupt
yormak
0
191146
5672538
5265259
2026-06-29T19:33:21Z
Satirdan kahraman
37401
TurkceMaddePanel
5672538
wikitext
text/x-wiki
==Türkçe==
===Köken===
# {{k|dil=tr|tr}}
===Söyleniş===
*{{tr-IPA}}
* {{h|dil=tr||yor|mak}}
===Eylem===
{{tr-eylem}}
[[File:The Tired Dancer.jpg|küçükresim|Dans, kadını çok yormuş. (1) ]]
[[File:Olaus Magnus - On the Art of Prophecy.jpg|küçükresim|Kâhin, ölü balıklara bir işaret yoruyor. (4)]]
# [[yorgun]] duruma getirmek.
#* "Teknik teferruatla okurlarımı yormak istemiyorum." - Falih Rıfkı Atay
# sıkıntıya sokmak, üzmek
#* "Ömer, kalbimi en çok yoran bir sima gibi hatırımda kaldı." - Halide Edip Adıvar
# Bir anlam vermek, yorumlamak.
#* "Hayvanlara insanca duygu ve düşünceler yormak ne derece doğrudur bunu da kestiremiyorum." - Haldun Taner
#Bir sebebe bağlamak, bir duruma işaret saymak.
====Çekimleme====
{{tr-eylem-tablo}}
====Çeviriler====
{{üst|tip=çeviriler}}
*Azerice: {{ç|az|yozmaq}}
*Eski Türkçe: {{ç|otk|argarmak}}, {{ç|otk|argurmak}}
* Fransızca: {{ç|fr|fatiguer}}, {{ç|fr|épuiser}}, {{ç|fr|lasser}}
* İngilizce: {{ç|en|tire}}, {{ç|en|exhaust}}, {{ç|en|wear out}}
* İspanyolca: {{ç|es|cansar}}, {{ç|es|hartar}}
*Karaçay Balkarca: {{ç|krc|arıt}}
* Macarca: {{ç|hu|fáraszt}}, {{ç|hu|kimerít}}
{{alt}}
===Kaynakça===
* {{KYK:TDK}}
==Çağatayca==
===Eylem===
{{başlık başı|chg|eylem}}
# [[fal]] haber eylemek, güzel tâbir eylemek, nik söylemek
==Eski Türkçe==
{{düzenle|alfabe=Eski Türkçe}}
===Eylem===
{{başlık başı|otk|eylem}}
# tabir etmek
# Yormak
# [[yürümek]]
===Kaynakça===
* {{KÚNOS, Dr IGNAZ-ŞSEÇOS-1902}}
mkhedrf37e835x6n5th9ytrs6hqggns
yorulmak
0
191151
5672535
4183379
2026-06-29T19:31:05Z
Satirdan kahraman
37401
TurkceMaddePanel
5672535
wikitext
text/x-wiki
==Türkçe==
===Köken 1===
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||yo|rul|mak}}
===Eylem===
{{tr-eylem}}
[[File:Tired young nurse asleep and sitting at the table after long working day.jpg|küçükresim|Kız, '''yorulmuş.''']]
# [[yorgun|Yorgun]] duruma gelmek.
#* "El ele vererek dost olduk hemen / Yorulmaz dostuyla birlikte giden" - Enis Behiç Koryürek
===Köken 2===
===Eylem===
{{tr-eylem}}
# Bir sebebe bağlanılmak, yorumlanmak.
#* Bu davranış iyiye yorulmaz.
====Çekimleme====
{{tr-eylem-tablo}}
====Çeviriler====
{{Üst|tip=çeviriler}}
*Arapça: {{ç|ar|تعب}}
*Fince: {{ç|fi|väsyä}}, {{ç|fi|uupua}}
*İngilizce: {{ç|en|tire}}
*İsveççe: {{ç|sv|bli trött}}, {{ç|sv|tröttna}}
*Kürtçe: {{ç|ku|westîn}}
*Rusça: {{ç|ru|уставать}}
*Türkmence: {{ç|tk|aarmak}}, {{ç|tk|ýaadamak}}, {{ç|tk|ýorulmak}}
{{Alt}}
===Kaynakça===
* {{KYK:TDK}}
* {{KYK:Kubbealtı}}
* {{KYK:Nişanyan}}
5gvekfvoy8gakjivckrxmceqhj4f8w3
Zaman
0
199613
5672514
5246000
2026-06-29T18:10:53Z
Satirdan kahraman
37401
TurkceMaddePanel
5672514
wikitext
text/x-wiki
{{bak|zaman}}
==Türkçe==
===Köken===
[[zaman]] sözcüğünden.
===Söyleniş===
*{{tr-IPA}}
* {{h|dil=tr||Za|man}}
===Özel ad===
{{tr-özel ad|k=1}}
# {{özel ad|dil=tr|soyadı}}
====Çekimleme====
{{tr-ad-tablo}}
2rrzupe2j0f7ks91k16s6z98pmqagxn
anaokulu
0
209957
5672518
5239165
2026-06-29T19:03:42Z
Satirdan kahraman
37401
TurkceMaddePanel
5672518
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{birleşik|dil=tr|ana|okul}}
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||a|na|o|ku|lu}}
===Ad===
{{tr-ad}}
[[File:TR Izmir asv2020-02 img38 Löhner mansion.jpg|küçükresim|Anaokulu]]
# {{t|eğitim|dil=tr}} öğrenim çağına henüz gelmemiş 2-6 yaş arasındaki çocukları okul düzenine hazırlayan eğitim kuruluşu; [[ana mektebi]]
====Çekimleme====
{{tr-ad-tablo}}
====Çeviriler====
{{Üst|tip=çeviriler}}
*Almanca: {{ç|de|Vorschule}}
*Felemenkçe: {{ç|nl|kleuterschool}}
*Fince: {{ç|fi|esikoulu}}
*İngilizce: {{ç|en|nursery school}}, {{ç|en|preschool}},
*İtalyanca: {{ç|it|asilo}}, {{ç|it|scuola materna}}
*Kırım Tatarcası: {{ç|crh|}}
*Kürtçe: {{ç|ku|zarrokxane}}
*Tatarca: {{ç|tt|balalar baqçası}}
{{Alt}}
===Kaynakça===
* {{KYK:TDK}}
===Ek okumalar===
*{{proje bağlantısı|Vikipedi}}
kn8hunh7hgce0ax96pd5pa5hu1mu4es
5672519
5672518
2026-06-29T19:04:03Z
Satirdan kahraman
37401
/* */ [[MediaWiki:Gadget-AjaxEdit.js|AjaxDüzenle]] kullanılarak değiştirildi
5672519
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{birleşik|dil=tr|ana|okul}}
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||a|na|o|ku|lu}}
===Ad===
{{tr-ad}}
[[File:TR Izmir asv2020-02 img38 Löhner mansion.jpg|küçükresim|Anaokulu]]
# {{t|eğitim|dil=tr}} öğrenim çağına henüz gelmemiş 2-6 yaş arasındaki çocukları okul düzenine hazırlayan eğitim kuruluşu; [[ana mektebi]]
====Çekimleme====
{{tr-ad-tablo|istisna=bileşik}}
====Çeviriler====
{{Üst|tip=çeviriler}}
*Almanca: {{ç|de|Vorschule}}
*Felemenkçe: {{ç|nl|kleuterschool}}
*Fince: {{ç|fi|esikoulu}}
*İngilizce: {{ç|en|nursery school}}, {{ç|en|preschool}},
*İtalyanca: {{ç|it|asilo}}, {{ç|it|scuola materna}}
*Kırım Tatarcası: {{ç|crh|}}
*Kürtçe: {{ç|ku|zarrokxane}}
*Tatarca: {{ç|tt|balalar baqçası}}
{{Alt}}
===Kaynakça===
* {{KYK:TDK}}
===Ek okumalar===
*{{proje bağlantısı|Vikipedi}}
k2xhm4gorl2fmdf88yr5323vux16x4z
5672520
5672519
2026-06-29T19:04:11Z
Satirdan kahraman
37401
TurkceMaddePanel
5672520
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{birleşik|dil=tr|ana|okul}}
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||a|na|o|ku|lu}}
===Ad===
{{tr-ad|istisna=bileşik}}
[[File:TR Izmir asv2020-02 img38 Löhner mansion.jpg|küçükresim|Anaokulu]]
# {{t|eğitim|dil=tr}} öğrenim çağına henüz gelmemiş 2-6 yaş arasındaki çocukları okul düzenine hazırlayan eğitim kuruluşu; [[ana mektebi]]
====Çekimleme====
{{tr-ad-tablo|istisna=bileşik}}
====Çeviriler====
{{Üst|tip=çeviriler}}
*Almanca: {{ç|de|Vorschule}}
*Felemenkçe: {{ç|nl|kleuterschool}}
*Fince: {{ç|fi|esikoulu}}
*İngilizce: {{ç|en|nursery school}}, {{ç|en|preschool}},
*İtalyanca: {{ç|it|asilo}}, {{ç|it|scuola materna}}
*Kırım Tatarcası: {{ç|crh|}}
*Kürtçe: {{ç|ku|zarrokxane}}
*Tatarca: {{ç|tt|balalar baqçası}}
{{Alt}}
===Kaynakça===
* {{KYK:TDK}}
===Ek okumalar===
*{{proje bağlantısı|Vikipedi}}
q7sw7hbmr69akut344bwwfvg8lba1k8
nişan yüzüğü
0
218248
5672631
4189570
2026-06-29T22:17:01Z
Satirdan kahraman
37401
TurkceMaddePanel
5672631
wikitext
text/x-wiki
==Türkçe==
===Köken===
*{{birleşik|dil=tr|nişan|yüzük}}
===Söyleniş===
*{{tr-IPA}}
*{{h|dil=tr||ni|şan|yü|zü|ğü}}
===Ad===
{{tr-ad}}
[[File:Engagement rings.JPG|küçükresim|'''Nişan yüzüğü''' takan bir çift.]]
#{{t|dil=tr|takılar|sembol adları|evlilik}} Evlenecek çiftin nişanlandıklarında taktıkları ve düğünden sonra da taşıdıkları halka biçimli yüzük; [[nişan halkası]]
====Çekimleme====
{{tr-ad-tablo}}
====Çeviriler====
{{Üst|tip=çeviriler}}
*Danca: {{ç|da|forlovelsesring}}
*Fince: {{ç|fi|kihlasormus}}
*İngilizce: {{ç|en|engagement ring}}
*İsveççe: {{ç|sv|förlovningsring}}
{{Alt}}
===Kaynakça===
* {{KYK:TDK}}
41fzitifkjyr1o6hah7utq8pkcde68x
virüs
0
220959
5672570
5344594
2026-06-29T20:48:03Z
Satirdan kahraman
37401
TurkceMaddePanel
5672570
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{köken|dil=tr|la}} {{b|la|vīrus|anlam=bir tür zararlı mikroorganizma}} sözcüğünden. Bu sözcük Latince {{b|la|virus|mana=zehir}} sözcüğünden alıntıdır. Latince sözcük Arkaik Latince tanıksız veya yeniden kurulmuş wisos biçiminden evrilmiştir. Bu biçim Hintavrupa Anadili tanıksız veya yeniden kurulmuş {{b|ine-pro|*wei̯s- |anlam=kötü kokmak, zehir}} biçiminden evrilmiştir.
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||vi|rüs}}
===Ad===
{{tr-ad}}
[[File:Herpes simplex virus pap.jpg|thumb|Bir '''virüs'''. (1)]]
[[File:SkyNet Virus Code.png|Bilgisayar '''virüsü'''. (2)]]
# {{t|viroloji|dil=tr}} Hastalık yapıcı, bakterilerden daha küçük, yaşamak için bir başka hücrenin içine girmek zorunda olan ve ancak elektron mikroskobunda görülebilen parazit.
#* "Benliğinin bir tarafına sokulup ölü yaşayan bir virüs Seher’in aşkı gibi müsait bir zemin bulunca canlanmış." - Refik Halit Karay
# {{t|bilişim|dil=tr}} Değişik şekillerde bilgisayarlara yüklenen, programların bozulmasına, veri kaybına veya bilgisayarın olağan dışı çalışmasına neden olan program.
====Çekimleme====
{{tr-ad-tablo}}
====Deyimler====
[[mutant virüs]]
====Üst kavramlar====
[[tıp]],
[[malware]],
[[patojen]],
[[viroloji]],
[[zararlı yazılım]]
====Türetilmiş kavramlar====
[[amogus]],
[[sus]],
====Çeviriler====
{{Üst|tip=çeviriler}}
*Afrikanca: {{ç|af|virus}}
*Almanca: {{ç|de|Virus|n}}*Aragonca: {{ç|an|}}
*Arapça: {{ç|ar|فِيرُوس|m}}, {{ç|ar|ڤِيرُوس|m}}
*Arnavutça: {{ç|sq|virus}}
*Bulgarca: {{ç|bg|вирус|m}} *Esperanto: {{ç|eo|viruso}}
*Estonca: {{ç|et|viirus}}
*Fransızca: {{ç|fr|virus|m}}
*İngilizce: {{ç|en|virus}}
*İsveççe: {{ç|sv|virus|n}}
*Keçuva dili: {{ç|qu|miyu}}
*Latince: {{ç|la|virus}}
*Lehçe: {{ç|pl|wirus}}
*Macarca: {{ç|hu|vírus}}
*Norveççe: {{ç|no|virus}}
*Rusça: {{ç|ru|вирус|m}}; {{ç|ru|вирус|m}}
*Uygurca: {{ç|uz|ۋىرۇس}}
{{Alt}}
===Kaynakça===
* {{KYK:TDK}}
* {{KYK:Kubbealtı}}
* {{KYK:Nişanyan}}
oqku8tl6sd8kecqupvfj97b355u4q6s
5672572
5672570
2026-06-29T20:48:13Z
Satirdan kahraman
37401
/* */ [[MediaWiki:Gadget-AjaxEdit.js|AjaxDüzenle]] kullanılarak değiştirildi
5672572
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{köken|dil=tr|la}} {{b|la|vīrus|anlam=bir tür zararlı mikroorganizma}} sözcüğünden. Bu sözcük Latince {{b|la|virus|mana=zehir}} sözcüğünden alıntıdır. Latince sözcük Arkaik Latince tanıksız veya yeniden kurulmuş wisos biçiminden evrilmiştir. Bu biçim Hintavrupa Anadili tanıksız veya yeniden kurulmuş {{b|ine-pro|*wei̯s- |anlam=kötü kokmak, zehir}} biçiminden evrilmiştir.
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||vi|rüs}}
===Ad===
{{tr-ad}}
[[File:Herpes simplex virus pap.jpg|thumb|Bir '''virüs'''. (1)]]
[[File:SkyNet Virus Code.png|küçükresim|Bilgisayar '''virüsü'''. (2)]]
# {{t|viroloji|dil=tr}} Hastalık yapıcı, bakterilerden daha küçük, yaşamak için bir başka hücrenin içine girmek zorunda olan ve ancak elektron mikroskobunda görülebilen parazit.
#* "Benliğinin bir tarafına sokulup ölü yaşayan bir virüs Seher’in aşkı gibi müsait bir zemin bulunca canlanmış." - Refik Halit Karay
# {{t|bilişim|dil=tr}} Değişik şekillerde bilgisayarlara yüklenen, programların bozulmasına, veri kaybına veya bilgisayarın olağan dışı çalışmasına neden olan program.
====Çekimleme====
{{tr-ad-tablo}}
====Deyimler====
[[mutant virüs]]
====Üst kavramlar====
[[tıp]],
[[malware]],
[[patojen]],
[[viroloji]],
[[zararlı yazılım]]
====Türetilmiş kavramlar====
[[amogus]],
[[sus]],
====Çeviriler====
{{Üst|tip=çeviriler}}
*Afrikanca: {{ç|af|virus}}
*Almanca: {{ç|de|Virus|n}}*Aragonca: {{ç|an|}}
*Arapça: {{ç|ar|فِيرُوس|m}}, {{ç|ar|ڤِيرُوس|m}}
*Arnavutça: {{ç|sq|virus}}
*Bulgarca: {{ç|bg|вирус|m}} *Esperanto: {{ç|eo|viruso}}
*Estonca: {{ç|et|viirus}}
*Fransızca: {{ç|fr|virus|m}}
*İngilizce: {{ç|en|virus}}
*İsveççe: {{ç|sv|virus|n}}
*Keçuva dili: {{ç|qu|miyu}}
*Latince: {{ç|la|virus}}
*Lehçe: {{ç|pl|wirus}}
*Macarca: {{ç|hu|vírus}}
*Norveççe: {{ç|no|virus}}
*Rusça: {{ç|ru|вирус|m}}; {{ç|ru|вирус|m}}
*Uygurca: {{ç|uz|ۋىرۇس}}
{{Alt}}
===Kaynakça===
* {{KYK:TDK}}
* {{KYK:Kubbealtı}}
* {{KYK:Nişanyan}}
7e7siuz244ejrqmkkcn87i940ued859
5672574
5672572
2026-06-29T20:48:47Z
Satirdan kahraman
37401
/* */ [[MediaWiki:Gadget-AjaxEdit.js|AjaxDüzenle]] kullanılarak değiştirildi
5672574
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{köken|dil=tr|la}} {{b|la|vīrus|anlam=bir tür zararlı mikroorganizma}} sözcüğünden. Bu sözcük Latince {{b|la|virus|mana=zehir}} sözcüğünden alıntıdır. Latince sözcük Arkaik Latince tanıksız veya yeniden kurulmuş wisos biçiminden evrilmiştir. Bu biçim Hintavrupa Anadili tanıksız veya yeniden kurulmuş {{b|ine-pro|*wei̯s- |anlam=kötü kokmak, zehir}} biçiminden evrilmiştir.
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||vi|rüs}}
===Ad===
{{tr-ad}}
[[File:Herpes simplex virus pap.jpg|thumb|Bir '''virüs'''. (1)]]
[[File:SkyNet Virus Code.png|küçükresim|Bilgisayar '''virüsü'''. (2)]]
# {{t|viroloji|dil=tr}} Hastalık yapıcı, bakterilerden daha küçük, yaşamak için bir başka hücrenin içine girmek zorunda olan ve ancak elektron mikroskobunda görülebilen parazit.
#* "Benliğinin bir tarafına sokulup ölü yaşayan bir virüs Seher’in aşkı gibi müsait bir zemin bulunca canlanmış." - Refik Halit Karay
# {{t|bilişim|dil=tr}} Değişik şekillerde bilgisayarlara yüklenen, programların bozulmasına, veri kaybına veya bilgisayarın olağan dışı çalışmasına neden olan program.
====Çekimleme====
{{tr-ad-tablo}}
====Deyimler====
[[mutant virüs]]
====Üst kavramlar====
[[tıp]],
[[malware]],
[[patojen]],
[[viroloji]],
[[zararlı yazılım]]
====Çeviriler====
{{Üst|tip=çeviriler}}
*Afrikanca: {{ç|af|virus}}
*Almanca: {{ç|de|Virus|n}}*Aragonca: {{ç|an|}}
*Arapça: {{ç|ar|فِيرُوس|m}}, {{ç|ar|ڤِيرُوس|m}}
*Arnavutça: {{ç|sq|virus}}
*Bulgarca: {{ç|bg|вирус|m}} *Esperanto: {{ç|eo|viruso}}
*Estonca: {{ç|et|viirus}}
*Fransızca: {{ç|fr|virus|m}}
*İngilizce: {{ç|en|virus}}
*İsveççe: {{ç|sv|virus|n}}
*Keçuva dili: {{ç|qu|miyu}}
*Latince: {{ç|la|virus}}
*Lehçe: {{ç|pl|wirus}}
*Macarca: {{ç|hu|vírus}}
*Norveççe: {{ç|no|virus}}
*Rusça: {{ç|ru|вирус|m}}; {{ç|ru|вирус|m}}
*Uygurca: {{ç|uz|ۋىرۇس}}
{{Alt}}
===Kaynakça===
* {{KYK:TDK}}
* {{KYK:Kubbealtı}}
* {{KYK:Nişanyan}}
mnpe7m9j4pn1lvjn2kol5e6htm48a2x
5672575
5672574
2026-06-29T20:48:50Z
Satirdan kahraman
37401
/* */ [[MediaWiki:Gadget-AjaxEdit.js|AjaxDüzenle]] kullanılarak değiştirildi
5672575
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{köken|dil=tr|la}} {{b|la|vīrus|anlam=bir tür zararlı mikroorganizma}} sözcüğünden. Bu sözcük Latince {{b|la|virus|mana=zehir}} sözcüğünden alıntıdır. Latince sözcük Arkaik Latince tanıksız veya yeniden kurulmuş wisos biçiminden evrilmiştir. Bu biçim Hintavrupa Anadili tanıksız veya yeniden kurulmuş {{b|ine-pro|*wei̯s- |anlam=kötü kokmak, zehir}} biçiminden evrilmiştir.
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||vi|rüs}}
===Ad===
{{tr-ad}}
[[File:Herpes simplex virus pap.jpg|thumb|Bir '''virüs'''. (1)]]
[[File:SkyNet Virus Code.png|küçükresim|Bilgisayar '''virüsü'''. (2)]]
# {{t|viroloji|dil=tr}} Hastalık yapıcı, bakterilerden daha küçük, yaşamak için bir başka hücrenin içine girmek zorunda olan ve ancak elektron mikroskobunda görülebilen parazit.
#* "Benliğinin bir tarafına sokulup ölü yaşayan bir virüs Seher’in aşkı gibi müsait bir zemin bulunca canlanmış." - Refik Halit Karay
# {{t|bilişim|dil=tr}} Değişik şekillerde bilgisayarlara yüklenen, programların bozulmasına, veri kaybına veya bilgisayarın olağan dışı çalışmasına neden olan program.
====Çekimleme====
{{tr-ad-tablo}}
====Deyimler====
[[mutant virüs]]
====Çeviriler====
{{Üst|tip=çeviriler}}
*Afrikanca: {{ç|af|virus}}
*Almanca: {{ç|de|Virus|n}}*Aragonca: {{ç|an|}}
*Arapça: {{ç|ar|فِيرُوس|m}}, {{ç|ar|ڤِيرُوس|m}}
*Arnavutça: {{ç|sq|virus}}
*Bulgarca: {{ç|bg|вирус|m}} *Esperanto: {{ç|eo|viruso}}
*Estonca: {{ç|et|viirus}}
*Fransızca: {{ç|fr|virus|m}}
*İngilizce: {{ç|en|virus}}
*İsveççe: {{ç|sv|virus|n}}
*Keçuva dili: {{ç|qu|miyu}}
*Latince: {{ç|la|virus}}
*Lehçe: {{ç|pl|wirus}}
*Macarca: {{ç|hu|vírus}}
*Norveççe: {{ç|no|virus}}
*Rusça: {{ç|ru|вирус|m}}; {{ç|ru|вирус|m}}
*Uygurca: {{ç|uz|ۋىرۇس}}
{{Alt}}
===Kaynakça===
* {{KYK:TDK}}
* {{KYK:Kubbealtı}}
* {{KYK:Nişanyan}}
krffucxspc8z6p4fau8c24nzlkoza58
5672576
5672575
2026-06-29T20:49:09Z
Satirdan kahraman
37401
/* */ [[MediaWiki:Gadget-AjaxEdit.js|AjaxDüzenle]] kullanılarak değiştirildi
5672576
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{köken|dil=tr|la}} {{b|la|vīrus|anlam=bir tür zararlı mikroorganizma}} sözcüğünden. Bu sözcük Latince {{b|la|virus|mana=zehir}} sözcüğünden alıntıdır. Latince sözcük Arkaik Latince tanıksız veya yeniden kurulmuş wisos biçiminden evrilmiştir. Bu biçim Hintavrupa Anadili tanıksız veya yeniden kurulmuş {{b|ine-pro|*wei̯s- |anlam=kötü kokmak, zehir}} biçiminden evrilmiştir.
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||vi|rüs}}
===Ad===
{{tr-ad}}
[[File:Herpes simplex virus pap.jpg|thumb|Bir '''virüs'''. (1)]]
[[File:SkyNet Virus Code.png|küçükresim|Bilgisayar '''virüsü'''. (2)]]
# {{t|viroloji|dil=tr}} Hastalık yapıcı, bakterilerden daha küçük, yaşamak için bir başka hücrenin içine girmek zorunda olan ve ancak elektron mikroskobunda görülebilen parazit.
#* "Benliğinin bir tarafına sokulup ölü yaşayan bir virüs Seher’in aşkı gibi müsait bir zemin bulunca canlanmış." - Refik Halit Karay
# {{t|bilişim|dil=tr}} Değişik şekillerde bilgisayarlara yüklenen, programların bozulmasına, veri kaybına veya bilgisayarın olağan dışı çalışmasına neden olan program.
====Çekimleme====
{{tr-ad-tablo}}
====Türetilmiş kavramlar====
[[koronavirüs]], [[mutant virüs]]
====Çeviriler====
{{Üst|tip=çeviriler}}
*Afrikanca: {{ç|af|virus}}
*Almanca: {{ç|de|Virus|n}}*Aragonca: {{ç|an|}}
*Arapça: {{ç|ar|فِيرُوس|m}}, {{ç|ar|ڤِيرُوس|m}}
*Arnavutça: {{ç|sq|virus}}
*Bulgarca: {{ç|bg|вирус|m}} *Esperanto: {{ç|eo|viruso}}
*Estonca: {{ç|et|viirus}}
*Fransızca: {{ç|fr|virus|m}}
*İngilizce: {{ç|en|virus}}
*İsveççe: {{ç|sv|virus|n}}
*Keçuva dili: {{ç|qu|miyu}}
*Latince: {{ç|la|virus}}
*Lehçe: {{ç|pl|wirus}}
*Macarca: {{ç|hu|vírus}}
*Norveççe: {{ç|no|virus}}
*Rusça: {{ç|ru|вирус|m}}; {{ç|ru|вирус|m}}
*Uygurca: {{ç|uz|ۋىرۇس}}
{{Alt}}
===Kaynakça===
* {{KYK:TDK}}
* {{KYK:Kubbealtı}}
* {{KYK:Nişanyan}}
84qrzdvgdv56502z4c3j93xkptqdf6n
sivrisinek
0
226514
5672559
5637800
2026-06-29T20:34:17Z
Satirdan kahraman
37401
TurkceMaddePanel
5672559
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{birleşik|dil=tr|sivri|sinek}}
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||siv|ri|si|nek}}
===Ad===
{{tr-ad}}
[[Dosya:Aedes aegypti biting human.jpg|küçükresim|Bir '''sivrisinek.''']]
# {{t|dil=tr|böcekler}} [[çift kanatlılar]]dan, insan ve memeli hayvanların kanıyla beslenen, birçok türü bulunan ve bir türü sıtma mikrobu aşılayan, sulak, bataklık yerlerde çok üreyen ve [[bulaşıcı]] hastalıkları yayan [[uçucu]] [[böcek]]
#*{{mt|dergi=Öküz|sayı=15|yıl=1996|yazar=Orhan PAMUK|başlık=Gece Sivrisinek |sayfa=2|tanıklık=Kurtuldum sanmıştım, kafamı yastığa gömmüş, belki biraz da uyuklamıştım ki kendimi gecenin ortasında '''sivrisineğin''' uçuşu altında çaresiz ve yapayalnız buldum.|dil=tr}}
====Çekimleme====
{{tr-ad-tablo}}
====Atasözleri====
* [[anlayana sivrisinek saz, anlamayana davul zurna az]]
====Çeviriler====
{{üst|tip=çeviriler}}
*Almanca: {{ç|de|Mücke|f}}
*Baskça: {{ç|eu|eltxo}}
*Bulgarca: {{ç|bg|комар|m}}
*Çekçe: {{ç|cs|komár|m}}
*Danca: {{ç|da|stikmyg}}
*Endonezce: {{ç|id|nyamuk}}
*Eski Türkçe: {{ç|otk|kümiçe}}
*Estonca: {{ç|et|sääsk}}
*Felemenkçe: {{ç|nl|mug}}
*Fince: {{ç|fi|hyttynen}}
*Fransızca: {{ç|fr|cousin|m}}, {{ç|fr|moustique|m}}
*İngilizce: {{ç|en|gnat}}, {{ç|en|mosquito}}
*İspanyolca: {{ç|es|mosquito}}
*İsveççe: {{ç|sv|mygga}}
*Kırım Tatarcası: {{ç|crh|çirkiy}}, {{ç|crh|şırqıy}}
*Lao dili: {{ç|lo|ຍຸງ}}
*Lehçe: {{ç|pl|komar|m}}
*Macarca: {{ç|hu|szúnyog}}
*Min Nan dili: {{ç|nan|báng}}
*Norveççe: {{ç|no|mygg}}
*Rumence: {{ç|ro|ţânţar}}
*Rusça: {{ç|ru|комар|m}}
*Tatarca: {{ç|tt|çerki}}, {{ç|tt|ozın-borın}}
*Türkmence: {{ç|tk|çybyn}}
*Vietnamca: {{ç|vi|muỗi}}
{{alt}}
===Kaynakça===
* {{kaynak-TDK}}
===Ek okumalar===
*{{proje bağlantısı|Vikipedi}}
gdnircr4w5gwc0ed785x7n8p7udh1de
çizgi
0
243278
5672716
5633096
2026-06-30T06:19:08Z
Satirdan kahraman
37401
TurkceMaddePanel
5672716
wikitext
text/x-wiki
==Türkçe==
===Söyleniş===
*{{tr-IPA}}
* {{h|e|çiz|gi|dil=tr}}
===Ad===
[[File:Straight-line separator.png|thumb|'''Çizgi''' (1)]]
[[File:Outline of a facial profile divided geometrically. Drawing, Wellcome V0009158.jpg|küçükresim|Bir erkeğin '''yüz çizgileri''' (2)]]
{{tr-ad}}
# çizilmek veya çeşitli yollarla oluşmuş iz; [[çizi]], [[hat]], [[tahril]]
#*''Bu kâğıda üç '''çizgi''' çekti.'' - Ö. Seyfettin
# yüz ve vücut hatlarının her biri
#*{{kt|başlık=Siddharta|yazar=Hermann Hesse|yayıncı=Can Sanat Yayınları|yıl=2017|tercüme=Kâmuran Şipal|sayfa=93|tanıklık=Govinda yaşlanmıştı, ama yüzü eski '''çizgilerini''' koruyor, yüzünde bir şevk, sadakat, arayış ve ürkeklik ifadesi okunuyordu. |dil=tr}}
# {{t|geometri|dil=tr}} bir noktanın noktasıyla oluşan biçim
#*'''''Çizginin''' yalnız uzunluk boyutu vardır.''
# {{mecaz|dil=tr}} temel
#*''Ben hayatımı yeniden ve bambaşka '''çizgiler''' üzerinde kuracağım.'' - A. İlhan
# {{mecaz|dil=tr}} bir durumdan başka bir duruma atlanan, geçilen yer, sınır
#*''Bu topluluklar arasında amatör ve profesyonel çizgisini de tam olarak çizebilmek kolay değildir.'' - Metin And
====Çekimleme====
{{tr-ad-tablo}}
====Deyimler====
[[çizgi çekmek]],
[[çizgi film]],
[[çizgi hakemi]],
[[çizgi im]],
[[en çizgi]],
[[kısa çizgi]]
====Türetilmiş kavramlar====
* [[çizgili]], [[çizgisiz]]
====Çeviriler====
{{Üst|tip=çeviriler}}
*Almanca: {{ç|de|Linie|f}}, {{ç|de|Strich|m}}
*Azerice: {{ç|az|çizgi}}, {{ç|az|xətt}}
*Fince: {{ç|fi|viiva}}, {{ç|fi|juova}}, {{ç|fi|naarmu}}, {{ç|fi|piirto}}
*İngilizce: {{ç|en|line}}
*İspanyolca: {{ç|es|raya|f}}
*İsveççe: {{ç|sv|linje}}
{{Alt}}
===Kaynakça===
* {{KYK:TDK}}
==Azerice==
===Ad===
{{başlık başı|az|ad}}
# {{b|tr|çizgi}}
1quejms5nxxdf6npfkmormcpjdf0a17
5672717
5672716
2026-06-30T06:21:08Z
Satirdan kahraman
37401
TurkceMaddePanel
5672717
wikitext
text/x-wiki
==Türkçe==
===Söyleniş===
*{{tr-IPA}}
* {{h|e|çiz|gi|dil=tr}}
===Ad===
[[File:Straight-line separator.png|thumb|'''Çizgi''' (1)]]
[[File:Outline of a facial profile divided geometrically. Drawing, Wellcome V0009158.jpg|küçükresim|Bir erkeğin '''yüz çizgileri''' (2)]]
{{tr-ad}}
# çizilmek veya çeşitli yollarla oluşmuş iz; [[çizi]], [[hat]], [[tahril]]
#*''Bu kâğıda üç '''çizgi''' çekti.'' - Ö. Seyfettin
# yüz ve vücut hatlarının her biri
#*{{kt|başlık=Siddharta|yazar=Hermann Hesse|yayıncı=Can Sanat Yayınları|yıl=2017|tercüme=Kâmuran Şipal|sayfa=93|tanıklık=Govinda yaşlanmıştı, ama yüzü eski '''çizgilerini''' koruyor, yüzünde bir şevk, sadakat, arayış ve ürkeklik ifadesi okunuyordu. |dil=tr}}
# {{t|geometri|dil=tr}} bir noktanın noktasıyla oluşan biçim
#*'''''Çizginin''' yalnız uzunluk boyutu vardır.''
# {{mecaz|dil=tr}} temel
#*''Ben hayatımı yeniden ve bambaşka '''çizgiler''' üzerinde kuracağım.'' - A. İlhan
# {{mecaz|dil=tr}} bir durumdan başka bir duruma atlanan, geçilen yer, sınır
#*''Bu topluluklar arasında amatör ve profesyonel çizgisini de tam olarak çizebilmek kolay değildir.'' - Metin And
====Çekimleme====
{{tr-ad-tablo}}
====Deyimler====
[[çizgi çekmek]], [[çizgisinden sapmamak]]
====Türetilmiş kavramlar====
[[çizgi film]], [[çizgi hakemi]], [[çizgi im]], [[çizgi ölçek]], [[çizgi resim]], [[çizgi roman]], [[ana çizgi]], [[eğik çizgi]], [[gol çizgi teknolojisi]], [[kırık çizgi]], [[kırmızıçizgi]], [[kırmızı çizgi]], [[kısa çizgi]], [[uzun çizgi]], [[dış çizgiler durumu]], [[ev çizgileri]], [[atlama çizgisi]], [[aut çizgisi]], [[başlangıç çizgisi]], [[başucu çizgisi]], [[bitiş çizgisi]], [[çıkış çizgisi]], [[dip çizgisi]], [[doruk çizgisi]], [[ek çizgisi]], [[gol çizgisi]], [[ilave çizgisi]], [[kader çizgisi]], [[kale çizgisi]], [[kıyı çizgisi]], [[konuşma çizgisi]], [[korner çizgisi]], [[köşe çizgisi]], [[mafya çizgisi]], [[ölçek çizgisi]], [[ölçü çizgisi]], [[sahil çizgisi]], [[santra çizgisi]], [[serbest atış çizgisi]], [[su bölümü çizgisi]], [[taç çizgisi]], [[tarih değiştirme çizgisi]], [[ufuk çizgisi]], [[varış çizgisi]], [[yan çizgisi]]
====Çeviriler====
{{Üst|tip=çeviriler}}
*Almanca: {{ç|de|Linie|f}}, {{ç|de|Strich|m}}
*Azerice: {{ç|az|çizgi}}, {{ç|az|xətt}}
*Fince: {{ç|fi|viiva}}, {{ç|fi|juova}}, {{ç|fi|naarmu}}, {{ç|fi|piirto}}
*İngilizce: {{ç|en|line}}
*İspanyolca: {{ç|es|raya|f}}
*İsveççe: {{ç|sv|linje}}
{{Alt}}
===Kaynakça===
* {{KYK:TDK}}
==Azerice==
===Ad===
{{başlık başı|az|ad}}
# {{b|tr|çizgi}}
qmz6xpssmrimnf2ignshykeftdocdu1
anofel
0
257371
5672557
5632229
2026-06-29T20:31:39Z
Satirdan kahraman
37401
TurkceMaddePanel
5672557
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{köken|dil=tr|fr}} {{b|fr|anophèle|anlam=sıtmaya neden olan sivrisinek türü}} sözcüğünden. Bu sözcük Eski Yunanca {{b|grc|ἀνωφελής|ç=anophelḗs|anlam=zayıflatan, kurutan}} sözcüğünden alıntıdır. Eski Yunanca sözcük Eski Yunanca {{b|grc|ὀφελής|ç=ophelḗs}} sözcüğünden {{b|grc|α-|ç=a(n)-|anlam=olumsuzluk ön eki}} ile türetilmiştir. Bu sözcük Eski Yunanca {{b|grc|ὀφέλλω|ç=ophéllō|anlam=güçlendirmek, kan ve can vermek, beslemek, yaramak}} fiilinden türetilmiştir.
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||a|no|fel}}
===Ad===
{{tr-ad}}
[[Dosya:AnophelesGambiaemosquito.jpg|küçükresim|Anofel]]
# {{t|dil=tr|böcekler}} [[sıtma sivrisineği]]
#*{{kt|başlık= Dünkü - Bugünkü Akhisar|yazar=Ekmel İZDEM|yayıncı=Ülkü Basımevi|yıl=1944|sayfa=88|tanıklık=Rahmiye, Çamlatı, Kuvalık bataklıkları ile hiçbir disipline tâbi olmadan akan ve yer yer biriken sularda üreyen '''anufeller''' halkı sıtmadan kırıp geçiriyor.|dil=tr}}
===Çekimleme===
{{tr-ad-tablo}}
====Çeviriler====
{{üst|tip=çeviriler}}
*Fince: {{ç|fi|horkkahyttynen}}, {{ç|fi|malariahyttynen}}
{{alt}}
===Kaynakça===
* {{kaynak-TDK}}
===Ek okumalar===
* {{proje bağlantısı|Vikipedi}}
bk8n79goaiqs47uncihywkck87po3sg
çıkış çizgisi
0
260001
5672720
5244424
2026-06-30T06:27:36Z
Satirdan kahraman
37401
TurkceMaddePanel
5672720
wikitext
text/x-wiki
==Türkçe==
===Köken===
*{{birleşik|dil=tr|çıkış|çizgi}}
===Söyleniş===
*{{tr-IPA}}
* {{h|dil=tr||çı|kış|çiz|gi|si}}
===Ad===
{{tr-ad}}
[[File:Starting line (Unsplash).jpg|küçükresim|Çıkış çizgisi ]]
# {{t|dil=tr|spor}} Yarışın başlama yerini belirleyen beyaz çizgi; [[başlangıç çizgisi]].
====Çekimleme====
{{tr-ad-tablo}}
===Kaynakça===
* {{KYK:TDK}}
aa0gyy6xhfy61bx5em20tc8q3teclto
çizgi roman
0
260223
5672721
5244747
2026-06-30T06:30:45Z
Satirdan kahraman
37401
TurkceMaddePanel
5672721
wikitext
text/x-wiki
==Türkçe==
===Köken===
*{{birleşik|dil=tr|çizgi|roman}}
===Söyleniş===
*{{tr-IPA}}
* {{h|dil=tr||çiz|gi|ro|man}}
===Ad===
{{tr-ad}}
[[File:Copenhagen Comics 2015 - Comics of Taiwan.JPG|küçükresim|Çizgi romanlar]]
#{{t|dil=tr|kitap}} Konuyu ve olaylar zincirini kesintisiz olarak resimleme yöntemiyle okuyucuya sunan roman.
#* "… bilgisayarında düşman askerlerini öldürüyor, çizgi roman okuyordu." - Gülsüm Cengiz
====Çekimleme====
{{tr-ad-tablo}}
===Kaynakça===
* {{KYK:TDK}}
===Ek okumalar===
*{{proje bağlantısı|Vikipedi}}
rtqq5r1s5lqioa7sktp8dqv9mixh7hp
dansöz
0
260532
5672556
5390947
2026-06-29T20:29:28Z
Satirdan kahraman
37401
TurkceMaddePanel
5672556
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{köken|dil=tr|fr}} {{b|fr|danseuse|anlam=kadın dansçı}} sözcüğünden. Bu sözcük Fransızca {{b|fr|danser|anlam=dans etmek}} fiilinden {{b|fr|+euse}} ekiyle türetilmiştir. Fransızca {{b|fr|danser}} fiili Germence tanıksız veya yeniden kurulmuş {{b|gem-pro|*dintjan|anlam=sallanmak, oynamak}} sözcüğünden alıntıdır.
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||dan|söz}}
===Ad===
{{tr-ad}}
[[File:Alla Kushnir, ukrainian belly dancer, 2015.png|küçükresim|Dansöz]]
#{{t|dil=tr|meslekler|dans |kadın}} Dans etmeyi meslek edinmiş kadın.
#* "Dansözü bu tip masalara yollayan cıvık insanlar da var çevrede." - Rauf Tamer
===Çekimleme===
{{tr-ad-tablo}}
====Çeviriler====
{{Üst|tip=çeviriler}}
*Felemenkçe: {{ç|nl|danseres}}, {{ç|nl|beroepsdanseres}}
*Fince: {{ç|fi|tanssijatar}}, {{ç|fi|vatsatanssija}}
*Fransızca: {{ç|fr|danseuse}}
*Kürtçe: {{ç|ku|çengî}}, {{ç|ku|sozan}], {{ç|ku|reqase}}, {{ç|ku|dansoz}}
*Rusça: {{ç|ru|танцовщица}}
{{Alt}}
====Kaynakça====
*{{kaynak-TDK}}
2dkcjky2sfub6t8gjuwapx00rhw6jwm
gürül gürül
0
263692
5672524
4870454
2026-06-29T19:10:10Z
Satirdan kahraman
37401
TurkceMaddePanel
5672524
wikitext
text/x-wiki
==Türkçe==
===Köken===
===Söyleniş===
*{{tr-IPA}}
* {{h|dil=tr||gü|rül|gü|rül}}
===Belirteç===
{{tr-belirteç}}
[[File:حاله-الطقس-الان.webm|küçükresim|Yağmur '''gürül gürül''' yağıyor.]]
# {{t|dil=tr|ses}} Bol ve gür çıkan veya akan şeylerin sesini anlatır
===Kaynakça===
* {{KYK:TDK}}
m3fjzmc6g92glm56ug2qsckpq65ce66
halka olmak
0
263848
5672625
4410647
2026-06-29T22:09:48Z
Satirdan kahraman
37401
TurkceMaddePanel
5672625
wikitext
text/x-wiki
==Türkçe==
===Köken===
*{{birleşik|dil=tr|halka|olmak}}
===Söyleniş===
*{{tr-IPA}}
*{{h|dil=tr||hal|ka|ol|mak}}
===Eylem===
{{tr-eylem}}
[[File:A group of naked people sit in a circle eating and drinking, Wellcome V0039363.jpg|küçükresim|İnsanlar '''halka olmuş,''' yemek yiyorlar.]]
# Bir çember biçiminde dizilmek.
#* {{tanıklık|dil=tr|yazar=Feyza HEPÇİLİNGİRLER|makale=Rio'da O Yaz Seninle|dergi=Öküz|sayı=41|yıl=1997|sayfa=20|metin=Tam orada yakılan ateşin çevresinde '''halka olmuş''' gençler yerel bir ezgiyi iyi hep bir ağızdan söyleyerek dönüyorlardı.}}
====Çekimleme====
{{tr-eylem-tablo}}
===Kaynakça===
* {{KYK:TDK}}
c7kvmsznsp9nrdm9vvnxyrkt7bckn8t
5672626
5672625
2026-06-29T22:11:17Z
Satirdan kahraman
37401
/* */ [[MediaWiki:Gadget-AjaxEdit.js|AjaxDüzenle]] kullanılarak değiştirildi
5672626
wikitext
text/x-wiki
==Türkçe==
===Köken===
*{{birleşik|dil=tr|halka|olmak}}
===Söyleniş===
*{{tr-IPA}}
*{{h|dil=tr||hal|ka|ol|mak}}
===Eylem===
{{tr-eylem}}
[[File:A Modern Village School- Education in Cambridgeshire, England, UK, 1944 D23630.jpg|küçükresim|Öğrenciler, '''halka olmuş,''' öğretmenlerini dinliyorlar.]]
# Bir çember biçiminde dizilmek.
#* {{tanıklık|dil=tr|yazar=Feyza HEPÇİLİNGİRLER|makale=Rio'da O Yaz Seninle|dergi=Öküz|sayı=41|yıl=1997|sayfa=20|metin=Tam orada yakılan ateşin çevresinde '''halka olmuş''' gençler yerel bir ezgiyi iyi hep bir ağızdan söyleyerek dönüyorlardı.}}
====Çekimleme====
{{tr-eylem-tablo}}
===Kaynakça===
* {{KYK:TDK}}
p7hw8rb5m53ipj4daw2t6iex1vk73b6
halka yay
0
263849
5672639
4410657
2026-06-29T22:21:00Z
Satirdan kahraman
37401
TurkceMaddePanel
5672639
wikitext
text/x-wiki
==Türkçe==
===Köken===
*{{birleşik|dil=tr|halka|yay}}
===Söyleniş===
*{{tr-IPA}}
*{{h|dil=tr||hal|ka|yay}}
===Ad===
{{tr-ad}}
#{{t|dil=tr|malzemeler}} [[anahtar|Boru anahtarının]] iyi tutmasını sağlayan ve çevreyle anahtar kolu arasına konulan sarmal yay.
====Çekimleme====
{{tr-ad-tablo}}
====Deyimler====
====Türetilmiş kavramlar====
===Kaynakça===
* {{KYK:TDK}}
qrw6n8ahlwuby0r7czu9bcmu9pmjxsq
suç aleti
0
278008
5672550
4517395
2026-06-29T19:46:59Z
Satirdan kahraman
37401
TurkceMaddePanel
5672550
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{birleşik|dil=tr|suç|alet}}
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||suç|a|le|ti}}
===Ad===
{{tr-ad}}
[[File:DC-1914-27-d-Sarajevo-cropped.jpg|küçükresim|Adam, '''suç aleti''' olarak siyah bir tabanca kullanıyor.]]
#{{t|dil=tr|suç}} Suçun işlendiği alet veya suçun işlenmesinde söz konusu olan alet.
#* "Katil suç aletini neden yatağının altında saklasın? Aptal mı bu adam?" - Pınar Kür
====Çekimleme====
{{tr-ad-tablo}}
===Kaynakça===
* {{KYK:TDK}}
o2l1ppx57v9zj8g149vldx0iyuszaay
yıl halkası
0
283820
5672627
4503236
2026-06-29T22:12:02Z
Satirdan kahraman
37401
TurkceMaddePanel
5672627
wikitext
text/x-wiki
==Türkçe==
===Köken===
*{{birleşik|dil=tr| }}
===Söyleniş===
*{{tr-IPA}}
* {{h|dil=tr||}}
===Ad===
{{tr-ad}}
#{{t|dil=tr}}
====Çekimleme====
{{tr-ad-tablo}}
====Deyimler====
====Türetilmiş kavramlar====
===Kaynakça===
* {{KYK:TDK}}
===Ek okumalar===
*{{proje bağlantısı|Vikipedi}}
stv7c5qv02yjsfki88fgotvsy7257er
5672628
5672627
2026-06-29T22:13:20Z
Satirdan kahraman
37401
TurkceMaddePanel
5672628
wikitext
text/x-wiki
==Türkçe==
===Köken===
*{{birleşik|dil=tr|yıl|halka}}
===Söyleniş===
*{{tr-IPA}}
*{{h|dil=tr||yıl|hal|ka|sı}}
===Ad===
{{tr-ad}}
[[File:Roughly 200 years old - 54480567079.jpg|küçükresim|'''Yıl halkaları.''']]
#{{t|dil=tr|bitki bilimi|ağaçlar|zamanın ölçülmesi}} Ağaçta, bir büyüme döneminde oluşan çembersel bölüm.
====Çekimleme====
{{tr-ad-tablo}}
===Kaynakça===
* {{KYK:TDK}}
ckw5ilsnafa7pqere7tj8tywxop75dm
yorumlamak
0
284103
5672547
4869510
2026-06-29T19:43:25Z
Satirdan kahraman
37401
TurkceMaddePanel
5672547
wikitext
text/x-wiki
==Türkçe==
===Söyleniş===
*{{tr-IPA}}
* {{h|dil=tr||yo|rum|la|mak}}
===Eylem===
{{tr-eylem}}
[[File:Olaus Magnus - On the Art of Prophecy.jpg|thumb|Kralın isteği üzerine ölü balıkları '''yorumlayan''' adamı gösteren bir çizim. (2)]]
#{{t|dil=tr|edebiyat|yazı}} Bir yazıyı veya bir sözü yorum yaparak açıklamak;, [[tefsir etmek]]
# Bir olaya, bir duruma bir anlam vermek; [[tabir etmek]]
#*''Hasan Bey istediği gibi yorumlayabilir, bu beni ilgilendirmez.'' - H. E. Adıvar
# {{t|dil=tr|müzik|tiyatro}} bir müzik parçasını veya bir tiyatro oyununu kendine özgü bir duyarlık ve teknikle çalmak, söylemek veya oynamak, [[icra etmek]]
====Çekimleme====
{{tr-eylem-tablo}}
====Çeviriler====
{{üst|tip=çeviriler}}
*Azerice: {{ç|az|şərh etmək}}, {{ç|az|kommentari vermək}}, {{ç|az|izah etmək}}
* Fransızca: {{ç|fr|commenter}}, {{ç|fr|interpréter}}
*Kürtçe: {{ç|ku|şîrove kirin}}
{{alt}}
===Kaynakça===
* {{KYK:TDK}}
1zgilwi2tft22j6h6vh6495m899mziv
театр
0
333294
5672561
4546986
2026-06-29T20:40:43Z
MustafaCavlak
59368
/* Rusça */
5672561
wikitext
text/x-wiki
==Rusça==
{{vikipedi|dil=ru}}
===Köken===
{{nakledilen|ru|fr|théâtre}}, {{kökenli|ru|la|theātrum}}, {{kökenli|ru|grc|θέατρον}}.
===Söyleniş===
* {{ses|dil=ru|Ru-театр.ogg}}
===Ad===
{{başlık başı|ru|ad|baş=теа́тр|c=e}}
# [[tiyatro]]
====Çekimleme====
{{ru-ad-cansız-s-E-a|теа́тр}}
===Kaynakça===
* {{R:ru:Vasmer}}
[[Kategori:Rusçada tiyatro]]
[[Kategori:Rusçada binalar]]
n7j61g7luf3my96c8w0ust03n4khfpb
Güneş tacı
0
375350
5672582
3919105
2026-06-29T20:57:02Z
Satirdan kahraman
37401
TurkceMaddePanel
5672582
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{birleşik|dil=tr|Güneş|tacı}}
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||gü|neş|ta|cı}}
===Ad===
{{tr-ad}}
[[Dosya:Solar_eclipse_1999_4.jpg|küçükresim|'''Güneş tacı,''' bir tutulma esnasında çıplak gözle görünmekte.]]
#{{t|dil=tr|gök bilimi}} [[Güneş]] atmosferinin yoğunluğu çok düşük ve çok sıcak en dış katmanı, [[korona]]
====Çekimleme====
{{tr-ad-tablo}}
====Çeviriler====
{{üst|tip=çeviriler}}
*Fince: {{ç|fi|korona}}
*İngilizce: {{ç|en|corona}}
{{alt}}
===Kaynakça===
* {{KYK:TDK}}
===Ek okumalar===
*{{proje bağlantısı|Vikipedi}}
gpsgv56tewna8ye7ylxmrcznvi00xe3
5672583
5672582
2026-06-29T20:57:24Z
Satirdan kahraman
37401
/* */ [[MediaWiki:Gadget-AjaxEdit.js|AjaxDüzenle]] kullanılarak değiştirildi
5672583
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{birleşik|dil=tr|Güneş|taç}}
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||gü|neş|ta|cı}}
===Ad===
{{tr-ad}}
[[Dosya:Solar_eclipse_1999_4.jpg|küçükresim|'''Güneş tacı,''' bir tutulma esnasında çıplak gözle görünmekte.]]
#{{t|dil=tr|gök bilimi}} [[Güneş]] atmosferinin yoğunluğu çok düşük ve çok sıcak en dış katmanı, [[korona]]
====Çekimleme====
{{tr-ad-tablo}}
====Çeviriler====
{{üst|tip=çeviriler}}
*Fince: {{ç|fi|korona}}
*İngilizce: {{ç|en|corona}}
{{alt}}
===Kaynakça===
* {{KYK:TDK}}
===Ek okumalar===
*{{proje bağlantısı|Vikipedi}}
02b8bcazoom2xp5eyem08zi0z4mz9yr
katılaşmak
0
386356
5672712
4882946
2026-06-30T06:16:22Z
Satirdan kahraman
37401
TurkceMaddePanel
5672712
wikitext
text/x-wiki
==Türkçe==
===Söyleniş===
*{{tr-IPA}}
* {{h|dil=tr||ka|tı|laş|mak}}
===Eylem===
{{tr-eylem}}
[[File:Pouring liquid mercury bionerd.jpg|küçükresim|Kaba dökülen sıvı, '''katılaşıyor''' (1)]]
# {{terim|dil=tr|kimya|fizik}} [[katı|Katı]] duruma gelmek.
#*''Çekilmişti sanki kara toprağın kanı / Yol soğumuş, '''katılaş'''mış bir ceset gibi -E. B. Koryürek.''
# İz bırakmak, belirgin duruma gelmek.
#*Bu tutumundan hoşlanmadığını belirten bir küçümsemenin çizgileri dondu, '''katılaş'''tı yüzünde. -N. Cumalı.''
====Çekimleme====
{{tr-eylem-tablo}}
====Kaynakça====
{{kaynak-TDK}}
l5mzu8ybv9s2w095nh46tqto1g651n0
takım elbise
0
388252
5672711
5667302
2026-06-30T06:15:06Z
Satirdan kahraman
37401
TurkceMaddePanel
5672711
wikitext
text/x-wiki
==Türkçe==
===Köken===
{{birleşik|dil=tr|takım|elbise}}
===Söyleniş===
*{{tr-IPA}}
*{{h|dil=tr||ta|kım|el|bi|se}}
===Ad===
{{tr-ad}}
[[File:Mannequins in Galeries de la Capitale 3.jpg|küçükresim|Mankenlerin üstünde '''takım elbise''' var.]]
# {{t|dil=tr|giyim}} Ceket ve pantolondan oluşan erkek giysisi, [[takım]]
===Çekimleme===
{{tr-ad-tablo}}
====Çeviriler====
{{üst|tip=çeviriler}}
*Almanca: {{ç|de|Anzug|m}}, {{ç|de|Straßenanzug|m}}
*Bulgarca: {{ç|bg|анцуг|m}}
*Fince: {{ç|fi|pukuyhdistelmä}}, {{ç|fi|kokopuku}}
*Fransızca: {{ç|fr|complet|m}}
*İngilizce: {{ç|en|suit}}
*İtalyanca: {{ç|it|abito completo|m}}
{{alt}}
===Kaynakça===
*{{KYK:TDK}}
===Ek okumalar===
*{{proje bağlantısı|Vikipedi}}
eyd713hq812tjlpbgj62fgfwgt5314s
korona
0
388425
5672581
5215791
2026-06-29T20:55:05Z
Satirdan kahraman
37401
/* */ [[MediaWiki:Gadget-AjaxEdit.js|AjaxDüzenle]] kullanılarak değiştirildi
5672581
wikitext
text/x-wiki
==Türkçe==
===Köken===
{{k|la|dil=tr}} {{ç|la|corona}}
===Söyleniş===
* {{IPA|/coˈɾona/|dil=tr}}
* {{h||ko|ro|na|dil=tr}}
===Ad===
{{tr-ad}} [[koronası|'''korona''' -sı]]
# {{t|astronomi|dil=tr}} [[Güneş tacı]]
# {{t|biyoloji|dil=tr}} aken tipi meyveye sahip bazı bitki meyvelerinin üzerinde taç şeklinde yer alan yapılar
# {{t|biyoloji|dil=tr}} rotator gibi bazı hayvanların ön tarafında bulunan silli, halkasal yapı
# {{t|kimya|yüksek gerilim|dil=tr}} yüksek gerilimli hatlarda ve kıvılcımla ateşlenen motorlarda daha çok gözlenen, oksijenin iyonlaşıp ozon oluşmasına sebep olan elektriksel boşalım etkisi. Oluşan ozonun şiddetli yükseltgeyici etkisinden dolayı bu tür yerlerdeki kablo, tel veya fiş bağlantılarında yükseltgenmeye dirençli naylon, neopren ve diğer sentetik maddeler kaplama için kullanılır.
# {{t|halk dili|dil=tr}} [[korona virüsü]] veya [[koronavirüs]] ifadesinin halk arasındaki adı.
====Kelime birliktelikleri====
* {{mânâ|biyoloji, viroloji}} [[korona virüsü]]
* {{mânâ|kimya, yüksek gerilim}} [[korona deşarjı]]
====Çeviriler====
{{üst|astronomi|tip=çeviriler}}
* Almanca: {{ç|de|Sonnenkorona|f}}
* Fince: {{ç|fi|korona}}
* İngilizce: {{ç|en|corona}}
* İsveççe: {{ç|sv|korona|c}}
* İtalyanca: {{ç|it|corona|c}}
{{alt}}
===Kaynakça===
* {{kaynak-TDK}}
===Ek okumalar===
* {{proje bağlantısı|Vikipedi}}
==Fince==
===Ad===
{{fi-ad}}
# {{t|astronomi|dil=fi}} [[Güneş tacı]], {{b|tr|korona}}
==Macarca==
===Ad===
{{başlık başı|hu|ad}}
# [[taç]], kraliyet tacı
# [[Macaristan]]'ın 1892 ila 1926 arasında kullandığı [[para birimi]]
6ue8ayftq9ctl058dttjava0iik1miv
5672585
5672581
2026-06-29T21:01:30Z
Satirdan kahraman
37401
TurkceMaddePanel
5672585
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{köken|dil=tr|NL.}} {{b|la|corona(virus)|anlam=bir tür virüs}} sözcüğünden. Bu sözcük Latince {{b|la|corona|anlam=taç}} sözcüğünden türetilmiştir.
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||ko|ro|na}}
===Ad===
{{tr-ad}}
[[Dosya:Solar_eclipse_1999_4.jpg|küçükresim|'''Korona,''' bir tutulma esnasında çıplak gözle görünmekte. (1)]]
# {{t|gök bilimi|dil=tr}} [[Güneş tacı]]
# {{t|biyoloji|dil=tr}} aken tipi meyveye sahip bazı bitki meyvelerinin üzerinde taç şeklinde yer alan yapılar
# {{t|biyoloji|dil=tr}} rotator gibi bazı hayvanların ön tarafında bulunan silli, halkasal yapı
# {{t|kimya|yüksek gerilim|dil=tr}} yüksek gerilimli hatlarda ve kıvılcımla ateşlenen motorlarda daha çok gözlenen, oksijenin iyonlaşıp ozon oluşmasına sebep olan elektriksel boşalım etkisi. Oluşan ozonun şiddetli yükseltgeyici etkisinden dolayı bu tür yerlerdeki kablo, tel veya fiş bağlantılarında yükseltgenmeye dirençli naylon, neopren ve diğer sentetik maddeler kaplama için kullanılır.
# {{t|halk dili|dil=tr}} [[koronavirüs]].
====Türetilmiş kavramlar====
[korona virüsü]], [[korona deşarjı]]
====Çeviriler====
{{üst|astronomi|tip=çeviriler}}
* Almanca: {{ç|de|Sonnenkorona|f}}
* Fince: {{ç|fi|korona}}
* İngilizce: {{ç|en|corona}}
* İsveççe: {{ç|sv|korona|c}}
* İtalyanca: {{ç|it|corona|c}}
{{alt}}
===Kaynakça===
* {{kaynak-TDK}}
===Ek okumalar===
* {{proje bağlantısı|Vikipedi}}
==Fince==
===Ad===
{{fi-ad}}
# {{t|astronomi|dil=fi}} [[Güneş tacı]], {{b|tr|korona}}
==Macarca==
===Ad===
{{başlık başı|hu|ad}}
# [[taç]], kraliyet tacı
# [[Macaristan]]'ın 1892 ila 1926 arasında kullandığı [[para birimi]]
8o29rvz9moggo7h2r9t43x5sm7rcfys
5672587
5672585
2026-06-29T21:02:31Z
Satirdan kahraman
37401
/* */ [[MediaWiki:Gadget-AjaxEdit.js|AjaxDüzenle]] kullanılarak değiştirildi
5672587
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{köken|dil=tr|la}} {{b|la|corona|anlam=taç}} sözcüğünden .
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||ko|ro|na}}
===Ad===
{{tr-ad}}
[[Dosya:Solar_eclipse_1999_4.jpg|küçükresim|'''Korona,''' bir tutulma esnasında çıplak gözle görünmekte. (1)]]
# {{t|gök bilimi|dil=tr}} [[Güneş tacı]]
# {{t|biyoloji|dil=tr}} aken tipi meyveye sahip bazı bitki meyvelerinin üzerinde taç şeklinde yer alan yapılar
# {{t|biyoloji|dil=tr}} rotator gibi bazı hayvanların ön tarafında bulunan silli, halkasal yapı
# {{t|kimya|yüksek gerilim|dil=tr}} yüksek gerilimli hatlarda ve kıvılcımla ateşlenen motorlarda daha çok gözlenen, oksijenin iyonlaşıp ozon oluşmasına sebep olan elektriksel boşalım etkisi. Oluşan ozonun şiddetli yükseltgeyici etkisinden dolayı bu tür yerlerdeki kablo, tel veya fiş bağlantılarında yükseltgenmeye dirençli naylon, neopren ve diğer sentetik maddeler kaplama için kullanılır.
# {{t|halk dili|dil=tr}} [[koronavirüs]].
====Türetilmiş kavramlar====
[korona virüsü]], [[korona deşarjı]]
====Çeviriler====
{{üst|astronomi|tip=çeviriler}}
* Almanca: {{ç|de|Sonnenkorona|f}}
* Fince: {{ç|fi|korona}}
* İngilizce: {{ç|en|corona}}
* İsveççe: {{ç|sv|korona|c}}
* İtalyanca: {{ç|it|corona|c}}
{{alt}}
===Kaynakça===
* {{kaynak-TDK}}
===Ek okumalar===
* {{proje bağlantısı|Vikipedi}}
==Fince==
===Ad===
{{fi-ad}}
# {{t|astronomi|dil=fi}} [[Güneş tacı]], {{b|tr|korona}}
==Macarca==
===Ad===
{{başlık başı|hu|ad}}
# [[taç]], kraliyet tacı
# [[Macaristan]]'ın 1892 ila 1926 arasında kullandığı [[para birimi]]
5xpfnkm2dtu263bnz36fu8wb80e9lpd
5672588
5672587
2026-06-29T21:02:59Z
Satirdan kahraman
37401
TurkceMaddePanel
5672588
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{köken|dil=tr|la}} {{b|la|corona|anlam=taç}} sözcüğünden .
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||ko|ro|na}}
===Ad===
{{tr-ad}}
[[Dosya:Solar_eclipse_1999_4.jpg|küçükresim|'''Korona,''' bir tutulma esnasında çıplak gözle görünmekte. (1)]]
# {{t|gök bilimi|dil=tr}} [[Güneş tacı]]
# {{t|biyoloji|dil=tr}} aken tipi meyveye sahip bazı bitki meyvelerinin üzerinde taç şeklinde yer alan yapılar
# {{t|biyoloji|dil=tr}} rotator gibi bazı hayvanların ön tarafında bulunan silli, halkasal yapı
# {{t|kimya|yüksek gerilim|dil=tr}} yüksek gerilimli hatlarda ve kıvılcımla ateşlenen motorlarda daha çok gözlenen, oksijenin iyonlaşıp ozon oluşmasına sebep olan elektriksel boşalım etkisi. Oluşan ozonun şiddetli yükseltgeyici etkisinden dolayı bu tür yerlerdeki kablo, tel veya fiş bağlantılarında yükseltgenmeye dirençli naylon, neopren ve diğer sentetik maddeler kaplama için kullanılır.
# {{t|halk dili|dil=tr}} [[koronavirüs]].
====Çekimleme====
{{tr-ad-tablo}}
====Türetilmiş kavramlar====
[[korona virüsü]], [[korona deşarjı]]
====Çeviriler====
{{üst|astronomi|tip=çeviriler}}
* Almanca: {{ç|de|Sonnenkorona|f}}
* Fince: {{ç|fi|korona}}
* İngilizce: {{ç|en|corona}}
* İsveççe: {{ç|sv|korona|c}}
* İtalyanca: {{ç|it|corona|c}}
{{alt}}
===Kaynakça===
* {{kaynak-TDK}}
===Ek okumalar===
* {{proje bağlantısı|Vikipedi}}
==Fince==
===Ad===
{{fi-ad}}
# {{t|astronomi|dil=fi}} [[Güneş tacı]], {{b|tr|korona}}
==Macarca==
===Ad===
{{başlık başı|hu|ad}}
# [[taç]], kraliyet tacı
# [[Macaristan]]'ın 1892 ila 1926 arasında kullandığı [[para birimi]]
glinxvbe56yahof936jqutp4xgnsz8j
Vikisözlük:Değişiklik sayılarına göre Vikisözlükçüler listesi
4
466356
5672590
5672368
2026-06-29T21:05:13Z
YBot
37147
Güncelleme
5672590
wikitext
text/x-wiki
{{/begin}}
<center>
{| class="wikitable"
! #
! Kullanıcı
! Değişiklik sayısı
! Kullanıcı grupları
|-
| 1
| [[Kullanıcı:HastaLaVi2|HastaLaVi2]]
| align="center" | 1.264.519
| arayüz yöneticisi, hizmetli
|-
| 2
| [[Kullanıcı:Victor Trevor|Victor Trevor]]
| align="center" | 144.832
|
|-
| 3
| [[Kullanıcı:MustafaCavlak|MustafaCavlak]]
| align="center" | 104.436
| hizmetli, geçici hesap IP görüntüleyici
|-
| 4
| [[Kullanıcı:Viki|Viki]]
| align="center" | 45.152
|
|-
| 5
| [[Kullanıcı:By erdo can|By erdo can]]
| align="center" | 42.866
|
|-
| 6
| [[Kullanıcı:Satirdan kahraman|Satirdan kahraman]]
| align="center" | 37.863
|
|-
| 7
| [[Kullanıcı:Sae1962|Sae1962]]
| align="center" | 34.149
|
|-
| 8
| [[Kullanıcı:Saltinbas|Saltinbas]]
| align="center" | 26.434
|
|-
| 9
| [[Kullanıcı:MüjdeA|MüjdeA]]
| align="center" | 25.502
|
|-
| 10
| [[Kullanıcı:Sabri76|Sabri76]]
| align="center" | 20.349
|
|-
| 11
| [[Kullanıcı:Katakay|Katakay]]
| align="center" | 19.415
|
|-
| 12
| [[Kullanıcı:Turgut46|Turgut46]]
| align="center" | 17.534
| hizmetli
|-
| 13
| [[Kullanıcı:Vuzorg|Vuzorg]]
| align="center" | 15.932
|
|-
| 14
| [[Kullanıcı:Ender|Ender]]
| align="center" | 14.945
|
|-
| 15
| [[Kullanıcı:Kök|Kök]]
| align="center" | 8.437
|
|-
| 16
| [[Kullanıcı:Curious|Curious]]
| align="center" | 7.438
|
|-
| 17
| [[Kullanıcı:Bobcats|Bobcats]]
| align="center" | 6.526
|
|-
| 18
| [[Kullanıcı:Nosferatü|Nosferatü]]
| align="center" | 6.408
|
|-
| 19
| [[Kullanıcı:Uncitoyen|Uncitoyen]]
| align="center" | 5.685
| hizmetli
|-
| 20
| [[Kullanıcı:Vikiyılmaz|Vikiyılmaz]]
| align="center" | 5.369
|
|-
| 21
| [[Kullanıcı:Sinek~trwiktionary|Sinek~trwiktionary]]
| align="center" | 5.221
|
|-
| 22
| [[Kullanıcı:YZCTEK|YZCTEK]]
| align="center" | 4.880
|
|-
| 23
| [[Kullanıcı:Vorhon|Vorhon]]
| align="center" | 4.699
|
|-
| 24
| [[Kullanıcı:LA2|LA2]]
| align="center" | 4.433
|
|-
| 25
| [[Kullanıcı:Apisite|Apisite]]
| align="center" | 4.428
|
|-
| 26
| [[Kullanıcı:B5.101.222.187|B5.101.222.187]]
| align="center" | 4.259
|
|-
| 27
| [[Kullanıcı:Kavurt|Kavurt]]
| align="center" | 4.088
|
|-
| 28
| [[Kullanıcı:Vitruvian|Vitruvian]]
| align="center" | 4.054
|
|-
| 29
| [[Kullanıcı:123snake45|123snake45]]
| align="center" | 3.971
|
|-
| 30
| [[Kullanıcı:Alikiroglu61|Alikiroglu61]]
| align="center" | 3.773
|
|-
| 31
| [[Kullanıcı:3210|3210]]
| align="center" | 3.716
|
|-
| 32
| [[Kullanıcı:Goreno|Goreno]]
| align="center" | 3.474
|
|-
| 33
| [[Kullanıcı:Runningfridgesrule|Runningfridgesrule]]
| align="center" | 3.119
|
|-
| 34
| [[Kullanıcı:Reality006|Reality006]]
| align="center" | 3.099
|
|-
| 35
| [[Kullanıcı:HâlitM|HâlitM]]
| align="center" | 3.052
|
|-
| 36
| [[Kullanıcı:Ahmed922229|Ahmed922229]]
| align="center" | 3.009
|
|-
| 37
| [[Kullanıcı:Barishan|Barishan]]
| align="center" | 2.971
|
|-
| 38
| [[Kullanıcı:Ekrem691|Ekrem691]]
| align="center" | 2.398
|
|-
| 39
| [[Kullanıcı:Esege|Esege]]
| align="center" | 2.321
|
|-
| 40
| [[Kullanıcı:Ugur Basak|Ugur Basak]]
| align="center" | 2.267
|
|-
| 41
| [[Kullanıcı:Gamlıbaykuş|Gamlıbaykuş]]
| align="center" | 2.098
|
|-
| 42
| [[Kullanıcı:AML ZİYA AKYASAN|AML ZİYA AKYASAN]]
| align="center" | 1.989
|
|-
| 43
| [[Kullanıcı:Entry62|Entry62]]
| align="center" | 1.959
|
|-
| 44
| [[Kullanıcı:Magurale|Magurale]]
| align="center" | 1.854
|
|-
| 45
| [[Kullanıcı:Sihl fatma|Sihl fatma]]
| align="center" | 1.835
|
|-
| 46
| [[Kullanıcı:Don Alessandro|Don Alessandro]]
| align="center" | 1.815
|
|-
| 47
| [[Kullanıcı:Burudet88|Burudet88]]
| align="center" | 1.791
|
|-
| 48
| [[Kullanıcı:Şêr|Şêr]]
| align="center" | 1.668
|
|-
| 49
| [[Kullanıcı:Abuk78|Abuk78]]
| align="center" | 1.534
|
|-
| 50
| [[Kullanıcı:Göktürker|Göktürker]]
| align="center" | 1.508
|
|-
| 51
| [[Kullanıcı:Flanoz|Flanoz]]
| align="center" | 1.463
|
|-
| 52
| [[Kullanıcı:Sa'y|Sa'y]]
| align="center" | 1.345
|
|-
| 53
| [[Kullanıcı:Mzekiu|Mzekiu]]
| align="center" | 1.344
|
|-
| 54
| [[Kullanıcı:Samleml enes bilgin|Samleml enes bilgin]]
| align="center" | 1.315
|
|-
| 55
| [[Kullanıcı:İbrahim alican|İbrahim alican]]
| align="center" | 1.292
|
|-
| 56
| [[Kullanıcı:SİHL Gökhan|SİHL Gökhan]]
| align="center" | 1.278
|
|-
| 57
| [[Kullanıcı:Nazendegül|Nazendegül]]
| align="center" | 1.260
|
|-
| 58
| [[Kullanıcı:ליאון12|ליאון12]]
| align="center" | 1.178
|
|-
| 59
| [[Kullanıcı:Semlaml110|Semlaml110]]
| align="center" | 1.174
|
|-
| 60
| [[Kullanıcı:Ahmetaslan|Ahmetaslan]]
| align="center" | 1.141
|
|-
| 61
| [[Kullanıcı:Kibele|Kibele]]
| align="center" | 1.136
|
|-
| 62
| [[Kullanıcı:Wwww8888|Wwww8888]]
| align="center" | 1.125
|
|-
| 63
| [[Kullanıcı:Kmlblg 332|Kmlblg 332]]
| align="center" | 1.124
|
|-
| 64
| [[Kullanıcı:Lagrium|Lagrium]]
| align="center" | 1.094
|
|-
| 65
| [[Kullanıcı:SİHL ALİ MUSA|SİHL ALİ MUSA]]
| align="center" | 1.045
|
|-
| 66
| [[Kullanıcı:Ömer faruk çakmak|Ömer faruk çakmak]]
| align="center" | 996
|
|-
| 67
| [[Kullanıcı:Aybeg|Aybeg]]
| align="center" | 968
|
|-
| 68
| [[Kullanıcı:ВМНС|ВМНС]]
| align="center" | 962
|
|-
| 69
| [[Kullanıcı:Almanbet Janışev|Almanbet Janışev]]
| align="center" | 954
|
|-
| 70
| [[Kullanıcı:Seksen iki yüz kırk beş|Seksen iki yüz kırk beş]]
| align="center" | 931
|
|-
| 71
| [[Kullanıcı:Maxa|Maxa]]
| align="center" | 912
|
|-
| 72
| [[Kullanıcı:Wiamboo|Wiamboo]]
| align="center" | 880
|
|-
| 73
| [[Kullanıcı:SİHL Menzulekumaş|SİHL Menzulekumaş]]
| align="center" | 846
|
|-
| 74
| [[Kullanıcı:Melkorettin|Melkorettin]]
| align="center" | 812
|
|-
| 75
| [[Kullanıcı:Yasemin|Yasemin]]
| align="center" | 802
|
|-
| 76
| [[Kullanıcı:Peirep|Peirep]]
| align="center" | 791
|
|-
| 77
| [[Kullanıcı:Jeuwre|Jeuwre]]
| align="center" | 786
|
|-
| 78
| [[Kullanıcı:S.ihl.selmaaksoy|S.ihl.selmaaksoy]]
| align="center" | 781
|
|-
| 79
| [[Kullanıcı:Gibranist|Gibranist]]
| align="center" | 773
|
|-
| 80
| [[Kullanıcı:Kmlblgfatmanur|Kmlblgfatmanur]]
| align="center" | 771
|
|-
| 81
| [[Kullanıcı:Asım Hoca|Asım Hoca]]
| align="center" | 765
|
|-
| 82
| [[Kullanıcı:Malafaya|Malafaya]]
| align="center" | 765
|
|-
| 83
| [[Kullanıcı:Hagvoda|Hagvoda]]
| align="center" | 760
|
|-
| 84
| [[Kullanıcı:YosefHan7|YosefHan7]]
| align="center" | 756
|
|-
| 85
| [[Kullanıcı:Mustafahoca|Mustafahoca]]
| align="center" | 745
|
|-
| 86
| [[Kullanıcı:ZazaLejyoner|ZazaLejyoner]]
| align="center" | 740
|
|-
| 87
| [[Kullanıcı:Sürmene aml ve eml yusufcakir|Sürmene aml ve eml yusufcakir]]
| align="center" | 721
|
|-
| 88
| [[Kullanıcı:Mehmet-k61|Mehmet-k61]]
| align="center" | 670
|
|-
| 89
| [[Kullanıcı:Sinus46|Sinus46]]
| align="center" | 670
|
|-
| 90
| [[Kullanıcı:Kml serhan|Kml serhan]]
| align="center" | 668
|
|-
| 91
| [[Kullanıcı:TrDAsh|TrDAsh]]
| align="center" | 639
|
|-
| 92
| [[Kullanıcı:Itidal|Itidal]]
| align="center" | 635
|
|-
| 93
| [[Kullanıcı:Ömerbysl|Ömerbysl]]
| align="center" | 635
|
|-
| 94
| [[Kullanıcı:Chelik99|Chelik99]]
| align="center" | 587
|
|-
| 95
| [[Kullanıcı:Mereyü|Mereyü]]
| align="center" | 556
|
|-
| 96
| [[Kullanıcı:Octahedron80|Octahedron80]]
| align="center" | 547
|
|-
| 97
| [[Kullanıcı:ALİ İHSAN KARAMAN|ALİ İHSAN KARAMAN]]
| align="center" | 533
|
|-
| 98
| [[Kullanıcı:Gullerdiyari|Gullerdiyari]]
| align="center" | 520
|
|-
| 99
| [[Kullanıcı:Yeniler|Yeniler]]
| align="center" | 515
|
|-
| 100
| [[Kullanıcı:Andac20|Andac20]]
| align="center" | 509
|
|-
| 101
| [[Kullanıcı:Dilyâresi|Dilyâresi]]
| align="center" | 485
|
|-
| 102
| [[Kullanıcı:Nerepla Keskin|Nerepla Keskin]]
| align="center" | 483
|
|-
| 103
| [[Kullanıcı:Berkucar0|Berkucar0]]
| align="center" | 473
|
|-
| 104
| [[Kullanıcı:İsmetaydin|İsmetaydin]]
| align="center" | 465
|
|-
| 105
| [[Kullanıcı:Sadmleml enes|Sadmleml enes]]
| align="center" | 464
|
|-
| 106
| [[Kullanıcı:Condmatstrel|Condmatstrel]]
| align="center" | 461
|
|-
| 107
| [[Kullanıcı:Wutsje|Wutsje]]
| align="center" | 440
|
|-
| 108
| [[Kullanıcı:Lo Ximiendo|Lo Ximiendo]]
| align="center" | 435
|
|-
| 109
| [[Kullanıcı:Kml znnt|Kml znnt]]
| align="center" | 430
|
|-
| 110
| [[Kullanıcı:CommonsDelinker|CommonsDelinker]]
| align="center" | 423
|
|-
| 111
| [[Kullanıcı:Kendim|Kendim]]
| align="center" | 418
|
|-
| 112
| [[Kullanıcı:Pathoschild|Pathoschild]]
| align="center" | 413
|
|-
| 113
| [[Kullanıcı:Kemal.KURBAN|Kemal.KURBAN]]
| align="center" | 413
|
|-
| 114
| [[Kullanıcı:Merbeg|Merbeg]]
| align="center" | 410
|
|-
| 115
| [[Kullanıcı:Hamzahoca|Hamzahoca]]
| align="center" | 405
|
|-
| 116
| [[Kullanıcı:AHMET AYSOY|AHMET AYSOY]]
| align="center" | 393
|
|-
| 117
| [[Kullanıcı:Sihl ayhan|Sihl ayhan]]
| align="center" | 385
|
|-
| 118
| [[Kullanıcı:A.d.m.l.ve.e.m.lmuhammet alican|A.d.m.l.ve.e.m.lmuhammet alican]]
| align="center" | 383
|
|-
| 119
| [[Kullanıcı:Kvazimodo|Kvazimodo]]
| align="center" | 381
|
|-
| 120
| [[Kullanıcı:Muhammet yardım|Muhammet yardım]]
| align="center" | 378
|
|-
| 121
| [[Kullanıcı:Egemensen~trwiktionary|Egemensen~trwiktionary]]
| align="center" | 376
|
|-
| 122
| [[Kullanıcı:Johnny281993|Johnny281993]]
| align="center" | 376
|
|-
| 123
| [[Kullanıcı:Türkçe|Türkçe]]
| align="center" | 368
|
|-
| 124
| [[Kullanıcı:Vito Genovese|Vito Genovese]]
| align="center" | 365
|
|-
| 125
| [[Kullanıcı:Ata Kemal|Ata Kemal]]
| align="center" | 365
|
|-
| 126
| [[Kullanıcı:ToprakM|ToprakM]]
| align="center" | 365
|
|-
| 127
| [[Kullanıcı:Yunus Emre Biçer|Yunus Emre Biçer]]
| align="center" | 364
|
|-
| 128
| [[Kullanıcı:Bm|Bm]]
| align="center" | 347
|
|-
| 129
| [[Kullanıcı:Ampouble|Ampouble]]
| align="center" | 343
|
|-
| 130
| [[Kullanıcı:SLÖzlem|SLÖzlem]]
| align="center" | 343
|
|-
| 131
| [[Kullanıcı:S.orsev.ayşe kibaroğlu|S.orsev.ayşe kibaroğlu]]
| align="center" | 341
|
|-
| 132
| [[Kullanıcı:MelekArı|MelekArı]]
| align="center" | 336
|
|-
| 133
| [[Kullanıcı:Tegel|Tegel]]
| align="center" | 313
|
|-
| 134
| [[Kullanıcı:The cat|The cat]]
| align="center" | 311
|
|-
| 135
| [[Kullanıcı:SAL 378|SAL 378]]
| align="center" | 305
|
|-
| 136
| [[Kullanıcı:Saml livess 61|Saml livess 61]]
| align="center" | 297
|
|-
| 137
| [[Kullanıcı:Guljan|Guljan]]
| align="center" | 296
|
|-
| 138
| [[Kullanıcı:Kmlblg272|Kmlblg272]]
| align="center" | 292
|
|-
| 139
| [[Kullanıcı:SLDerya|SLDerya]]
| align="center" | 292
|
|-
| 140
| [[Kullanıcı:Srhat|Srhat]]
| align="center" | 285
|
|-
| 141
| [[Kullanıcı:2004onuralp|2004onuralp]]
| align="center" | 285
|
|-
| 142
| [[Kullanıcı:Swam pl|Swam pl]]
| align="center" | 284
|
|-
| 143
| [[Kullanıcı:Kml ibrahim|Kml ibrahim]]
| align="center" | 275
|
|-
| 144
| [[Kullanıcı:MSchoentgen|MSchoentgen]]
| align="center" | 274
|
|-
| 145
| [[Kullanıcı:Underfell Flowey|Underfell Flowey]]
| align="center" | 270
|
|-
| 146
| [[Kullanıcı:Dbl2010|Dbl2010]]
| align="center" | 264
|
|-
| 147
| [[Kullanıcı:Funda|Funda]]
| align="center" | 260
|
|-
| 148
| [[Kullanıcı:Kebab in my butt|Kebab in my butt]]
| align="center" | 260
|
|-
| 149
| [[Kullanıcı:Biyolojiyabikurdi|Biyolojiyabikurdi]]
| align="center" | 258
|
|-
| 150
| [[Kullanıcı:Arhancelo|Arhancelo]]
| align="center" | 256
|
|-
| 151
| [[Kullanıcı:SLnuray|SLnuray]]
| align="center" | 251
|
|-
| 152
| [[Kullanıcı:Gilthuanas|Gilthuanas]]
| align="center" | 250
|
|-
| 153
| [[Kullanıcı:Yorınçga573|Yorınçga573]]
| align="center" | 249
|
|-
| 154
| [[Kullanıcı:SL.resul akyıldız|SL.resul akyıldız]]
| align="center" | 247
|
|-
| 155
| [[Kullanıcı:SLözgül|SLözgül]]
| align="center" | 246
|
|-
| 156
| [[Kullanıcı:Azxpetro|Azxpetro]]
| align="center" | 244
|
|-
| 157
| [[Kullanıcı:Determinator|Determinator]]
| align="center" | 243
|
|-
| 158
| [[Kullanıcı:Серк.123|Серк.123]]
| align="center" | 243
|
|-
| 159
| [[Kullanıcı:Ceaeven|Ceaeven]]
| align="center" | 240
|
|-
| 160
| [[Kullanıcı:Sihl gülten deveci|Sihl gülten deveci]]
| align="center" | 237
|
|-
| 161
| [[Kullanıcı:Axbyc|Axbyc]]
| align="center" | 236
|
|-
| 162
| [[Kullanıcı:Superyetkin|Superyetkin]]
| align="center" | 235
| arayüz yöneticisi
|-
| 163
| [[Kullanıcı:Wikihez|Wikihez]]
| align="center" | 228
|
|-
| 164
| [[Kullanıcı:SLFatma|SLFatma]]
| align="center" | 227
|
|-
| 165
| [[Kullanıcı:Kmlblg240|Kmlblg240]]
| align="center" | 224
|
|-
| 166
| [[Kullanıcı:Erdemaslancan|Erdemaslancan]]
| align="center" | 224
|
|-
| 167
| [[Kullanıcı:Stml 172|Stml 172]]
| align="center" | 220
|
|-
| 168
| [[Kullanıcı:SLUğurcan|SLUğurcan]]
| align="center" | 219
|
|-
| 169
| [[Kullanıcı:Deknuydt|Deknuydt]]
| align="center" | 217
|
|-
| 170
| [[Kullanıcı:Kwamikagami|Kwamikagami]]
| align="center" | 212
|
|-
| 171
| [[Kullanıcı:Axis09|Axis09]]
| align="center" | 210
|
|-
| 172
| [[Kullanıcı:OSMAN ÇAVUŞLU|OSMAN ÇAVUŞLU]]
| align="center" | 209
|
|-
| 173
| [[Kullanıcı:Public class|Public class]]
| align="center" | 208
|
|-
| 174
| [[Kullanıcı:Aivasedo|Aivasedo]]
| align="center" | 205
|
|-
| 175
| [[Kullanıcı:Sal 390|Sal 390]]
| align="center" | 203
|
|-
| 176
| [[Kullanıcı:Onuralpateş2004|Onuralpateş2004]]
| align="center" | 202
|
|-
| 177
| [[Kullanıcı:Aslan yakup|Aslan yakup]]
| align="center" | 197
|
|-
| 178
| [[Kullanıcı:SLebru|SLebru]]
| align="center" | 197
|
|-
| 179
| [[Kullanıcı:Sal-zeynep|Sal-zeynep]]
| align="center" | 196
|
|-
| 180
| [[Kullanıcı:SLRahman|SLRahman]]
| align="center" | 194
|
|-
| 181
| [[Kullanıcı:Chapultepec|Chapultepec]]
| align="center" | 193
|
|-
| 182
| [[Kullanıcı:Trong Dang|Trong Dang]]
| align="center" | 192
|
|-
| 183
| [[Kullanıcı:Syum90|Syum90]]
| align="center" | 185
|
|-
| 184
| [[Kullanıcı:NURULLAH GÜLDAL|NURULLAH GÜLDAL]]
| align="center" | 183
|
|-
| 185
| [[Kullanıcı:Vikiçizer|Vikiçizer]]
| align="center" | 182
|
|-
| 186
| [[Kullanıcı:MehmedKM|MehmedKM]]
| align="center" | 182
|
|-
| 187
| [[Kullanıcı:Bikarhêner|Bikarhêner]]
| align="center" | 180
|
|-
| 188
| [[Kullanıcı:Şaşılık|Şaşılık]]
| align="center" | 179
|
|-
| 189
| [[Kullanıcı:Felecita|Felecita]]
| align="center" | 176
|
|-
| 190
| [[Kullanıcı:Ddenkel~trwiktionary|Ddenkel~trwiktionary]]
| align="center" | 175
|
|-
| 191
| [[Kullanıcı:Sezinumaykucuk|Sezinumaykucuk]]
| align="center" | 175
|
|-
| 192
| [[Kullanıcı:Sallapattias|Sallapattias]]
| align="center" | 171
|
|-
| 193
| [[Kullanıcı:SLburhantuncer|SLburhantuncer]]
| align="center" | 168
|
|-
| 194
| [[Kullanıcı:Bahattin|Bahattin]]
| align="center" | 168
|
|-
| 195
| [[Kullanıcı:Kml suleakguc|Kml suleakguc]]
| align="center" | 167
|
|-
| 196
| [[Kullanıcı:Sihl ASİYE|Sihl ASİYE]]
| align="center" | 167
|
|-
| 197
| [[Kullanıcı:Mehmetkasımay|Mehmetkasımay]]
| align="center" | 165
|
|-
| 198
| [[Kullanıcı:SLfatma254|SLfatma254]]
| align="center" | 163
|
|-
| 199
| [[Kullanıcı:Yko 235|Yko 235]]
| align="center" | 162
|
|-
| 200
| [[Kullanıcı:Stml 158|Stml 158]]
| align="center" | 159
|
|-
| 201
| [[Kullanıcı:Stml 121|Stml 121]]
| align="center" | 156
|
|-
| 202
| [[Kullanıcı:SLEngin|SLEngin]]
| align="center" | 154
|
|-
| 203
| [[Kullanıcı:Serdar62|Serdar62]]
| align="center" | 154
|
|-
| 204
| [[Kullanıcı:Terryclient|Terryclient]]
| align="center" | 151
|
|-
| 205
| [[Kullanıcı:Czeski Wratek|Czeski Wratek]]
| align="center" | 151
|
|-
| 206
| [[Kullanıcı:Calq|Calq]]
| align="center" | 148
|
|-
| 207
| [[Kullanıcı:Sihl Ramazan Erdöl|Sihl Ramazan Erdöl]]
| align="center" | 146
|
|-
| 208
| [[Kullanıcı:Drabdullayev17|Drabdullayev17]]
| align="center" | 140
|
|-
| 209
| [[Kullanıcı:Lionel Cristiano|Lionel Cristiano]]
| align="center" | 139
|
|-
| 210
| [[Kullanıcı:Hasan Sami|Hasan Sami]]
| align="center" | 138
|
|-
| 211
| [[Kullanıcı:Abuk SABUK|Abuk SABUK]]
| align="center" | 138
|
|-
| 212
| [[Kullanıcı:Dilci|Dilci]]
| align="center" | 137
|
|-
| 213
| [[Kullanıcı:Matiia|Matiia]]
| align="center" | 137
|
|-
| 214
| [[Kullanıcı:SİHL İSA ELER|SİHL İSA ELER]]
| align="center" | 135
|
|-
| 215
| [[Kullanıcı:Ata Kemal Ayaser|Ata Kemal Ayaser]]
| align="center" | 135
|
|-
| 216
| [[Kullanıcı:Emperyan|Emperyan]]
| align="center" | 135
|
|-
| 217
| [[Kullanıcı:Lou|Lou]]
| align="center" | 133
|
|-
| 218
| [[Kullanıcı:Rolby|Rolby]]
| align="center" | 133
|
|-
| 219
| [[Kullanıcı:Peter Berbe|Peter Berbe]]
| align="center" | 133
|
|-
| 220
| [[Kullanıcı:Eminovič|Eminovič]]
| align="center" | 132
|
|-
| 221
| [[Kullanıcı:Hdayetozsoy|Hdayetozsoy]]
| align="center" | 131
|
|-
| 222
| [[Kullanıcı:Fankibiber|Fankibiber]]
| align="center" | 129
|
|-
| 223
| [[Kullanıcı:GerardM|GerardM]]
| align="center" | 125
|
|-
| 224
| [[Kullanıcı:Ka dir 641|Ka dir 641]]
| align="center" | 125
|
|-
| 225
| [[Kullanıcı:Mesutbolukbas|Mesutbolukbas]]
| align="center" | 124
|
|-
| 226
| [[Kullanıcı:SLemine607 10D|SLemine607 10D]]
| align="center" | 122
|
|-
| 227
| [[Kullanıcı:Tarihçi Selo|Tarihçi Selo]]
| align="center" | 120
|
|-
| 228
| [[Kullanıcı:Lambiam|Lambiam]]
| align="center" | 120
|
|-
| 229
| [[Kullanıcı:Dodecaplex|Dodecaplex]]
| align="center" | 120
|
|-
| 230
| [[Kullanıcı:Vay~trwiktionary|Vay~trwiktionary]]
| align="center" | 119
|
|-
| 231
| [[Kullanıcı:Yavuz Atasever|Yavuz Atasever]]
| align="center" | 118
|
|-
| 232
| [[Kullanıcı:Metal Militia|Metal Militia]]
| align="center" | 117
|
|-
| 233
| [[Kullanıcı:Aarp65|Aarp65]]
| align="center" | 117
|
|-
| 234
| [[Kullanıcı:Eyüp Türküm|Eyüp Türküm]]
| align="center" | 117
|
|-
| 235
| [[Kullanıcı:Kalem.metin|Kalem.metin]]
| align="center" | 117
|
|-
| 236
| [[Kullanıcı:Mario The PS2 Guy|Mario The PS2 Guy]]
| align="center" | 117
|
|-
| 237
| [[Kullanıcı:Meyegon|Meyegon]]
| align="center" | 115
|
|-
| 238
| [[Kullanıcı:Cûndûllah el-Kurdî|Cûndûllah el-Kurdî]]
| align="center" | 115
|
|-
| 239
| [[Kullanıcı:Minorax|Minorax]]
| align="center" | 115
|
|-
| 240
| [[Kullanıcı:Baris6161TURK|Baris6161TURK]]
| align="center" | 113
|
|-
| 241
| [[Kullanıcı:Kml 207aysegül|Kml 207aysegül]]
| align="center" | 112
|
|-
| 242
| [[Kullanıcı:SLseda|SLseda]]
| align="center" | 111
|
|-
| 243
| [[Kullanıcı:Kmoksy|Kmoksy]]
| align="center" | 111
|
|-
| 244
| [[Kullanıcı:LesChloroformistes|LesChloroformistes]]
| align="center" | 110
|
|-
| 245
| [[Kullanıcı:Ladsgroup|Ladsgroup]]
| align="center" | 109
|
|-
| 246
| [[Kullanıcı:Müntesib|Müntesib]]
| align="center" | 109
|
|-
| 247
| [[Kullanıcı:Kmlrbabalik|Kmlrbabalik]]
| align="center" | 108
|
|-
| 248
| [[Kullanıcı:Kmlblg86|Kmlblg86]]
| align="center" | 108
|
|-
| 249
| [[Kullanıcı:S htk 117|S htk 117]]
| align="center" | 105
|
|-
| 250
| [[Kullanıcı:SLGamze|SLGamze]]
| align="center" | 105
|
|-
| 251
| [[Kullanıcı:Doğru Tercüman|Doğru Tercüman]]
| align="center" | 105
|
|-
| 252
| [[Kullanıcı:Küçükdere iöo gülay|Küçükdere iöo gülay]]
| align="center" | 104
|
|-
| 253
| [[Kullanıcı:Gülşah|Gülşah]]
| align="center" | 102
|
|-
| 254
| [[Kullanıcı:Balamax|Balamax]]
| align="center" | 102
|
|-
| 255
| [[Kullanıcı:Ormanbotanigi|Ormanbotanigi]]
| align="center" | 101
|
|-
| 256
| [[Kullanıcı:Stml 176|Stml 176]]
| align="center" | 101
|
|-
| 257
| [[Kullanıcı:Stml 165|Stml 165]]
| align="center" | 101
|
|-
| 258
| [[Kullanıcı:Kmlblg399|Kmlblg399]]
| align="center" | 100
|
|-
| 259
| [[Kullanıcı:Nerval|Nerval]]
| align="center" | 99
|
|-
| 260
| [[Kullanıcı:Stml 72|Stml 72]]
| align="center" | 98
|
|-
| 261
| [[Kullanıcı:Stryn|Stryn]]
| align="center" | 97
|
|-
| 262
| [[Kullanıcı:Küçükdere iöo sinan|Küçükdere iöo sinan]]
| align="center" | 96
|
|-
| 263
| [[Kullanıcı:Dünya vatandaşı|Dünya vatandaşı]]
| align="center" | 95
|
|-
| 264
| [[Kullanıcı:Muhammet yazıcı|Muhammet yazıcı]]
| align="center" | 95
|
|-
| 265
| [[Kullanıcı:SİHL 729|SİHL 729]]
| align="center" | 95
|
|-
| 266
| [[Kullanıcı:Xorasan|Xorasan]]
| align="center" | 95
|
|-
| 267
| [[Kullanıcı:Fiilçeker|Fiilçeker]]
| align="center" | 94
|
|-
| 268
| [[Kullanıcı:RadiX|RadiX]]
| align="center" | 94
|
|-
| 269
| [[Kullanıcı:Muallim Fatih|Muallim Fatih]]
| align="center" | 94
|
|-
| 270
| [[Kullanıcı:Marrovi|Marrovi]]
| align="center" | 94
|
|-
| 271
| [[Kullanıcı:Spacebirdy|Spacebirdy]]
| align="center" | 93
|
|-
| 272
| [[Kullanıcı:MhmtÖ|MhmtÖ]]
| align="center" | 93
|
|-
| 273
| [[Kullanıcı:Berr.in|Berr.in]]
| align="center" | 92
|
|-
| 274
| [[Kullanıcı:SL-busenur.523|SL-busenur.523]]
| align="center" | 91
|
|-
| 275
| [[Kullanıcı:SLİpek|SLİpek]]
| align="center" | 90
|
|-
| 276
| [[Kullanıcı:Kmlblgözlem|Kmlblgözlem]]
| align="center" | 89
|
|-
| 277
| [[Kullanıcı:Cavlak-FS|Cavlak-FS]]
| align="center" | 88
|
|-
| 278
| [[Kullanıcı:Azminwan|Azminwan]]
| align="center" | 87
|
|-
| 279
| [[Kullanıcı:Moonpulsar|Moonpulsar]]
| align="center" | 87
|
|-
| 280
| [[Kullanıcı:Stml 171|Stml 171]]
| align="center" | 86
|
|-
| 281
| [[Kullanıcı:Turkmen|Turkmen]]
| align="center" | 85
|
|-
| 282
| [[Kullanıcı:Xyz...|Xyz...]]
| align="center" | 84
|
|-
| 283
| [[Kullanıcı:Stml 117|Stml 117]]
| align="center" | 83
|
|-
| 284
| [[Kullanıcı:Juliancolton|Juliancolton]]
| align="center" | 81
|
|-
| 285
| [[Kullanıcı:Ludwig20|Ludwig20]]
| align="center" | 81
|
|-
| 286
| [[Kullanıcı:2004ateş|2004ateş]]
| align="center" | 81
|
|-
| 287
| [[Kullanıcı:Süleymanbedir|Süleymanbedir]]
| align="center" | 80
|
|-
| 288
| [[Kullanıcı:Kıdemli|Kıdemli]]
| align="center" | 80
|
|-
| 289
| [[Kullanıcı:Karabat Kuşu|Karabat Kuşu]]
| align="center" | 79
|
|-
| 290
| [[Kullanıcı:SAML VE EML CEMİL BAYRAM|SAML VE EML CEMİL BAYRAM]]
| align="center" | 79
|
|-
| 291
| [[Kullanıcı:Semlaml111|Semlaml111]]
| align="center" | 79
|
|-
| 292
| [[Kullanıcı:SEML Turan ÇAKIR|SEML Turan ÇAKIR]]
| align="center" | 78
|
|-
| 293
| [[Kullanıcı:Küçükdere iöo celilakyürek|Küçükdere iöo celilakyürek]]
| align="center" | 78
|
|-
| 294
| [[Kullanıcı:SLemine613|SLemine613]]
| align="center" | 78
|
|-
| 295
| [[Kullanıcı:Dokuz sekiz|Dokuz sekiz]]
| align="center" | 78
|
|-
| 296
| [[Kullanıcı:Sayonzei|Sayonzei]]
| align="center" | 78
|
|-
| 297
| [[Kullanıcı:İlhanbiskin|İlhanbiskin]]
| align="center" | 77
|
|-
| 298
| [[Kullanıcı:İsmailhoca|İsmailhoca]]
| align="center" | 77
|
|-
| 299
| [[Kullanıcı:Kmlblg80|Kmlblg80]]
| align="center" | 77
|
|-
| 300
| [[Kullanıcı:Masseman|Masseman]]
| align="center" | 76
|
|-
| 301
| [[Kullanıcı:Ridvanu|Ridvanu]]
| align="center" | 75
|
|-
| 302
| [[Kullanıcı:Ege yalcin~trwiktionary|Ege yalcin~trwiktionary]]
| align="center" | 75
|
|-
| 303
| [[Kullanıcı:İbrhm.kuru|İbrhm.kuru]]
| align="center" | 73
|
|-
| 304
| [[Kullanıcı:Mustafa Eşitgen|Mustafa Eşitgen]]
| align="center" | 73
|
|-
| 305
| [[Kullanıcı:Fagus|Fagus]]
| align="center" | 73
|
|-
| 306
| [[Kullanıcı:SL Pelin|SL Pelin]]
| align="center" | 72
|
|-
| 307
| [[Kullanıcı:Seninbey~trwiktionary|Seninbey~trwiktionary]]
| align="center" | 72
|
|-
| 308
| [[Kullanıcı:EmrahÖ|EmrahÖ]]
| align="center" | 72
|
|-
| 309
| [[Kullanıcı:BitikciKebbenek|BitikciKebbenek]]
| align="center" | 72
|
|-
| 310
| [[Kullanıcı:Emree4|Emree4]]
| align="center" | 71
|
|-
| 311
| [[Kullanıcı:Kontrolcu|Kontrolcu]]
| align="center" | 71
|
|-
| 312
| [[Kullanıcı:Nebra|Nebra]]
| align="center" | 71
|
|-
| 313
| [[Kullanıcı:Pembe karadeniz|Pembe karadeniz]]
| align="center" | 71
|
|-
| 314
| [[Kullanıcı:Stml 147|Stml 147]]
| align="center" | 70
|
|-
| 315
| [[Kullanıcı:SEMLNazımKURŞUN|SEMLNazımKURŞUN]]
| align="center" | 70
|
|-
| 316
| [[Kullanıcı:Giresunlu1993|Giresunlu1993]]
| align="center" | 70
|
|-
| 317
| [[Kullanıcı:Plenumchamber~trwiktionary|Plenumchamber~trwiktionary]]
| align="center" | 69
|
|-
| 318
| [[Kullanıcı:~2026-19042-98|~2026-19042-98]]
| align="center" | 69
|
|-
| 319
| [[Kullanıcı:Rock on She|Rock on She]]
| align="center" | 67
|
|-
| 320
| [[Kullanıcı:SLSerkan|SLSerkan]]
| align="center" | 65
|
|-
| 321
| [[Kullanıcı:Karduelis|Karduelis]]
| align="center" | 65
|
|-
| 322
| [[Kullanıcı:Zontollektuel|Zontollektuel]]
| align="center" | 65
|
|-
| 323
| [[Kullanıcı:Evrenkoruyan|Evrenkoruyan]]
| align="center" | 64
|
|-
| 324
| [[Kullanıcı:Adanalınacak|Adanalınacak]]
| align="center" | 64
|
|-
| 325
| [[Kullanıcı:Hapşu|Hapşu]]
| align="center" | 63
|
|-
| 326
| [[Kullanıcı:Dixtosa|Dixtosa]]
| align="center" | 63
|
|-
| 327
| [[Kullanıcı:El.wikt.user|El.wikt.user]]
| align="center" | 62
|
|-
| 328
| [[Kullanıcı:SL özge üstün|SL özge üstün]]
| align="center" | 62
|
|-
| 329
| [[Kullanıcı:Sal hasanilhan|Sal hasanilhan]]
| align="center" | 61
|
|-
| 330
| [[Kullanıcı:Prenses|Prenses]]
| align="center" | 60
|
|-
| 331
| [[Kullanıcı:Tofeiku|Tofeiku]]
| align="center" | 60
|
|-
| 332
| [[Kullanıcı:Sihl Murat|Sihl Murat]]
| align="center" | 59
|
|-
| 333
| [[Kullanıcı:Renamed user 1e23409a06e0b7922c2dfc98dde51974|Renamed user 1e23409a06e0b7922c2dfc98dde51974]]
| align="center" | 59
|
|-
| 334
| [[Kullanıcı:Arnavutsezgin|Arnavutsezgin]]
| align="center" | 58
|
|-
| 335
| [[Kullanıcı:Erkan Yilmaz|Erkan Yilmaz]]
| align="center" | 58
|
|-
| 336
| [[Kullanıcı:Galibibülent|Galibibülent]]
| align="center" | 57
|
|-
| 337
| [[Kullanıcı:S.orsev.dilek soydan|S.orsev.dilek soydan]]
| align="center" | 57
|
|-
| 338
| [[Kullanıcı:Stml 183|Stml 183]]
| align="center" | 57
|
|-
| 339
| [[Kullanıcı:Buzulkuşu|Buzulkuşu]]
| align="center" | 57
|
|-
| 340
| [[Kullanıcı:Spanier|Spanier]]
| align="center" | 57
|
|-
| 341
| [[Kullanıcı:LejyonerZaza|LejyonerZaza]]
| align="center" | 57
|
|-
| 342
| [[Kullanıcı:SAL 329|SAL 329]]
| align="center" | 56
|
|-
| 343
| [[Kullanıcı:S htk 428|S htk 428]]
| align="center" | 56
|
|-
| 344
| [[Kullanıcı:Stml 161|Stml 161]]
| align="center" | 56
|
|-
| 345
| [[Kullanıcı:HASAN ÖZGÜREN EML|HASAN ÖZGÜREN EML]]
| align="center" | 56
|
|-
| 346
| [[Kullanıcı:SLesra|SLesra]]
| align="center" | 56
|
|-
| 347
| [[Kullanıcı:SLhalit540|SLhalit540]]
| align="center" | 56
|
|-
| 348
| [[Kullanıcı:Stultiwikia|Stultiwikia]]
| align="center" | 56
|
|-
| 349
| [[Kullanıcı:LisafBia|LisafBia]]
| align="center" | 56
|
|-
| 350
| [[Kullanıcı:Quinlan83|Quinlan83]]
| align="center" | 56
|
|-
| 351
| [[Kullanıcı:Şegirt|Şegirt]]
| align="center" | 56
|
|-
| 352
| [[Kullanıcı:TAKASUGI Shinji|TAKASUGI Shinji]]
| align="center" | 55
|
|-
| 353
| [[Kullanıcı:Sarvaturi~trwiktionary|Sarvaturi~trwiktionary]]
| align="center" | 55
|
|-
| 354
| [[Kullanıcı:Ks.Tahd|Ks.Tahd]]
| align="center" | 55
|
|-
| 355
| [[Kullanıcı:Darkhorn~trwiktionary|Darkhorn~trwiktionary]]
| align="center" | 54
|
|-
| 356
| [[Kullanıcı:Anlztrk|Anlztrk]]
| align="center" | 54
|
|-
| 357
| [[Kullanıcı:Samleml özgür aydın|Samleml özgür aydın]]
| align="center" | 53
|
|-
| 358
| [[Kullanıcı:Elvire|Elvire]]
| align="center" | 53
|
|-
| 359
| [[Kullanıcı:İmmortalance|İmmortalance]]
| align="center" | 53
|
|-
| 360
| [[Kullanıcı:Tehonk|Tehonk]]
| align="center" | 53
|
|-
| 361
| [[Kullanıcı:NotBot|NotBot]]
| align="center" | 52
|
|-
| 362
| [[Kullanıcı:SHTK.ARZU|SHTK.ARZU]]
| align="center" | 52
|
|-
| 363
| [[Kullanıcı:SLOĞUZHAN|SLOĞUZHAN]]
| align="center" | 52
|
|-
| 364
| [[Kullanıcı:WikimediaNotifier|WikimediaNotifier]]
| align="center" | 52
|
|-
| 365
| [[Kullanıcı:Gufosowa|Gufosowa]]
| align="center" | 52
|
|-
| 366
| [[Kullanıcı:たまほめ|たまほめ]]
| align="center" | 51
|
|-
| 367
| [[Kullanıcı:Tembelejderha|Tembelejderha]]
| align="center" | 50
|
|-
| 368
| [[Kullanıcı:Kml Nurcan|Kml Nurcan]]
| align="center" | 50
|
|-
| 369
| [[Kullanıcı:Elton|Elton]]
| align="center" | 50
|
|-
| 370
| [[Kullanıcı:Ozgurhatic|Ozgurhatic]]
| align="center" | 50
|
|-
| 371
| [[Kullanıcı:Tıbbiye|Tıbbiye]]
| align="center" | 50
|
|-
| 372
| [[Kullanıcı:Sepkenki|Sepkenki]]
| align="center" | 50
|
|-
| 373
| [[Kullanıcı:Świętokrzyskie3|Świętokrzyskie3]]
| align="center" | 50
|
|-
| 374
| [[Kullanıcı:Stml 188|Stml 188]]
| align="center" | 48
|
|-
| 375
| [[Kullanıcı:Maderibeyza|Maderibeyza]]
| align="center" | 48
|
|-
| 376
| [[Kullanıcı:Müftülükarif|Müftülükarif]]
| align="center" | 48
|
|-
| 377
| [[Kullanıcı:Spl908455|Spl908455]]
| align="center" | 48
|
|-
| 378
| [[Kullanıcı:Gökçe Yörük|Gökçe Yörük]]
| align="center" | 48
|
|-
| 379
| [[Kullanıcı:Greywolf28|Greywolf28]]
| align="center" | 48
|
|-
| 380
| [[Kullanıcı:Sal ruveyda|Sal ruveyda]]
| align="center" | 47
|
|-
| 381
| [[Kullanıcı:S htk 145|S htk 145]]
| align="center" | 47
|
|-
| 382
| [[Kullanıcı:Cmrncntn|Cmrncntn]]
| align="center" | 47
|
|-
| 383
| [[Kullanıcı:Anon0004|Anon0004]]
| align="center" | 47
|
|-
| 384
| [[Kullanıcı:Doruk Salancı~trwiktionary|Doruk Salancı~trwiktionary]]
| align="center" | 46
|
|-
| 385
| [[Kullanıcı:Seml abdullah ege|Seml abdullah ege]]
| align="center" | 46
|
|-
| 386
| [[Kullanıcı:SACAK ALİFATİH|SACAK ALİFATİH]]
| align="center" | 46
|
|-
| 387
| [[Kullanıcı:Adml polat çelik 156|Adml polat çelik 156]]
| align="center" | 46
|
|-
| 388
| [[Kullanıcı:Luckas Blade|Luckas Blade]]
| align="center" | 46
|
|-
| 389
| [[Kullanıcı:BurstPower|BurstPower]]
| align="center" | 46
|
|-
| 390
| [[Kullanıcı:Lord Leatherface~trwiktionary|Lord Leatherface~trwiktionary]]
| align="center" | 45
|
|-
| 391
| [[Kullanıcı:Mambet|Mambet]]
| align="center" | 45
|
|-
| 392
| [[Kullanıcı:Öz Türkçe|Öz Türkçe]]
| align="center" | 45
|
|-
| 393
| [[Kullanıcı:JAn Dudík|JAn Dudík]]
| align="center" | 45
|
|-
| 394
| [[Kullanıcı:Billinghurst|Billinghurst]]
| align="center" | 45
|
|-
| 395
| [[Kullanıcı:Praxidicae|Praxidicae]]
| align="center" | 45
|
|-
| 396
| [[Kullanıcı:MathXplore|MathXplore]]
| align="center" | 45
|
|-
| 397
| [[Kullanıcı:Etimoloji|Etimoloji]]
| align="center" | 45
|
|-
| 398
| [[Kullanıcı:Zbutie3.14|Zbutie3.14]]
| align="center" | 45
|
|-
| 399
| [[Kullanıcı:Brightt11|Brightt11]]
| align="center" | 45
|
|-
| 400
| [[Kullanıcı:Sunshine23|Sunshine23]]
| align="center" | 44
|
|-
| 401
| [[Kullanıcı:BD2412|BD2412]]
| align="center" | 44
|
|-
| 402
| [[Kullanıcı:Wisar12|Wisar12]]
| align="center" | 44
|
|-
| 403
| [[Kullanıcı:Turkittihadcemiyeti|Turkittihadcemiyeti]]
| align="center" | 44
|
|-
| 404
| [[Kullanıcı:Hoo man|Hoo man]]
| align="center" | 43
|
|-
| 405
| [[Kullanıcı:Ghybu|Ghybu]]
| align="center" | 43
|
|-
| 406
| [[Kullanıcı:Zolgoyo|Zolgoyo]]
| align="center" | 43
|
|-
| 407
| [[Kullanıcı:YBK4|YBK4]]
| align="center" | 43
|
|-
| 408
| [[Kullanıcı:Aktas5561|Aktas5561]]
| align="center" | 42
|
|-
| 409
| [[Kullanıcı:Wiki13|Wiki13]]
| align="center" | 42
|
|-
| 410
| [[Kullanıcı:Alexander Mikhalenko|Alexander Mikhalenko]]
| align="center" | 42
|
|-
| 411
| [[Kullanıcı:Orsev.i.o.ayşe kibaroğlu|Orsev.i.o.ayşe kibaroğlu]]
| align="center" | 41
|
|-
| 412
| [[Kullanıcı:Stml 168|Stml 168]]
| align="center" | 41
|
|-
| 413
| [[Kullanıcı:Sihl selim|Sihl selim]]
| align="center" | 41
|
|-
| 414
| [[Kullanıcı:V. Doğan Günay~trwiktionary|V. Doğan Günay~trwiktionary]]
| align="center" | 41
|
|-
| 415
| [[Kullanıcı:Filanca|Filanca]]
| align="center" | 41
|
|-
| 416
| [[Kullanıcı:Nurettincerek|Nurettincerek]]
| align="center" | 41
|
|-
| 417
| [[Kullanıcı:Umitduranist|Umitduranist]]
| align="center" | 41
|
|-
| 418
| [[Kullanıcı:Wentayan|Wentayan]]
| align="center" | 41
|
|-
| 419
| [[Kullanıcı:Abant12|Abant12]]
| align="center" | 41
|
|-
| 420
| [[Kullanıcı:Ahmetcatalkaya|Ahmetcatalkaya]]
| align="center" | 40
|
|-
| 421
| [[Kullanıcı:Ahulusi|Ahulusi]]
| align="center" | 40
|
|-
| 422
| [[Kullanıcı:Savh|Savh]]
| align="center" | 40
|
|-
| 423
| [[Kullanıcı:FocalPoint|FocalPoint]]
| align="center" | 40
|
|-
| 424
| [[Kullanıcı:Bulgu|Bulgu]]
| align="center" | 40
|
|-
| 425
| [[Kullanıcı:Dijan|Dijan]]
| align="center" | 39
|
|-
| 426
| [[Kullanıcı:Saçak fatmamandirali|Saçak fatmamandirali]]
| align="center" | 39
|
|-
| 427
| [[Kullanıcı:Yabancı|Yabancı]]
| align="center" | 39
|
|-
| 428
| [[Kullanıcı:Cekli829|Cekli829]]
| align="center" | 39
|
|-
| 429
| [[Kullanıcı:Vanished user Xorisdtbdfgonugyfs|Vanished user Xorisdtbdfgonugyfs]]
| align="center" | 39
|
|-
| 430
| [[Kullanıcı:Mathonius|Mathonius]]
| align="center" | 39
|
|-
| 431
| [[Kullanıcı:Vincent Vega|Vincent Vega]]
| align="center" | 39
|
|-
| 432
| [[Kullanıcı:Samuele2002|Samuele2002]]
| align="center" | 39
|
|-
| 433
| [[Kullanıcı:CanerDemirci281993|CanerDemirci281993]]
| align="center" | 39
|
|-
| 434
| [[Kullanıcı:Eusbarbosa|Eusbarbosa]]
| align="center" | 38
|
|-
| 435
| [[Kullanıcı:Açak osman|Açak osman]]
| align="center" | 38
|
|-
| 436
| [[Kullanıcı:Araklı|Araklı]]
| align="center" | 38
|
|-
| 437
| [[Kullanıcı:Tapio Toola|Tapio Toola]]
| align="center" | 38
|
|-
| 438
| [[Kullanıcı:Oylm mat|Oylm mat]]
| align="center" | 37
|
|-
| 439
| [[Kullanıcı:Yalhi|Yalhi]]
| align="center" | 37
|
|-
| 440
| [[Kullanıcı:Admlmuhammet alican|Admlmuhammet alican]]
| align="center" | 37
|
|-
| 441
| [[Kullanıcı:SLHakan|SLHakan]]
| align="center" | 37
|
|-
| 442
| [[Kullanıcı:JackPotte|JackPotte]]
| align="center" | 37
|
|-
| 443
| [[Kullanıcı:Onkaimeon|Onkaimeon]]
| align="center" | 37
|
|-
| 444
| [[Kullanıcı:Vanished user 127237|Vanished user 127237]]
| align="center" | 37
|
|-
| 445
| [[Kullanıcı:Aabdullayev851|Aabdullayev851]]
| align="center" | 37
|
|-
| 446
| [[Kullanıcı:Wooze|Wooze]]
| align="center" | 37
|
|-
| 447
| [[Kullanıcı:Intolerable situation|Intolerable situation]]
| align="center" | 37
|
|-
| 448
| [[Kullanıcı:Ykio emelaydın|Ykio emelaydın]]
| align="center" | 36
|
|-
| 449
| [[Kullanıcı:S htk 612|S htk 612]]
| align="center" | 36
|
|-
| 450
| [[Kullanıcı:Flyax|Flyax]]
| align="center" | 36
|
|-
| 451
| [[Kullanıcı:Manco Capac|Manco Capac]]
| align="center" | 36
|
|-
| 452
| [[Kullanıcı:Joseph|Joseph]]
| align="center" | 36
|
|-
| 453
| [[Kullanıcı:Zuzumaykut|Zuzumaykut]]
| align="center" | 36
|
|-
| 454
| [[Kullanıcı:Goktr001|Goktr001]]
| align="center" | 36
|
|-
| 455
| [[Kullanıcı:Rxy|Rxy]]
| align="center" | 36
|
|-
| 456
| [[Kullanıcı:MPF|MPF]]
| align="center" | 36
|
|-
| 457
| [[Kullanıcı:Alperen|Alperen]]
| align="center" | 35
|
|-
| 458
| [[Kullanıcı:S htk 186|S htk 186]]
| align="center" | 35
|
|-
| 459
| [[Kullanıcı:Yonca573|Yonca573]]
| align="center" | 35
|
|-
| 460
| [[Kullanıcı:Pinar|Pinar]]
| align="center" | 34
|
|-
| 461
| [[Kullanıcı:Mardetanha|Mardetanha]]
| align="center" | 34
|
|-
| 462
| [[Kullanıcı:Nanahuatl|Nanahuatl]]
| align="center" | 34
|
|-
| 463
| [[Kullanıcı:Yoldasso|Yoldasso]]
| align="center" | 34
|
|-
| 464
| [[Kullanıcı:Java2002|Java2002]]
| align="center" | 34
|
|-
| 465
| [[Kullanıcı:Hasley|Hasley]]
| align="center" | 34
|
|-
| 466
| [[Kullanıcı:Recep Arslanbaş|Recep Arslanbaş]]
| align="center" | 34
|
|-
| 467
| [[Kullanıcı:TugbekOlek|TugbekOlek]]
| align="center" | 33
|
|-
| 468
| [[Kullanıcı:Vese~trwiktionary|Vese~trwiktionary]]
| align="center" | 33
|
|-
| 469
| [[Kullanıcı:Ozyurekli|Ozyurekli]]
| align="center" | 33
|
|-
| 470
| [[Kullanıcı:EsenBoga|EsenBoga]]
| align="center" | 33
|
|-
| 471
| [[Kullanıcı:Golgelerim|Golgelerim]]
| align="center" | 33
|
|-
| 472
| [[Kullanıcı:Sanya3|Sanya3]]
| align="center" | 33
|
|-
| 473
| [[Kullanıcı:Kırmızı renk|Kırmızı renk]]
| align="center" | 33
|
|-
| 474
| [[Kullanıcı:Stml 153|Stml 153]]
| align="center" | 32
|
|-
| 475
| [[Kullanıcı:SLsoner|SLsoner]]
| align="center" | 32
|
|-
| 476
| [[Kullanıcı:KoreanQuoter|KoreanQuoter]]
| align="center" | 32
|
|-
| 477
| [[Kullanıcı:Sungurer|Sungurer]]
| align="center" | 32
|
|-
| 478
| [[Kullanıcı:HestNewDes|HestNewDes]]
| align="center" | 32
|
|-
| 479
| [[Kullanıcı:Sml-hanife1|Sml-hanife1]]
| align="center" | 31
|
|-
| 480
| [[Kullanıcı:SAL 417|SAL 417]]
| align="center" | 31
|
|-
| 481
| [[Kullanıcı:MercanX|MercanX]]
| align="center" | 31
|
|-
| 482
| [[Kullanıcı:Kokoloc|Kokoloc]]
| align="center" | 31
|
|-
| 483
| [[Kullanıcı:Köksarı|Köksarı]]
| align="center" | 30
|
|-
| 484
| [[Kullanıcı:Akkiz|Akkiz]]
| align="center" | 30
|
|-
| 485
| [[Kullanıcı:Mclovinx|Mclovinx]]
| align="center" | 30
|
|-
| 486
| [[Kullanıcı:Talha1481|Talha1481]]
| align="center" | 30
|
|-
| 487
| [[Kullanıcı:Kumanof|Kumanof]]
| align="center" | 30
|
|-
| 488
| [[Kullanıcı:Tenperver|Tenperver]]
| align="center" | 30
|
|-
| 489
| [[Kullanıcı:~2026-22795-35|~2026-22795-35]]
| align="center" | 30
|
|-
| 490
| [[Kullanıcı:Sı 643|Sı 643]]
| align="center" | 29
|
|-
| 491
| [[Kullanıcı:SAMLEML MURAT ÇEBİ|SAMLEML MURAT ÇEBİ]]
| align="center" | 29
|
|-
| 492
| [[Kullanıcı:Kmlblg318|Kmlblg318]]
| align="center" | 29
|
|-
| 493
| [[Kullanıcı:Merube 89|Merube 89]]
| align="center" | 29
|
|-
| 494
| [[Kullanıcı:Hgav|Hgav]]
| align="center" | 29
|
|-
| 495
| [[Kullanıcı:Alsace38|Alsace38]]
| align="center" | 29
|
|-
| 496
| [[Kullanıcı:Dilşo Kardî|Dilşo Kardî]]
| align="center" | 29
|
|-
| 497
| [[Kullanıcı:Ulukan|Ulukan]]
| align="center" | 29
|
|-
| 498
| [[Kullanıcı:Kaan2121|Kaan2121]]
| align="center" | 29
|
|-
| 499
| [[Kullanıcı:Selahattin ilhan|Selahattin ilhan]]
| align="center" | 29
|
|-
| 500
| [[Kullanıcı:Zartatue|Zartatue]]
| align="center" | 29
|
|}
</center>
9ib8o13dol0ghgpsgauo7l4xr60ltqs
koronavirüs
0
467479
5672579
3685015
2026-06-29T20:54:15Z
Satirdan kahraman
37401
TurkceMaddePanel
5672579
wikitext
text/x-wiki
==Türkçe==
===Köken===
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||ko|ro|na|vi|rüs}}
===Ad===
{{tr-ad}}
[[File:Coronaviruses 004 lores.jpg|küçükresim|'''Koronavirüs.''']]
#{{t|dil=tr|viroloji}} Yüksek ateş ve nefes darlığı ile tanımlanan, viral solunum yolu hastalığına sebep olan bir tür virüs.
====Çekimleme====
{{tr-ad-tablo}}
===Kaynakça===
* {{KYK:TDK}}
* {{KYK:Nişanyan}}
===Ek okumalar===
*{{proje bağlantısı|Vikipedi}}
bskvlie50jtddgnbgku3ak4gqgcgejy
απροσδόκητος
0
572248
5672762
4209024
2026-06-30T09:36:30Z
MustafaCavlak
59368
/* Yunanca */
5672762
wikitext
text/x-wiki
{{bak|ἀπροσδόκητος}}
==Yunanca==
===Ön ad===
{{el-ön ad|d=απροσδόκητη|n=απροσδόκητο}}
# [[beklenmedik]], [[umulmadık]]
#: {{eş anlamlılar|el|αιφνίδιος|αναπάντεχος|ανέλπιστος|απρόβλεπτος|απρόοπτος|απρόσμενος}}
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=απροσδόκητ}}
====Karşıt anlamlılar====
* {{b|el|αναμενόμενος}}
* {{b|el|προσδοκώμενος}}
====İlgili sözcükler====
* {{b|el|απροσδόκητα}}
faie07uy2ejxs5c9i0fsr5u1z9i8waf
αδαμαντοπωλείο
0
605173
5672645
4553033
2026-06-29T22:29:53Z
MustafaCavlak
59368
/* Ad */
5672645
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|n|αδαμαντοπωλεία}}
# [[kuyumcu]] [[dükkân]]ı
====Çekimleme====
{{el-aN-ο-α-2a|αδαμαντοπωλεί}}
becug8f78yn1i25bturgx4iw4vm0mrq
cyanurer
0
882814
5672737
4853247
2026-06-30T08:52:39Z
MustafaCavlak
59368
/* Eylem */
5672737
wikitext
text/x-wiki
==Fransızca==
===Eylem===
{{fr-eylem}}
# [[siyanürlemek]]
====Çekimleme====
{{fr-er-oto}}
easllueu3lgsj5j7e696el5ktix1kpc
başlangıç çizgisi
0
898599
5672719
5241381
2026-06-30T06:26:58Z
Satirdan kahraman
37401
TurkceMaddePanel
5672719
wikitext
text/x-wiki
==Türkçe==
===Köken===
*{{birleşik|dil=tr|başlangıç|çizgi }}
===Söyleniş===
*{{tr-IPA}}
* {{h|dil=tr||baş|lan|gıç|çiz|gi|si}}
===Ad===
{{tr-ad}}
[[File:Starting line (Unsplash).jpg|küçükresim|Başlangıç çizgisi ]]
# {{t|dil=tr|spor}} [[çıkış çizgisi]].
====Çekimleme====
{{tr-ad-tablo}}
===Kaynakça===
* {{KYK:TDK}}
1r3k35s26ucmn6poc8l7b93cc0gc4p1
sıtma sivrisineği
0
923192
5672558
4910613
2026-06-29T20:33:25Z
Satirdan kahraman
37401
TurkceMaddePanel
5672558
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{birleşik|dil=tr|sıtma|sivrisinek}}
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||sıt|ma|siv|ri|si|ne|ği}}
===Ad===
{{tr-ad}}
[[Dosya:AnophelesGambiaemosquito.jpg|küçükresim|Sıtma sivrisineği]]
#{{t|dil=tr|böcekler}} Çift kanatlılardan, ince, uzun vücutlu ve dar kanatlı, dişisi sıtma asalağını insandan insana taşıyan bir eklem bacaklı türü; [[anofel]] {{belirtici|Anopheles maculipennis}}.
#* "Sıtma sivrisineği genellikle güneş battıktan sonra soktuğundan sıtmalı yerlerde güneş doğmadan önce ve battıktan sonra dışarıda bulunmayınız." - Mehmet Temel
====Çekimleme====
{{tr-ad-tablo}}
===Kaynakça===
*{{kaynak-TDK}}
aewtrmuoa6yupdtsul5wki5z4yno2p1
ανέλπιστος
0
1301311
5672763
5353923
2026-06-30T09:37:12Z
MustafaCavlak
59368
/* Ön ad */
5672763
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[umulmadık]]
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=ανέλπιστ}}
b94zy6gxe1thoh4pa1r0cefydpy6qvo
ανεπίβλεπτος
0
1301373
5672749
5353985
2026-06-30T09:24:46Z
MustafaCavlak
59368
/* Ön ad */
5672749
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[denetimsiz]]
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=ανεπίβλεπτ}}
20xfya9pgqgre5yvbh088rl00clkmvq
απρόοπτος
0
1302058
5672761
5354670
2026-06-30T09:34:54Z
MustafaCavlak
59368
/* Ön ad */
5672761
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# öngörülmemiş olan, öngörülemeyen
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=απρόοπτ}}
7h4h1yzrwf89wvgxnszurlfupgavj5v
δεκάλεπτος
0
1303243
5672752
5355856
2026-06-30T09:26:35Z
MustafaCavlak
59368
5672752
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[on]] [[dakikalık]]
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=δεκάλεπτ}}
p3q1l2lf0jvb1duanhk1iulaxcjrtcn
δεκαπεντάλεπτος
0
1303250
5672750
5355863
2026-06-30T09:25:45Z
MustafaCavlak
59368
/* Ön ad */
5672750
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[on beş]] [[dakikalık]]
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=δεκαπεντάλεπτ}}
39ag4opaw7dcvc2i54kjbqmtsd1ep8o
δίλεπτος
0
1303379
5672755
5355992
2026-06-30T09:29:48Z
MustafaCavlak
59368
/* Ön ad */
5672755
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[iki]] [[dakikalık]]
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=δίλεπτ}}
1x9hd0dby35zir1clhuufmmhik1f1as
δίλεφτος
0
1303380
5672758
5355993
2026-06-30T09:31:48Z
MustafaCavlak
59368
/* Ön ad */
5672758
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# {{farklı|dil=el|δίλεπτος}}
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=δίλεφτ}}
9dvj9hodrpyldlvifd3iomlaus4sj7h
δίστιχος
0
1303429
5672743
5356043
2026-06-30T09:16:00Z
MustafaCavlak
59368
5672743
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[iki]] [[dizeli]], iki [[satırlı]]
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=δίστιχ}}
99xuggwy6h6seku0yq4bfmen6ivt7ob
εικοσάλεπτος
0
1303616
5672751
5356230
2026-06-30T09:26:12Z
MustafaCavlak
59368
5672751
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[yirmi]] [[dakikalık]]
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=εικοσάλεπτ}}
4koeaivu7ovw80f47ysnnwh2pjobkna
έμμονος
0
1303701
5672684
5356315
2026-06-30T01:22:53Z
MustafaCavlak
59368
/* Ön ad */
5672684
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[takıntılı]], [[saplantılı]]
# [[ısrarcı]]
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=έμμον}}
ps3z2z2ic9a7al7rd3tb32hi590t53a
εξάστιχος
0
1303822
5672739
5356436
2026-06-30T09:14:11Z
MustafaCavlak
59368
/* Ön ad */
5672739
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[altı]] [[dizeli]], altı [[satırlı]]
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=εξάστιχ}}
h4xtjeih62rus53qxdj2z3jlo6cn6ih
επτάστιχος
0
1303932
5672748
5356546
2026-06-30T09:18:29Z
MustafaCavlak
59368
/* Ön ad */
5672748
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[yedi]] [[dizeli]], yedi [[satırlı]]
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=επτάστιχ}}
0a60qtn8595ye0kus23nhix3slalka9
ευρύτερος
0
1304099
5672682
5356713
2026-06-30T01:19:37Z
MustafaCavlak
59368
/* Ön ad */
5672682
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[daha]] [[geniş]]
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=ευρύτερ}}
4rq5zn700u2cudovuay6rzxzf22bdzz
λιγόλεπτος
0
1304850
5672756
5357464
2026-06-30T09:30:31Z
MustafaCavlak
59368
/* Ön ad */
5672756
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# {{farklı|dil=el|ολιγόλεπτος}}
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=λιγόλεπτ}}
4ymxe9qujvk06bb1d6enxv1678h4bjw
μονόλεφτος
0
1305142
5672759
5357756
2026-06-30T09:32:27Z
MustafaCavlak
59368
/* Ön ad */
5672759
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# {{farklı|dil=el|μονόλεπτος}}
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=μονόλεφτ}}
rm4gwlt96l64jf21dmjpm6i16vyv4ov
μονόστιχος
0
1305166
5672742
5357780
2026-06-30T09:15:27Z
MustafaCavlak
59368
/* Ön ad */
5672742
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[tek]] [[dizeli]], bir [[satırlı]]
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=μονόστιχ}}
k3k4jsc8bhyyxmyx5lzt6znjotxsypt
οκτάστιχος
0
1305471
5672745
5358085
2026-06-30T09:17:06Z
MustafaCavlak
59368
5672745
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[sekiz]] [[dizeli]], sekiz [[satırlı]]
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=οκτάστιχ}}
7ru9axss0xbypcitncpdzunpavbdrey
ολιγόλεπτος
0
1305498
5672753
5358112
2026-06-30T09:27:03Z
MustafaCavlak
59368
/* Ön ad */
5672753
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[birkaç]] [[dakikalık]]
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=ολιγόλεπτ}}
t1t7dn9c51d3y5bobkxl6qq5czt3fm2
ολιγόστιχος
0
1305505
5672744
5358119
2026-06-30T09:16:47Z
MustafaCavlak
59368
/* Ön ad */
5672744
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[az]] sayıda [[dize]]den oluşan, az [[satırlı]]
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=ολιγόστιχ}}
09w5ec7dnfut4mqspip2l1hlx7paikg
οχτάστιχος
0
1305679
5672740
5358293
2026-06-30T09:14:44Z
MustafaCavlak
59368
/* Ön ad */
5672740
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# {{farklı|dil=el|οκτάστιχος}}
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=οχτάστιχ}}
7if44rzypztd22uiad6nxcctc9z8bb1
πεντάλεπτος
0
1305863
5672757
5358477
2026-06-30T09:30:55Z
MustafaCavlak
59368
/* Ön ad */
5672757
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[beş]] [[dakikalık]]
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=πεντάλεπτ}}
dwg7slwy2tr2p2aq933rbl7oa4epmhb
πεντάστιχος
0
1305877
5672746
5358491
2026-06-30T09:17:40Z
MustafaCavlak
59368
/* Ön ad */
5672746
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[beş]] [[dizeli]], beş [[satırlı]]
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=πεντάστιχ}}
n0kw4gckv8kv576b73q78m56sdd436x
περίβλεφτος
0
1305899
5672760
5358513
2026-06-30T09:32:58Z
MustafaCavlak
59368
/* Ön ad */
5672760
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# {{farklı|dil=el|περίβλεπτος}}
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=περίβλεφτ}}
rv4zs1kfe0him904moza2tzkmckiyyd
πολύστιχος
0
1306151
5672738
5358765
2026-06-30T09:13:20Z
MustafaCavlak
59368
/* Ön ad */
5672738
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[çok]] [[dizeli]], çok [[satırlı]]
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=πολύστιχ}}
3qqtr7dyug3yepda1afj9s6rl3j6oa7
τετράστιχος
0
1306812
5672741
5359427
2026-06-30T09:15:03Z
MustafaCavlak
59368
/* Ön ad */
5672741
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[dört]] [[dizeli]], dört [[satırlı]]
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=τετράστιχ}}
qv71axsu2b4pir6gdi4e93fku56d3aq
τρίστιχος
0
1306954
5672747
5359569
2026-06-30T09:18:02Z
MustafaCavlak
59368
/* Ön ad */
5672747
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[üç]] [[dizeli]], üç [[satırlı]]
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=τρίστιχ}}
kxmvg6gt06890yq11mzlcgy2jlk8qr2
τσιγγούνικος
0
1306988
5672729
5359603
2026-06-30T07:58:41Z
MustafaCavlak
59368
/* Ön ad */
5672729
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# {{farklı|dil=el|τσιγκούνικος}}
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=τσιγγούνικ}}
dzl35dfprfyud16zs31xemkjjl4ovnt
τσιγκούνικος
0
1306990
5672728
5359605
2026-06-30T07:57:41Z
MustafaCavlak
59368
/* Ön ad */
5672728
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[cimrilik]]le ilgili, [[cimri]], [[cimrice]]
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=τσιγκούνικ}}
hbvxiew83b0x54prk831vp0bdzuptj9
υπέρλεπτος
0
1307054
5672754
5359669
2026-06-30T09:28:49Z
MustafaCavlak
59368
/* Ön ad */
5672754
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[fazlasıyla]] [[ince]]
====Çekimleme====
{{el-çekim-öa|çekim=ος-η-ο|kök=υπέρλεπτ}}
f7c4ghndpbgy2si2fvoj1zd1swop2u8
fédéraliser
0
1455440
5672724
5510445
2026-06-30T07:49:21Z
MustafaCavlak
59368
/* Fransızca */
5672724
wikitext
text/x-wiki
==Fransızca==
===Köken===
{{ek|dil=fr|fédéral|iser}}
===Eylem===
{{fr-eylem}}
# [[federalleştirmek]]
====Çekimleme====
{{fr-er-oto}}
g9555lb7srynfk26c6lbf8bz0xvpn00
inaugurer
0
1455841
5672731
5510851
2026-06-30T08:06:53Z
MustafaCavlak
59368
/* Fransızca */
5672731
wikitext
text/x-wiki
==Fransızca==
===Köken===
Öğrenilmiş bir şekilde {{nakledilen|fr|la|inaugurō|inaugurāre}}.
===Eylem===
{{fr-eylem}}
# [[tören]]le [[açmak]], [[açılış]] töreniyle [[başlatmak]]
====Çekimleme====
{{fr-er-oto}}
5sye8eltr5z4ri6v5ig5f9d20ech24u
refédéraliser
0
1457050
5672725
5512086
2026-06-30T07:50:59Z
MustafaCavlak
59368
/* Fransızca */
5672725
wikitext
text/x-wiki
==Fransızca==
===Köken===
{{ön ek|dil=fr|re|fédéraliser}}
===Eylem===
{{fr-eylem}}
# [[yeniden]] [[federalleştirmek]]
====Çekimleme====
{{fr-er-oto}}
kd7szy4k2960x4cbvqhfp6pya6cs28j
ribouler
0
1457340
5672730
5512397
2026-06-30T08:04:42Z
MustafaCavlak
59368
/* Fransızca */
5672730
wikitext
text/x-wiki
==Fransızca==
===Köken===
{{z|fr|rebouler}} sözcüğünden.
===Eylem===
{{fr-eylem}}
# {{t|dil=fr|teklifsiz konuşma}} [[gözlerini devirmek]]
====Çekimleme====
{{fr-er-oto}}
pighsj5ri5oeedxs7106ine5elmaone
schuldenfrei
0
1512851
5672732
5568759
2026-06-30T08:08:00Z
MustafaCavlak
59368
/* Ön ad */
5672732
wikitext
text/x-wiki
==Almanca==
===Ön ad===
{{de-ön ad|-}}
# [[borçsuz]]
====Çekimleme====
{{de-kıyaslanamayan-tablo}}
lafb1nor84mhbgr7l73pnyfckc0dosi
Modül:ru-genel
828
1589236
5672511
5669922
2026-06-29T15:42:34Z
MustafaCavlak
59368
imported from en
5672511
Scribunto
text/plain
local export = {}
--[==[ intro:
Author: Benwing; some very early work by Rua and Atitarev
This module holds some commonly used functions for the Russian language. It's generally for use from other modules, not
`#invoke`, although some functions can be invoked from a template (`export.iotation()`, `export.reduce_stem()`,
`export.dereduce_stem()`, actually added to support calling from a bot script rather than from a user template; and
`export.make_unstressed()`, called from {{tl|R:ru:Vasmer}}). There may be issues when invoking such functions from
templates when transliteration is present, due to the need for the transliteration to be decomposed, as mentioned below
(all strings from Wiktionary pages are normally in composed form).
NOTE NOTE NOTE: All functions assume that transliteration (but not Russian) has had its acute and grave accents
decomposed using `export.decompose()`. This is the first thing that should be done to all user-specified
transliteration and any transliteration we compute that we expect to work with.
]==]
local m_str_utils = require("Modül:string araçları")
local m_table_tools = require("Modül:table tools")
-- Prevents an infinite require loop since ru-translit requires a different function in this module.
local m_ru_translit = require("Modül:require when needed")("Modül:ru-alfabe çeviri")
local m_headword_utilities = require("Modül:require when needed")("Modül:başlık başı araçları")
local m_table = require("Modül:require when needed")("Modül:table")
local gsplit = m_str_utils.gsplit
local split = m_str_utils.split
local toNFD = mw.ustring.toNFD
local u = m_str_utils.char
local ufind = mw.ustring.find
local ugsub = mw.ustring.gsub
local ulen = m_str_utils.len
local ulower = m_str_utils.lower
local umatch = mw.ustring.match
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local usub = m_str_utils.sub
local insert = table.insert
local concat = table.concat
local AC = u(0x0301) -- acute = ́
local GR = u(0x0300) -- grave = ̀
local CFLEX = u(0x0302) -- circumflex = ̂
local BREVE = u(0x0306) -- breve ̆
local DIA = u(0x0308) -- diaeresis = ̈
local CARON = u(0x030C) -- caron ̌
local OGONEK = u(0x0328) -- ogonek ̨
local PSEUDOVOWEL = u(0xFFF1) -- pseudovowel placeholder
local PSEUDOCONS = u(0xFFF2) -- pseudoconsonant placeholder
-- any stress
export.stress = AC .. GR
-- regex for any optional stress(s)
export.opt_stress = "[" .. export.stress .. "]*"
-- any accent
export.accent = export.stress .. DIA .. BREVE .. CARON .. OGONEK
-- regex for any optional accent(s)
export.opt_accent = "[" .. export.accent .. "]*"
-- any composed Cyrillic vowel with grave accent
export.composed_grave_vowel = "ѐЀѝЍ"
-- any Cyrillic vowel except ёЁ
export.vowel_no_jo = "аАеЕиИӥӤіІїЇоОуУыЫѣѢэЭюЮяЯѵѴ" .. PSEUDOVOWEL .. export.composed_grave_vowel
-- any Cyrillic vowel, including ёЁ
export.vowel = export.vowel_no_jo .. "ёЁ"
-- any vowel in transliteration
export.tr_vowel = "aAeEěĚɛƐiIoOǒǑǫǪuUyY" .. PSEUDOVOWEL
-- any consonant in transliteration, omitting "j" and the soft/hard sign
export.tr_cons_no_approx = "bBcCčČdDfFgGkKlLmMnNpPrRsSšŠtTvVxXzZžŽ" .. PSEUDOCONS
-- any consonant in transliteration, including soft/hard sign
export.tr_cons = export.tr_cons_no_approx .. "jJʹʺ"
-- regex for any consonant in transliteration, including soft/hard sign,
-- optionally followed by any accent
export.tr_cons_acc_re = "[" .. export.tr_cons .. "]" .. export.opt_accent
-- any Cyrillic consonant except sibilants and ц
export.cons_except_sib_c = "бБвВгГдДзЗйЙкКлЛмМнНпПрРсСтТфФхХъЪьЬѳѲ" .. PSEUDOCONS
-- Cyrillic sibilant consonants
export.sib = "жЖчЧшШщЩ"
-- Cyrillic sibilant consonants and ц
export.sib_c = export.sib .. "цЦ"
-- any Cyrillic consonant
export.cons = export.cons_except_sib_c .. export.sib_c
-- Cyrillic velar consonants
export.velar = "гГкКхХ"
-- uppercase Cyrillic
export.uppercase = "АБВГДЕЀЁЖЗИЍӤІЇЙКЛМНОПРСТУФХЦЧШЩЪЫЬѢЭЮЯѲѴ"
local function ine(x)
return x ~= "" and x or nil
end
--[==[
Apply Proto-Slavic iotation. This is the change that is affected by a Slavic -j- after a consonant.
`stem` is the Cyrillic stem and `tr` its optional manual translit. If `shch` is given, т iotates to щ instead of ч.
Normally return two values, the iotated Cyrillic stem and corresponding transliteration (which will be {nil} if passed
in as {nil}). If invoked from a template or bot, however, the return value will be a single string; if manual
transliteration is present, the return value will be a string of the form `CYRILLIC//TRANSLIT` with two slahes
separating the Cyrillic from the translit.
]==]
function export.iotation(stem, tr, shch)
local combine_tr = false
-- so this can be called from a template (or usually, a bot)
if type(stem) == "table" then
stem, tr, shch = ine(stem.args[1]), ine(stem.args[2]), ine(stem.args[3])
combine_tr = true
end
stem = ugsub(stem, "[сх]$", "ш")
stem = ugsub(stem, "с[кт]$", "щ")
stem = ugsub(stem, "[кц]$", "ч")
-- normally "т" is iotated as "ч" but there are many verbs that are iotated with "щ"
if shch == "щ" then
stem = stem:gsub("т$", "щ")
else
stem = stem:gsub("т$", "ч")
end
stem = ugsub(stem, "[гдз]$", "ж")
stem = ugsub(stem, "[бвмпфѳ]$", "%0л")
-- ѵ is equivalent to в after certain vowels
stem = ugsub(stem, "[аАеЕѐЀиИѝЍӥӤіІїЇѣѢэЭяЯ]" .. export.opt_stress .. "ѵ$", "%0л")
if tr then
tr = tr:gsub("[sx]$", "š")
:gsub("s[kt]$", "šč")
:gsub("[kc]$", "č")
-- normally "т" is iotated as "ч" but there are many verbs that are iotated with "щ"
if shch == "щ" then
tr = tr:gsub("t$", "šč")
else
tr = tr:gsub("t$", "č")
end
tr = tr:gsub("[dgz]$", "ž")
:gsub("[bfmpv]$", "%0l")
end
if combine_tr then
return export.combine_russian_tr(stem, tr)
end
return stem, tr
end
do
-- A word needs accents if it is unstressed and contains more than one
-- vowel, unless it's a prefix or suffix
local function word_needs_accents(word)
return not (word:sub(1, 1) == "-" or word:sub(-1) == "-") and
export.is_unstressed(word) and not export.is_monosyllabic(word)
end
-- Does a set of Cyrillic words in connected text need accents? We need to
-- split by word and check each one.
function export.needs_accents(text)
for word in gsplit(text, "%s+") do
if word_needs_accents(word) then
return true
end
end
return false
end
end
--[==[
True if either:
# A vowel is marked with explicit primary stress.
# The word has a single jo in it (which doesn't have secondary stress).
This is because a word with multiple jos requires explicit stress to be marked, since we can't infer where primary
stress lies. `Jo` can be `ё`, `ѣ̈`, or `я̈` (e.g. `сѣ̈дла`, plural of `сѣдло́`).
]==]
function export.is_stressed(word)
if word:find(AC) then
return true
end
word = toNFD(word)
return (
select(2, ugsub(word, "[еѣяЕѢЯ]" .. DIA, "")) == 1 and
not umatch(word, "[еѣяЕѢЯ]" .. DIA .. GR)
)
end
--[==[
True if a Cyrillic word requires explicit stress.
]==]
function export.is_unstressed(word)
return not export.is_stressed(word)
end
--[==[
True if Cyrillic word is stressed on the last syllable.
]==]
function export.is_ending_stressed(word)
return ufind(word, "[ёЁ][^" .. export.vowel .. "]*$") or
ufind(word, "[" .. export.vowel .. "][́̈][^" .. export.vowel .. "]*$")
end
do
local function word_is_multi_stressed(word)
-- Allow ё along with another stress, e.g. [[трёхэта́жный]], [[гёрлфре́нд]] or [[Са́мсё]].
return ufind(word, "[" .. export.vowel .. "][́̈].*[" .. export.vowel .. "][́̈]")
end
--[==[
True if a Cyrillic term has two or more stresses (acute or diaeresis) in a given word.
]==]
function export.is_multi_stressed(text)
for word in gsplit(text, "[%s-]+") do
if word_is_multi_stressed(word) then
return true
end
end
return false
end
end
--[==[
True if Cyrillic word is stressed on the first syllable.
]==]
function export.is_beginning_stressed(word)
return ufind(word, "^[^" .. export.vowel .. "]*[ёЁ]") or
ufind(word, "^[^" .. export.vowel .. "]*[" .. export.vowel .. "]́")
end
--[==[
True if Cyrillic word has no vowel. Don't treat suffixes as nonsyllabic even if they have no vowel, as they are
generally added onto words with vowels.
]==]
function export.is_nonsyllabic(word)
return not ufind(word, "^%-") and not ufind(word, "[" .. export.vowel .. "]")
end
--[==[
True if Cyrillic word has no more than one vowel; includes non-syllabic stems such as `льд-`.
]==]
function export.is_monosyllabic(word)
return not ufind(word, "[" .. export.vowel .. "].*[" .. export.vowel .. "]")
end
local recomposer = {
-- Cyrillic letters
["е" .. DIA] = "ё",
["Е" .. DIA] = "Ё",
["и" .. DIA] = "ӥ",
["И" .. DIA] = "Ӥ",
["и" .. BREVE] = "й",
["И" .. BREVE] = "Й",
["і" .. DIA] = "ї",
["І" .. DIA] = "Ї",
-- Latin letters
["c" .. CARON] = "č",
["C" .. CARON] = "Č",
["e" .. CARON] = "ě",
["E" .. CARON] = "Ě",
["o" .. CARON] = "ǒ",
["O" .. CARON] = "Ǒ",
["o" .. OGONEK] = "ǫ",
["O" .. OGONEK] = "Ǫ",
["s" .. CARON] = "š",
["S" .. CARON] = "Š",
["z" .. CARON] = "ž",
["Z" .. CARON] = "Ž",
-- used in ru-pron:
["ж" .. BREVE] = "ӂ", -- used in ru-pron
["Ж" .. BREVE] = "Ӂ",
["j" .. CFLEX] = "ĵ",
["J" .. CFLEX] = "Ĵ",
["j" .. CARON] = "ǰ",
-- no composed uppercase equivalent of J-caron
["ʒ" .. CARON] = "ǯ",
["Ʒ" .. CARON] = "Ǯ",
}
--[==[
Decompose acute, grave, etc. on letters (esp. Latin) into individivual character + combining accent. But recompose
Cyrillic and Latin characters that we want to treat as units and get caught in the crossfire. We mostly want acute and
grave decomposed; perhaps should just explicitly decompose those and no others.
]==]
function export.decompose(text)
return (ugsub(toNFD(text), ".[" .. BREVE .. DIA .. CARON .. OGONEK .. "]", recomposer))
end
function export.assert_decomposed(text)
assert(not ufind(text, "[áéíóúýàèìòùỳäëïöüÿÁÉÍÓÚÝÀÈÌÒÙỲÄËÏÖÜŸ]"))
end
--[==[
Transliterate text and then apply acute/grave decomposition.
]==]
function export.translit(text, no_include_monosyllabic_jo_accent)
local jo_accent = not no_include_monosyllabic_jo_accent and "mono" or nil
return export.decompose(m_ru_translit.tr(text, nil, nil, jo_accent))
end
--[==[
Recompose acutes and graves into preceding vowels. Probably not necessary.
]==]
function export.recompose(text)
return mw.ustring.toNFC(text)
end
local grave_decomposer = {
["ѐ"] = "е" .. GR,
["Ѐ"] = "Е" .. GR,
["ѝ"] = "и" .. GR,
["Ѝ"] = "И" .. GR,
}
--[==[
Decompose precomposed Cyrillic chars w/grave accent; not necessary for acute accent as there aren't precomposed Cyrillic
chars w/acute accent, and undesirable for precomposed `ё` and `Ё`.
]==]
function export.decompose_grave(word)
return (ugsub(word, "[ѐЀѝЍ]", grave_decomposer))
end
local grave_deaccenter = {
[GR] = "", -- grave accent
["ѐ"] = "е", -- composed Cyrillic chars w/grave accent
["Ѐ"] = "Е",
["ѝ"] = "и",
["Ѝ"] = "И",
}
local deaccenter = mw.clone(grave_deaccenter)
deaccenter[AC] = "" -- acute accent
--[==[
Remove acute and grave accents; don't affect composed diaeresis in `ёЁ` or uncomposed diaeresis in `-ѣ̈-` (as in plural
`сѣ̈дла` of `сѣдло́`). NOTE: Translit must already be decomposed! See comment at top.
]==]
function export.remove_accents(word, tr)
local ru_removed = ugsub(word, "[́̀ѐЀѝЍ]", deaccenter)
if not tr then
return ru_removed, nil
end
return ru_removed, (ugsub(tr, "[" .. AC .. GR .. "]", deaccenter))
end
--[==[
Remove grave accents; don't affect acute or composed diaeresis in `ёЁ` or uncomposed diaeresis in `-ѣ̈-` (as in plural
`сѣ̈дла` of `сѣдло́`). NOTE: Translit must already be decomposed! See comment at top.
]==]
function export.remove_grave_accents(word, tr)
local ru_removed = ugsub(word, "[̀ѐЀѝЍ]", grave_deaccenter)
if not tr then
return ru_removed, nil
end
return ru_removed, (ugsub(tr, GR, ""))
end
--[==[
Remove acute and grave accents in monosyllabic words; don't affect diaeresis (composed or uncomposed) because it
indicates a change in vowel quality, which still applies to monosyllabic words. Don't change suffixes, where a
"monosyllabic" stress is still significant (e.g. `-ча́т` short masculine of `-ча́тый`, vs. `-́чат` short masculine of
`-́чатый`). NOTE: Translit must already be decomposed! See comment at top.
]==]
function export.remove_monosyllabic_accents(word, tr)
if export.is_monosyllabic(word) and not ufind(word, "^%-") then
return export.remove_accents(word, tr)
else
return word, tr
end
end
local destresser = mw.clone(deaccenter)
destresser["ё"] = "е"
destresser["Ё"] = "Е"
destresser[DIA] = "" -- diaeresis
-- Subfunction of split_syllables(). On input we get sections of text consisting of CONSONANT - VOWEL - CONSONANT -
-- VOWEL ... - CONSONANT, where CONSONANT consists of zero or more consonants and VOWEL consists of exactly one vowel
-- plus any following accent(s); we combine these into syllables as required by split_syllables().
local function combine_captures(captures)
if captures[1] and not captures[2] then
return captures
end
local combined = {}
for i = 1, (#captures - 1), 2 do
insert(combined, captures[i] .. captures[i+1])
end
combined[#combined] = combined[#combined] .. captures[#captures]
return combined
end
--[==[
Split Russian text and transliteration into syllables. Syllables end with vowel + accent(s), except for the last
syllable, which includes any trailing consonants. NOTE: Translit must already be decomposed! See comment at top.
]==]
function export.split_syllables(ru, tr)
-- Split into alternating consonant/vowel sequences, as described in
-- combine_captures().
local rusyllables = combine_captures(split(ru, "([" .. export.vowel .. "]" .. export.opt_accent .. ")"))
local trsyllables
if tr then
export.assert_decomposed(tr)
trsyllables = combine_captures(split(tr, "([" .. export.tr_vowel .. "]" .. export.opt_accent .. ")"))
if #rusyllables ~= #trsyllables then
error("Russian " .. ru .. " doesn't have same number of syllables as translit " .. tr)
end
end
--error(concat(rusyllables, "/") .. "(" .. #rusyllables .. (trsyllables and (") || " .. concat(trsyllables, "/") .. "(" .. #trsyllables .. ")") or ""))
return rusyllables, trsyllables
end
--[==[
Split Russian word and transliteration into hyphen-separated components. Rejoining with `concat(..., "-")` will
recover the original word. If the original word ends in a hyphen, that hyphen gets included with the preceding component(this is the only case when an individual component has a hyphen in it).
]==]
function export.split_hyphens(ru, tr)
local rucomponents = split(ru, "%-")
if rucomponents[#rucomponents] == "" and #rucomponents > 1 then
rucomponents[#rucomponents - 1] = rucomponents[#rucomponents - 1] .. "-"
table.remove(rucomponents)
end
local trcomponents
if tr then
trcomponents = split(tr, "%-")
if trcomponents[#trcomponents] == "" and #trcomponents > 1 then
trcomponents[#trcomponents - 1] = trcomponents[#trcomponents - 1] .. "-"
table.remove(trcomponents)
end
if #rucomponents ~= #trcomponents then
error("Russian " .. ru .. " doesn't have same number of hyphenated components as translit " .. tr)
end
end
return rucomponents, trcomponents
end
--[==[
Apply `j` correction, converting `je` to `e` after consonants, `jo` to `o` after a sibilant, `ju` to `u` after hard
sibilant. NOTE: Translit must already be decomposed! See comment at top.
]==]
function export.j_correction(tr)
tr = ugsub(tr, "([" .. export.tr_cons_no_approx .. "]" .. export.opt_accent ..")[Jj]([EeĚě])", "%1%2")
tr = ugsub(tr, "([žščŽŠČ])[Jj]([Oo])", "%1%2")
return (ugsub(tr, "([žšŽŠ])[Jj]([Uu])", "%1%2"))
end
local function make_unstressed_ru(ru)
-- The following regexp has grave+acute+diaeresis after the bracket
return (ugsub(ru, "[̀́̈ёЁѐЀѝЍ]", destresser))
end
--[==[
Remove all stress marks (acute, grave, diaeresis). NOTE: Translit must already be decomposed! See comment at top.
]==]
function export.make_unstressed(ru, tr)
-- so this can be called from a template (specifically {{R:ru:Vasmer}})
if type(ru) == "table" then
ru, tr = ine(ru.args[1]), ine(ru.args[2])
end
if not tr then
return make_unstressed_ru(ru), nil
end
-- In the presence of TR, we need to do things the hard way: Splitting
-- into syllables and only converting Latin o to e opposite a ё.
local rusyl, trsyl = export.split_syllables(ru, tr)
for i=1,#rusyl do
if ufind(rusyl[i], "[ёЁ]") then
trsyl[i] = ugsub(trsyl[i], "[Oo]", {["O"] = "E", ["o"] = "e"})
end
rusyl[i] = make_unstressed_ru(rusyl[i])
-- the following should still work as it will affect accents only
trsyl[i] = make_unstressed_ru(trsyl[i])
end
-- Also need to apply j correction as otherwise we'll have je after cons, etc.
return concat(rusyl, ""), export.j_correction(concat(trsyl, ""))
end
local function remove_jo_ru(word)
return (ugsub(word, "[̈ёЁ]", destresser))
end
local function make_unstressed_once_ru(word)
-- leave graves alone
return (ugsub(word, "([́̈ёЁ])([^́̈ёЁ]*)$", function(x, rest) return destresser[x] .. rest; end, 1))
end
--[==[
Remove diaeresis stress marks only. NOTE: Translit must already be decomposed! See comment at top.
]==]
function export.remove_jo(ru, tr)
if not tr then
return remove_jo_ru(ru), nil
end
-- In the presence of TR, we need to do things the hard way: Splitting
-- into syllables and only converting Latin o to e opposite a ё.
local rusyl, trsyl = export.split_syllables(ru, tr)
for i=1,#rusyl do
if ufind(rusyl[i], "[ёЁ]") then
trsyl[i] = ugsub(trsyl[i], "[Oo]", {["O"] = "E", ["o"] = "e"})
end
rusyl[i] = remove_jo_ru(rusyl[i])
-- the following should still work as it will affect accents only
trsyl[i] = make_unstressed_once_ru(trsyl[i])
end
-- Also need to apply j correction as otherwise we'll have je after cons, etc.
return concat(rusyl, ""),
export.j_correction(concat(trsyl, ""))
end
local function map_last_hyphenated_component(fn, ru, tr)
if ufind(ru, "%-") then
-- If there is a hyphen, do it the hard way by splitting into
-- individual components and doing the last one. Otherwise we just do
-- the whole string.
local rucomponents, trcomponents = export.split_hyphens(ru, tr)
local lastru, lasttr = fn(rucomponents[#rucomponents],
trcomponents and trcomponents[#trcomponents] or nil)
rucomponents[#rucomponents] = lastru
ru = concat(rucomponents, "-")
if trcomponents then
trcomponents[#trcomponents] = lasttr
tr = concat(trcomponents, "-")
end
return ru, tr
end
return fn(ru, tr)
end
-- Make last stressed syllable (acute or diaeresis) unstressed; leave unstressed; leave graves alone; if `NOCONCAT`,
-- return individual syllables. NOTE: Translit must already be decomposed! See comment at top.
local function make_unstressed_once_after_hyphen_split(ru, tr, noconcat)
if not tr then
return make_unstressed_once_ru(ru), nil
end
-- In the presence of TR, we need to do things the hard way, as with
-- make_unstressed().
local rusyl, trsyl = export.split_syllables(ru, tr)
for i=#rusyl,1,-1 do
local stressed = export.is_stressed(rusyl[i])
if stressed then
if ufind(rusyl[i], "[ёЁ]") then
trsyl[i] = ugsub(trsyl[i], "[Oo]", {["O"] = "E", ["o"] = "e"})
end
rusyl[i] = make_unstressed_once_ru(rusyl[i])
-- the following should still work as it will affect accents only
trsyl[i] = make_unstressed_once_ru(trsyl[i])
break
end
end
if noconcat then
return rusyl, trsyl
end
-- Also need to apply j correction as otherwise we'll have je after cons
return concat(rusyl, ""),
export.j_correction(concat(trsyl, ""))
end
--[==[
Make last stressed syllable (acute or diaeresis) to the right of any hyphen unstressed (unless the hyphen is
word-final); leave graves alone. We don't destress a syllable to the left of a hyphen unless the hyphen is word-final
(i.e. a prefix). Otherwise e.g. the accents in the first part of words like ко́е-како́й and а́льфа-лу́ч won't remain. NOTE:
Translit must already be decomposed! See comment at top.
]==]
function export.make_unstressed_once(ru, tr)
return map_last_hyphenated_component(make_unstressed_once_after_hyphen_split, ru, tr)
end
local function make_unstressed_once_at_beginning_ru(word)
-- leave graves alone
return (ugsub(word, "^([^́̈ёЁ]*)([́̈ёЁ])", function(rest, x) return rest .. destresser[x]; end, 1))
end
--[==[
Make first stressed syllable (acute or diaeresis) unstressed; leave graves alone; if `NOCONCAT`, return individual
syllables. NOTE: Translit must already be decomposed! See comment at top.
]==]
function export.make_unstressed_once_at_beginning(ru, tr, noconcat)
if not tr then
return make_unstressed_once_at_beginning_ru(ru), nil
end
-- In the presence of TR, we need to do things the hard way, as with
-- make_unstressed().
local rusyl, trsyl = export.split_syllables(ru, tr)
for i=1,#rusyl do
local stressed = export.is_stressed(rusyl[i])
if stressed then
if ufind(rusyl[i], "[ёЁ]") then
trsyl[i] = ugsub(trsyl[i], "[Oo]", {["O"] = "E", ["o"] = "e"})
end
rusyl[i] = make_unstressed_once_at_beginning_ru(rusyl[i])
-- the following should still work as it will affect accents only
trsyl[i] = make_unstressed_once_at_beginning_ru(trsyl[i])
break
end
end
if noconcat then
return rusyl, trsyl
end
-- Also need to apply j correction as otherwise we'll have je after cons
return concat(rusyl, ""),
export.j_correction(concat(trsyl, ""))
end
--[==[
Subfunction of `make_ending_stressed()`, `make_beginning_stressed()`, which add an acute accent to a syllable that may
already have a grave accent; in such a case, remove the grave. NOTE: Translit must already be decomposed! See comment at
top.
]==]
function export.correct_grave_acute_clash(word, tr)
word = ugsub(word, "([̀ѐЀѝЍ])́", function(x) return grave_deaccenter[x] .. AC; end)
word = ugsub(word, AC .. GR, AC)
if not tr then
return word, nil
end
tr = ugsub(tr, GR .. AC, AC)
tr = ugsub(tr, AC .. GR, AC)
return word, tr
end
local function make_ending_stressed_ru(word)
-- If already ending stressed, just return word so we don't mess up ё
if export.is_ending_stressed(word) then
return word
end
-- Destress the last stressed syllable
word = make_unstressed_once_ru(word)
-- Add an acute to the last syllable
word = ugsub(word, "([" .. export.vowel_no_jo .. "])([^" .. export.vowel .. "]*)$",
"%1́%2")
-- If that caused an acute and grave next to each other, remove the grave
return export.correct_grave_acute_clash(word)
end
-- Remove the last primary stress from the word and put it on the final syllable. Leave grave accents alone except in
-- the last syllable. If final syllable already has primary stress, do nothing. NOTE: Translit must already be
-- decomposed! See comment at top.
local function make_ending_stressed_after_hyphen_split(ru, tr)
if not tr then
return make_ending_stressed_ru(ru), nil
end
-- If already ending stressed, just return ru/tr so we don't mess up ё
if export.is_ending_stressed(ru) then
return ru, tr
end
-- Destress the last stressed syllable; pass in "noconcat" so we get
-- the individual syllables back
local rusyl, trsyl = make_unstressed_once_after_hyphen_split(ru, tr, "noconcat")
-- Add an acute to the last syllable of both Russian and translit
rusyl[#rusyl] = ugsub(rusyl[#rusyl], "([" .. export.vowel_no_jo .. "])",
"%1" .. AC)
trsyl[#trsyl] = ugsub(trsyl[#trsyl], "([" .. export.tr_vowel .. "])",
"%1" .. AC)
-- If that caused an acute and grave next to each other, remove the grave
rusyl[#rusyl], trsyl[#trsyl] =
export.correct_grave_acute_clash(rusyl[#rusyl], trsyl[#trsyl])
-- j correction didn't get applied in make_unstressed_once because
-- we short-circuited it and made it return lists of syllables
return concat(rusyl, ""),
export.j_correction(concat(trsyl, ""))
end
--[==[
Remove the last primary stress from the portion of the word to the right of any hyphen (unless the hyphen is word-final)
and put it on the final syllable. Leave grave accents alone except in the last syllable. If final syllable already has
primary stress, do nothing. (See `make_unstressed_once()` for why we don't affect stresses to the left of a hyphen.)
NOTE: Translit must already be decomposed! See comment at top.
]==]
function export.make_ending_stressed(ru, tr)
return map_last_hyphenated_component(make_ending_stressed_after_hyphen_split, ru, tr)
end
local function make_beginning_stressed_ru(word)
-- If already beginning stressed, just return word so we don't mess up ё
if export.is_beginning_stressed(word) then
return word
end
-- Destress the first stressed syllable
word = make_unstressed_once_at_beginning_ru(word)
-- Add an acute to the first syllable
word = ugsub(word, "^([^" .. export.vowel .. "]*)([" .. export.vowel_no_jo .. "])",
"%1%2́")
-- If that caused an acute and grave next to each other, remove the grave
return export.correct_grave_acute_clash(word)
end
--[==[
Remove the first primary stress from the word and put it on the initial syllable. Leave grave accents alone except in
the first syllable. If initial syllable already has primary stress, do nothing. NOTE: Translit must already be
decomposed! See comment at top.
]==]
function export.make_beginning_stressed(ru, tr)
if not tr then
return make_beginning_stressed_ru(ru), nil
end
-- If already beginning stressed, just return ru/tr so we don't mess up ё
if export.is_beginning_stressed(ru) then
return ru, tr
end
-- Destress the first stressed syllable; pass in "noconcat" so we get
-- the individual syllables back
local rusyl, trsyl = export.make_unstressed_once_at_beginning(ru, tr, "noconcat")
-- Add an acute to the first syllable of both Russian and translit
rusyl[1] = ugsub(rusyl[1], "([" .. export.vowel_no_jo .. "])",
"%1" .. AC)
trsyl[1] = ugsub(trsyl[1], "([" .. export.tr_vowel .. "])",
"%1" .. AC)
-- If that caused an acute and grave next to each other, remove the grave
rusyl[1], trsyl[1] = export.correct_grave_acute_clash(rusyl[1], trsyl[1])
-- j correction didn't get applied in make_unstressed_once_at_beginning
-- because we short-circuited it and made it return lists of syllables
return concat(rusyl, ""),
export.j_correction(concat(trsyl, ""))
end
-- used for tracking and categorization
local hard_cons = {"hard-cons", "cons"}
local hard_vowel = {"vowel", "hard-vowel"}
local i_vowel = {"i", "vowel", "soft-vowel"}
local sibilant_cons = {"sibilant", "cons"}
local soft_vowel = {"vowel", "soft-vowel"}
local velar_cons = {"velar", "cons"}
local trailing_letter_type = {
["ш"] = sibilant_cons,
["щ"] = sibilant_cons,
["ч"] = sibilant_cons,
["ж"] = sibilant_cons,
["ц"] = {"c", "cons"},
["к"] = velar_cons,
["г"] = velar_cons,
["х"] = velar_cons,
["ь"] = {"soft-cons", "cons"},
["ъ"] = hard_cons,
["й"] = {"palatal", "cons"},
["а"] = hard_vowel,
["я"] = soft_vowel,
["э"] = hard_vowel,
["е"] = soft_vowel,
["ѐ"] = soft_vowel,
["ѣ"] = soft_vowel,
["и"] = i_vowel,
["ѝ"] = i_vowel,
["ӥ"] = i_vowel,
["і"] = i_vowel,
["ї"] = i_vowel,
["ѵ"] = i_vowel,
["ы"] = hard_vowel,
["о"] = hard_vowel,
["ё"] = soft_vowel,
["у"] = hard_vowel,
["ю"] = soft_vowel,
}
function export.get_stem_trailing_letter_type(stem)
return trailing_letter_type[ulower(usub(export.remove_accents(stem), -1))] or hard_cons
end
--[==[
Reduce stem by eliminating the "epenthetic" vowel. Applies to nominative singular masculine 2nd-declension hard and
soft, and 3rd-declension feminine in -ь (e.g. [[любовь]]). `STEM` should be the result after calling
`detect_stem_type()`, but with final -й if present. Normally returns two arguments (`STEM` and `TR`), but can be called
from a template or bot using `#invoke` and will return one argument (`STEM`, or `STEM//TR` if `TR` is present). Returns
{nil} if unable to reduce. NOTE: Translit must already be decomposed! See comment at top.
]==]
function export.reduce_stem(stem, tr, soft_n)
local pre, letter, post
local pretr, lettertr, posttr
local combine_tr = false
-- test cases with translit:
-- =p.reduce_stem("фе́ез", "fɛ́jez") -> фе́йз, fɛ́jz
-- =p.reduce_stem("фе́йез", "fɛ́jez") -> фе́йз, fɛ́jz
-- =p.reduce_stem("фе́без", "fɛ́bez") -> фе́бз, fɛ́bz
-- =p.reduce_stem("фе́лез", "fɛ́lez") -> фе́льз, fɛ́lʹz
-- =p.reduce_stem("феёз", p.decompose("fɛjóz")) -> фейз, fɛjz
-- =p.reduce_stem("фейёз", p.decompose("fɛjjóz")) -> фейз, fɛjz
-- =p.reduce_stem("фебёз", p.decompose("fɛbjóz")) -> фебз, fɛbz
-- =p.reduce_stem("фелёз", p.decompose("fɛljóz")) -> фельз, fɛlʹz
-- =p.reduce_stem("фе́бей", "fɛ́bej") -> фе́бь, fɛ́bʹ
-- =p.reduce_stem("фебёй", p.decompose("fɛbjój")) -> фебь, fɛbʹ
-- =p.reduce_stem("фе́ей", "fɛ́jej") -> фе́йй, fɛ́jj
-- =p.reduce_stem("феёй", p.decompose("fɛjój")) -> фейй, fɛjj
-- so this can be called from a template (or usually, a bot)
if type(stem) == "table" then
stem, tr = ine(stem.args[1]), ine(stem.args[2])
combine_tr = true
end
pre, letter, post = umatch(stem, "^(.*)([оОеЕёЁ])́?([" .. export.cons .. "]+)$")
if not pre then
return nil, nil
end
if tr then
-- FIXME, may not be necessary to write the posttr portion as a
-- consonant + zero or more consonant/accent combinations -- when will
-- we ever get an accent after a consonant? That would indicate a
-- failure of the decompose mechanism.
pretr, lettertr, posttr = umatch(tr, "^(.*)([oOeE])́?([" .. export.tr_cons .. "][" .. export.tr_cons .. export.accent .. "]*)$")
if not pretr then
return nil, nil -- should not happen unless tr is really messed up
end
-- Remove any trailing j's on the translit stem which don't have a
-- corresponding й on the Cyrillic stem. This avoids excess j's with
-- cases like индонези́ец//indonɛzíjec, but retains multiple j's where
-- necessary.
pretr = ugsub(pretr, "[jJ]+$", function(m)
return usub(m, 1, ulen(umatch(pre, "[йЙ]*$")))
end)
end
if letter == "О" or letter == "о" then
-- FIXME, what about when the accent is on the removed letter?
if post == "й" or post == "Й" then
-- FIXME, is this correct?
return nil, nil
end
letter = ""
else
local is_upper = ufind(post, "[" .. export.uppercase .. "]")
if ufind(pre, "[" .. export.vowel .. "]́?$") then
letter = is_upper and "Й" or "й"
elseif post == "й" or post == "Й" then
letter = is_upper and "Ь" or "ь"
post = ""
if posttr then
posttr = ""
end
elseif ufind(post, "[" .. export.velar .. "]$") and ufind(pre, "[" .. export.cons_except_sib_c .. "]$") or
ufind(post, "[^йЙ" .. export.velar .. "]$") and ufind(pre, "[лЛ]$") or
soft_n and ufind(pre, "[нН]$") then
letter = is_upper and "Ь" or "ь"
else
letter = ""
end
end
stem = pre .. letter .. post
if tr then
tr = pretr .. export.translit(letter) .. posttr
end
if combine_tr then
return export.combine_russian_tr(stem, tr)
else
return stem, tr
end
end
--[==[
Generate the dereduced stem given `STEM` and `EPENTHETIC_STRESS` (which indicates whether the epenthetic vowel should be
stressed); this is without any terminating non-syllabic ending, which is added if needed by the calling function.
Normally returns two arguments (`STEM` and `TR`), but can be called from a template using `#invoke` (or by bot) and will
return one argument (`STEM`, or `STEM//TR` if `TR` is present). Returns {nil} if unable to dereduce. NOTE: Translit
must already be decomposed! See comment at top.
]==]
function export.dereduce_stem(stem, tr, epenthetic_stress)
local combine_tr = false
-- so this can be called from a template (or usually, a bot)
if type(stem) == "table" then
stem, tr, epenthetic_stress = ine(stem.args[1]), ine(stem.args[2]), ine(stem.args[3])
combine_tr = true
end
if epenthetic_stress then
stem, tr = export.make_unstressed_once(stem, tr)
end
local pre, letter, post
local pretr, lettertr, posttr
-- FIXME!!! Deal with this special case
--if not (z.stem_type == "soft" and _.equals(z.stress_type, {"b", "f"}) -- we should ignore asterix for 2*b and 2*f (so to process it just like 2b or 2f)
-- or _.contains(z.specific, "(2)") and _.equals(z.stem_type, {"velar", "letter-ц", "vowel"})) -- and also the same for (2)-specific and 3,5,6 stem-types
--then
-- I think this corresponds to our -ья and -ье types, which we
-- handle separately
--if z.stem_type == "vowel" then -- 1).
-- if _.equals(z.stress_type, {"b", "c", "e", "f", "f'", "b'" }) then -- gen_pl ending stressed -- TODO: special vars for that
-- z.stems["gen_pl"] = _.replace(z.stems["gen_pl"], "ь$", "е́")
-- else
-- z.stems["gen_pl"] = _.replace(z.stems["gen_pl"], "ь$", "и")
-- end
--end
pre, letter, post = umatch(stem, "^(.*)([" .. export.cons .. "])([" .. export.cons .. "])$")
if tr then
pretr, lettertr, posttr = umatch(tr, "^(.*)(" .. export.tr_cons_acc_re .. ")(" .. export.tr_cons_acc_re .. ")$")
if pre and not pretr then
return nil, nil -- should not happen unless tr is really messed up
end
end
if pre then
local is_upper = ufind(post, "[" .. export.uppercase .. "]")
local epvowel
if ufind(letter, "[ьйЬЙ]") then
letter = ""
lettertr = ""
if ufind(post, "[цЦ]$") or not epenthetic_stress then
epvowel = is_upper and "Е" or "е"
else
epvowel = is_upper and "Ё" or "ё"
end
elseif ufind(letter, "[" .. export.cons_except_sib_c .. "]") and ufind(post, "[" .. export.velar .. "]") or
ufind(letter, "[" .. export.velar .. "]") then
epvowel = is_upper and "О" or "о"
elseif post == "ц" or post == "Ц" then
epvowel = is_upper and "Е" or "е"
elseif epenthetic_stress then
if ufind(letter, "[" .. export.sib .. "]") then
epvowel = is_upper and "О́" or "о́"
else
epvowel = is_upper and "Ё" or "ё"
end
else
epvowel = is_upper and "Е" or "е"
end
assert(epvowel)
stem = pre .. letter .. epvowel .. post
if tr then
tr = pretr .. lettertr .. export.translit(epvowel) .. posttr
tr = export.j_correction(tr)
end
if epenthetic_stress then
stem, tr = export.make_ending_stressed(stem, tr)
end
if combine_tr then
return export.combine_russian_tr(stem, tr)
else
return stem, tr
end
end
return nil, nil
end
--[==[
Parse an entry that potentially has final footnote symbols and initial `*` for a hypothetical entry into initial
symbols, text and final symbols.
]==]
function export.split_symbols(entry, do_subscript)
local prefentry, finalnotes = m_table_tools.separate_notes(entry)
local initnotes, text = umatch(prefentry, "(%*?)(.*)$")
return initnotes, text, finalnotes
end
--------------------------------------------------------------------------
-- Used for manual translit --
--------------------------------------------------------------------------
--[==[
Transliterate text after removing any links. The translit is decomposed in the process.
]==]
function export.translit_no_links(text)
return export.translit(require("Modül:bağlantılar").remove_links(text))
end
--[==[
Split a combined Cyrillic/translit string (either in the form `CYRILLIC//TRANSLIT` or just `CYRILLIC`) into its
components, decompose the translit, and either return a two-element list of `CYRILLIC` and `TRANSLIT` (if `dopair` is
given), or two separate return values (if `dopair` is not specified).
]==]
function export.split_russian_tr(term, dopair)
local ru, tr
if not term:find("//") then
ru = term
else
local splitvals = split(term, "//")
if #splitvals ~= 2 then
error("Must have at most one // in a Russian//translit expr: '" .. term .. "'")
end
ru, tr = splitvals[1], export.decompose(splitvals[2])
end
if dopair then
return {ru, tr}
else
return ru, tr
end
end
--[==[
Combine Cyrillic and translit into a single string separated by `//`. If translit is {nil}, the return value will be
the same as the passed-in Cyrillic. `ru` can be a string (which any manual translit in `tr`) or a two-element table of
`{CYRILLIC, TRANSLIT}`.
]==]
function export.combine_russian_tr(ru, tr)
if type(ru) == "table" then
ru, tr = unpack(ru)
end
if tr then
return ru .. "//" .. tr
else
return ru
end
end
local function concat_maybe_moving_notes(x, y, movenotes)
if movenotes then
local xentry, xnotes = m_table_tools.separate_notes(x)
local yentry, ynotes = m_table_tools.separate_notes(y)
return xentry .. yentry .. xnotes .. ynotes
else
return x .. y
end
end
--[==[
Concatenate two Cyrillic strings `RU1` and `RU2` that may have corresponding manual transliteration `TR1` and `TR2`
(which should be {nil} if there is no manual translit, and otherwise should be decomposed). If `DOPAIR`, return a
two-item list of the combined Cyrillic and manual translit (which will be {nil} if both `TR1` and `TR2` are {nil});
else, return two values, the combined Cyrillic and manual translit. If `MOVENOTES`, extract any footnote symbols at the
end of `RU1` and move them to the end of the concatenated string, before any footnote symbols for `RU2`; same thing goes
for `TR1` and `TR2`.
]==]
function export.concat_russian_tr(ru1, tr1, ru2, tr2, dopair, movenotes)
local ru, tr
if not tr1 and not tr2 then
ru = concat_maybe_moving_notes(ru1, ru2, movenotes)
else
if not tr1 then
tr1 = export.translit_no_links(ru1)
end
if not tr2 then
tr2 = export.translit_no_links(ru2)
end
ru, tr = concat_maybe_moving_notes(ru1, ru2, movenotes), export.j_correction(concat_maybe_moving_notes(tr1, tr2, movenotes))
end
if dopair then
return {ru, tr}
else
return ru, tr
end
end
--[==[
Concatenate two Cyrillic/translit combinations (where each combination is a two-element list of `{CYRILLIC, TRANSLIT}`
where `TRANSLIT` may be nil) by individually concatenating the Cyrillic and translit portions, and return a concatenated
combination as a two-element list. If the manual translit portions of both terms on entry are {nil}, the result will
also have {nil} manual translit. If `MOVENOTES`, extract any footnote symbols at the end of `TERM1` and move them after
the concatenated string and before any footnote symbols at the end of `TERM2`.
]==]
function export.concat_paired_russian_tr(term1, term2, movenotes)
assert(type(term1) == "table")
assert(type(term2) == "table")
local ru1, tr1 = term1[1], term1[2]
local ru2, tr2 = term2[1], term2[2]
return export.concat_russian_tr(ru1, tr1, ru2, tr2, "dopair", movenotes)
end
function export.concat_forms(forms)
local joined_rutr = {}
for _, form in ipairs(forms) do
insert(joined_rutr, export.combine_russian_tr(form))
end
return concat(joined_rutr, ",")
end
--[==[
Given a list of forms, where each form is a two-element list of `{CYRILLIC, TRANSLIT}`, strip footnote symbols from the
end of the Cyrillic and translit.
]==]
function export.strip_notes_from_forms(forms)
local newforms = {}
for _, form in ipairs(forms) do
local ru, tr = form[1], form[2]
ru, _ = m_table_tools.separate_notes(ru)
if tr then
tr, _ = m_table_tools.separate_notes(tr)
end
insert(newforms, {ru, tr})
end
return newforms
end
--[==[
Given a list of forms, where each form is a two-element list of `{CYRILLIC, TRANSLIT}`, unzip into parallel lists of
Cyrillic and translit. The latter list may have gaps in it.
]==]
function export.unzip_forms(forms)
local rulist = {}
local trlist = {}
for i, form in ipairs(forms) do
local ru, tr = form[1], form[2]
rulist[i] = ru
trlist[i] = tr
end
return rulist, trlist
end
--[==[
Given parallel lists of Cyrillic and translit (where the latter list may have gaps in it), return a list of forms,
where each form is a two-element list of `{CYRILLIC, TRANSLIT}`.
]==]
function export.zip_forms(rulist, trlist)
local forms = {}
for i, ru in ipairs(rulist) do
insert(forms, {ru, trlist[i]})
end
return forms
end
local function any_forms_have_translit(forms)
for _, form in ipairs(forms) do
if form[2] then
return true
end
end
return false
end
--[==[
Given a list of forms, where each form is a two-element list of `{CYRILLIC, TRANSLIT}`, combine forms with identical
Cyrillic, concatenating the translit with a comma+space in between.
]==]
function export.combine_translit_of_duplicate_forms(forms)
if not forms[1] then
return forms
end
-- Optimization to avoid creating a new list in the majority case when no translit exists.
if not any_forms_have_translit(forms) then
return forms
end
local newforms = {}
insert(newforms, {forms[1][1], forms[1][2]})
for i = 2, #forms do
local found_duplicate = false
for j = 1, #newforms do
-- If the Russian of the next form is the same as that of the last one, combine their translits and modify
-- newforms[] in-place. Otherwise add the next form to newforms[]. Make sure to clone the form rather than
-- just appending it directly since we may modify it in-place; we don't want to side-effect `forms` as
-- passed in.
if forms[i][1] == newforms[j][1] then
local tr1 = newforms[j][2]
local tr2 = forms[i][2]
if not tr1 and not tr2 then
-- this shouldn't normally happen
else
tr1 = tr1 or export.translit_no_links(newforms[j][1])
tr2 = tr2 or export.translit_no_links(forms[i][1])
if tr1 == tr2 then
-- this shouldn't normally happen
else
newforms[j][2] = tr1 .. ", " .. tr2
end
end
found_duplicate = true
break
end
end
if not found_duplicate then
insert(newforms, {forms[i][1], forms[i][2]})
end
end
return newforms
end
function export.any_termobjs_have_translit(termobjs)
for _, termobj in ipairs(termobjs) do
if termobj.tr then
return true
end
end
return false
end
--[==[
Given a list of term objects, where each object is a table of `{term = CYRILLIC, tr = TRANSLIT, ...}`, combine forms
with identical Cyrillic and identical ancillary properties, concatenating the translit with a comma+space in between.
Also recompose all transliteration.
]==]
function export.combine_translit_of_duplicate_termobjs_and_recompose(termobjs)
if not termobjs[1] then
return termobjs
end
-- Optimization to avoid creating a new list in the majority case when no translit exists.
if not export.any_termobjs_have_translit(termobjs) then
return termobjs
end
local newtermobjs = {}
insert(newtermobjs, m_table.shallowCopy(termobjs[1]))
for i = 2, #termobjs do
local found_duplicate = false
for j = 1, #newtermobjs do
-- If the Russian of the next termobj is the same as that of the last one, combine their translits and
-- modify newtermobjs[] in-place. Otherwise add the next termobj to newtermobjs[]. Make sure to clone the
-- termobj rather than just appending it directly since we may modify it in-place; we don't want to
-- side-effect `termobjs` as passed in.
if termobjs[i].term == newtermobjs[j].term and
m_headword_utilities.termobj_ancillary_properties_equal(termobjs[i], newtermobjs[j]) then
local tr1 = newtermobjs[j].tr
local tr2 = termobjs[i].tr
if not tr1 and not tr2 then
-- this shouldn't normally happen
else
tr1 = tr1 or export.translit_no_links(newtermobjs[j].term)
tr2 = tr2 or export.translit_no_links(termobjs[i].term)
if tr1 == tr2 then
-- this shouldn't normally happen
else
newtermobjs[j].tr = tr1 .. ", " .. tr2
end
end
found_duplicate = true
break
end
end
if not found_duplicate then
insert(newtermobjs, m_table.shallowCopy(termobjs[i]))
end
end
for _, newtermobj in ipairs(newtermobjs) do
if newtermobj.tr then
newtermobj.tr = export.recompose(newtermobj.tr)
end
end
return newtermobjs
end
--[==[
Given a list of forms, where each form is a two-element list of `{CYRILLIC, TRANSLIT}`, split cases where two different
transliterations have been packed into a single translit field by creating two adjacent term/translit pairs. This is
the opposite operation of `combine_translit_of_duplicate_forms()`.
]==]
function export.split_translit_of_duplicate_forms(forms)
if not forms[1] then
return forms
end
-- Optimization to avoid creating a new list in the majority case when no translit exists.
if not export.any_forms_have_translit(forms) then
return forms
end
local newforms = {}
for _, form in ipairs(forms) do
local ru, tr = unpack(form)
if not tr or not tr:find(",") or ru:find(",") then
insert(newforms, form)
else
local split_trs = split(tr, ",%s*")
local default_tr = export.translit_no_links(ru)
for _, split_tr in ipairs(split_trs) do
if split_tr == default_tr then
split_tr = nil
end
insert(newforms, {ru, split_tr})
end
end
end
return newforms
end
--[==[
Given a list of forms, where each form is a two-element list of `{CYRILLIC, TRANSLIT}`, split cases where two different
transliterations have been packed into a single translit field by creating two adjacent term/translit pairs. This is
the opposite operation of `combine_translit_of_duplicate_forms()`.
]==]
function export.split_translit_of_duplicate_termobjs_and_decompose(termobjs)
if not termobjs[1] then
return termobjs
end
-- Optimization to avoid creating a new list in the majority case when no translit exists.
if not export.any_termobjs_have_translit(termobjs) then
return termobjs
end
local newobjs = {}
for _, obj in ipairs(termobjs) do
local tr = obj.tr
if tr then
tr = export.decompose(tr)
end
if not tr or not tr:find(",") or obj.term:find(",[^%s]") then
if not tr or tr == obj.tr then
insert(newobjs, obj)
else
obj = m_table.shallowCopy(obj)
obj.tr = tr
insert(newobjs, obj)
end
else
local term = obj.term
local embedded_comma_in_term = not not term:find(",")
-- If there's an embedded comma in the term, we want to split on commas not followed by a space; otherwise,
-- we split on commas whether or not followed by a space. To implement "comma not followed by space", we
-- can use a "frontier pattern"; the one below matches if the character after the comma is in the specified
-- set (which is anything but a comma or space) and the comma itself is not in the specified set (in other
-- words, it is a comma or space, which matches because it's a comma). This doesn't work correctly if there
-- are two commas in a row, but that should not happen as there should not be an empty translit.
local split_trs = split(tr, embedded_comma_in_term and ",%f[^,%s]" or ",%s*")
local default_tr = export.translit_no_links(term)
for _, split_tr in ipairs(split_trs) do
if split_tr == default_tr then
split_tr = nil
end
local newobj = m_table.shallowCopy(obj)
newobj.tr = split_tr
insert(newobjs, newobj)
end
end
end
return newobjs
end
function export.strip_ending(ru, tr, ending)
local strippedru = ugsub(ru, ending .. "$", "")
if strippedru == ru then
error("Argument " .. ru .. " doesn't end with expected ending " .. ending)
end
ru = strippedru
tr = export.strip_tr_ending(tr, ending)
return ru, tr
end
function export.strip_tr_ending(tr, ending)
if not tr then return nil end
local endingtr = ugsub(export.translit_no_links(ending), "^([Jj])", "%1?")
local strippedtr = ugsub(tr, endingtr .. "$", "")
if strippedtr == tr then
error("Translit " .. tr .. " doesn't end with expected ending " .. endingtr)
end
return strippedtr
end
return export
689j5be9hrnp2zpsl0xirx75ti03txr
5672512
5672511
2026-06-29T15:45:02Z
MustafaCavlak
59368
5672512
Scribunto
text/plain
local export = {}
--[==[ intro:
Author: Benwing; some very early work by Rua and Atitarev
This module holds some commonly used functions for the Russian language. It's generally for use from other modules, not
`#invoke`, although some functions can be invoked from a template (`export.iotation()`, `export.reduce_stem()`,
`export.dereduce_stem()`, actually added to support calling from a bot script rather than from a user template; and
`export.make_unstressed()`, called from {{tl|R:ru:Vasmer}}). There may be issues when invoking such functions from
templates when transliteration is present, due to the need for the transliteration to be decomposed, as mentioned below
(all strings from Wiktionary pages are normally in composed form).
NOTE NOTE NOTE: All functions assume that transliteration (but not Russian) has had its acute and grave accents
decomposed using `export.decompose()`. This is the first thing that should be done to all user-specified
transliteration and any transliteration we compute that we expect to work with.
]==]
local m_str_utils = require("Modül:string araçları")
local m_table_tools = require("Modül:table tools")
-- Prevents an infinite require loop since ru-translit requires a different function in this module.
local m_ru_translit = require("Modül:require when needed")("Modül:ru-alfabeçeviri")
local m_headword_utilities = require("Modül:require when needed")("Modül:başlık başı araçları")
local m_table = require("Modül:require when needed")("Modül:table")
local gsplit = m_str_utils.gsplit
local split = m_str_utils.split
local toNFD = mw.ustring.toNFD
local u = m_str_utils.char
local ufind = mw.ustring.find
local ugsub = mw.ustring.gsub
local ulen = m_str_utils.len
local ulower = m_str_utils.lower
local umatch = mw.ustring.match
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local usub = m_str_utils.sub
local insert = table.insert
local concat = table.concat
local AC = u(0x0301) -- acute = ́
local GR = u(0x0300) -- grave = ̀
local CFLEX = u(0x0302) -- circumflex = ̂
local BREVE = u(0x0306) -- breve ̆
local DIA = u(0x0308) -- diaeresis = ̈
local CARON = u(0x030C) -- caron ̌
local OGONEK = u(0x0328) -- ogonek ̨
local PSEUDOVOWEL = u(0xFFF1) -- pseudovowel placeholder
local PSEUDOCONS = u(0xFFF2) -- pseudoconsonant placeholder
-- any stress
export.stress = AC .. GR
-- regex for any optional stress(s)
export.opt_stress = "[" .. export.stress .. "]*"
-- any accent
export.accent = export.stress .. DIA .. BREVE .. CARON .. OGONEK
-- regex for any optional accent(s)
export.opt_accent = "[" .. export.accent .. "]*"
-- any composed Cyrillic vowel with grave accent
export.composed_grave_vowel = "ѐЀѝЍ"
-- any Cyrillic vowel except ёЁ
export.vowel_no_jo = "аАеЕиИӥӤіІїЇоОуУыЫѣѢэЭюЮяЯѵѴ" .. PSEUDOVOWEL .. export.composed_grave_vowel
-- any Cyrillic vowel, including ёЁ
export.vowel = export.vowel_no_jo .. "ёЁ"
-- any vowel in transliteration
export.tr_vowel = "aAeEěĚɛƐiIoOǒǑǫǪuUyY" .. PSEUDOVOWEL
-- any consonant in transliteration, omitting "j" and the soft/hard sign
export.tr_cons_no_approx = "bBcCčČdDfFgGkKlLmMnNpPrRsSšŠtTvVxXzZžŽ" .. PSEUDOCONS
-- any consonant in transliteration, including soft/hard sign
export.tr_cons = export.tr_cons_no_approx .. "jJʹʺ"
-- regex for any consonant in transliteration, including soft/hard sign,
-- optionally followed by any accent
export.tr_cons_acc_re = "[" .. export.tr_cons .. "]" .. export.opt_accent
-- any Cyrillic consonant except sibilants and ц
export.cons_except_sib_c = "бБвВгГдДзЗйЙкКлЛмМнНпПрРсСтТфФхХъЪьЬѳѲ" .. PSEUDOCONS
-- Cyrillic sibilant consonants
export.sib = "жЖчЧшШщЩ"
-- Cyrillic sibilant consonants and ц
export.sib_c = export.sib .. "цЦ"
-- any Cyrillic consonant
export.cons = export.cons_except_sib_c .. export.sib_c
-- Cyrillic velar consonants
export.velar = "гГкКхХ"
-- uppercase Cyrillic
export.uppercase = "АБВГДЕЀЁЖЗИЍӤІЇЙКЛМНОПРСТУФХЦЧШЩЪЫЬѢЭЮЯѲѴ"
local function ine(x)
return x ~= "" and x or nil
end
--[==[
Apply Proto-Slavic iotation. This is the change that is affected by a Slavic -j- after a consonant.
`stem` is the Cyrillic stem and `tr` its optional manual translit. If `shch` is given, т iotates to щ instead of ч.
Normally return two values, the iotated Cyrillic stem and corresponding transliteration (which will be {nil} if passed
in as {nil}). If invoked from a template or bot, however, the return value will be a single string; if manual
transliteration is present, the return value will be a string of the form `CYRILLIC//TRANSLIT` with two slahes
separating the Cyrillic from the translit.
]==]
function export.iotation(stem, tr, shch)
local combine_tr = false
-- so this can be called from a template (or usually, a bot)
if type(stem) == "table" then
stem, tr, shch = ine(stem.args[1]), ine(stem.args[2]), ine(stem.args[3])
combine_tr = true
end
stem = ugsub(stem, "[сх]$", "ш")
stem = ugsub(stem, "с[кт]$", "щ")
stem = ugsub(stem, "[кц]$", "ч")
-- normally "т" is iotated as "ч" but there are many verbs that are iotated with "щ"
if shch == "щ" then
stem = stem:gsub("т$", "щ")
else
stem = stem:gsub("т$", "ч")
end
stem = ugsub(stem, "[гдз]$", "ж")
stem = ugsub(stem, "[бвмпфѳ]$", "%0л")
-- ѵ is equivalent to в after certain vowels
stem = ugsub(stem, "[аАеЕѐЀиИѝЍӥӤіІїЇѣѢэЭяЯ]" .. export.opt_stress .. "ѵ$", "%0л")
if tr then
tr = tr:gsub("[sx]$", "š")
:gsub("s[kt]$", "šč")
:gsub("[kc]$", "č")
-- normally "т" is iotated as "ч" but there are many verbs that are iotated with "щ"
if shch == "щ" then
tr = tr:gsub("t$", "šč")
else
tr = tr:gsub("t$", "č")
end
tr = tr:gsub("[dgz]$", "ž")
:gsub("[bfmpv]$", "%0l")
end
if combine_tr then
return export.combine_russian_tr(stem, tr)
end
return stem, tr
end
do
-- A word needs accents if it is unstressed and contains more than one
-- vowel, unless it's a prefix or suffix
local function word_needs_accents(word)
return not (word:sub(1, 1) == "-" or word:sub(-1) == "-") and
export.is_unstressed(word) and not export.is_monosyllabic(word)
end
-- Does a set of Cyrillic words in connected text need accents? We need to
-- split by word and check each one.
function export.needs_accents(text)
for word in gsplit(text, "%s+") do
if word_needs_accents(word) then
return true
end
end
return false
end
end
--[==[
True if either:
# A vowel is marked with explicit primary stress.
# The word has a single jo in it (which doesn't have secondary stress).
This is because a word with multiple jos requires explicit stress to be marked, since we can't infer where primary
stress lies. `Jo` can be `ё`, `ѣ̈`, or `я̈` (e.g. `сѣ̈дла`, plural of `сѣдло́`).
]==]
function export.is_stressed(word)
if word:find(AC) then
return true
end
word = toNFD(word)
return (
select(2, ugsub(word, "[еѣяЕѢЯ]" .. DIA, "")) == 1 and
not umatch(word, "[еѣяЕѢЯ]" .. DIA .. GR)
)
end
--[==[
True if a Cyrillic word requires explicit stress.
]==]
function export.is_unstressed(word)
return not export.is_stressed(word)
end
--[==[
True if Cyrillic word is stressed on the last syllable.
]==]
function export.is_ending_stressed(word)
return ufind(word, "[ёЁ][^" .. export.vowel .. "]*$") or
ufind(word, "[" .. export.vowel .. "][́̈][^" .. export.vowel .. "]*$")
end
do
local function word_is_multi_stressed(word)
-- Allow ё along with another stress, e.g. [[трёхэта́жный]], [[гёрлфре́нд]] or [[Са́мсё]].
return ufind(word, "[" .. export.vowel .. "][́̈].*[" .. export.vowel .. "][́̈]")
end
--[==[
True if a Cyrillic term has two or more stresses (acute or diaeresis) in a given word.
]==]
function export.is_multi_stressed(text)
for word in gsplit(text, "[%s-]+") do
if word_is_multi_stressed(word) then
return true
end
end
return false
end
end
--[==[
True if Cyrillic word is stressed on the first syllable.
]==]
function export.is_beginning_stressed(word)
return ufind(word, "^[^" .. export.vowel .. "]*[ёЁ]") or
ufind(word, "^[^" .. export.vowel .. "]*[" .. export.vowel .. "]́")
end
--[==[
True if Cyrillic word has no vowel. Don't treat suffixes as nonsyllabic even if they have no vowel, as they are
generally added onto words with vowels.
]==]
function export.is_nonsyllabic(word)
return not ufind(word, "^%-") and not ufind(word, "[" .. export.vowel .. "]")
end
--[==[
True if Cyrillic word has no more than one vowel; includes non-syllabic stems such as `льд-`.
]==]
function export.is_monosyllabic(word)
return not ufind(word, "[" .. export.vowel .. "].*[" .. export.vowel .. "]")
end
local recomposer = {
-- Cyrillic letters
["е" .. DIA] = "ё",
["Е" .. DIA] = "Ё",
["и" .. DIA] = "ӥ",
["И" .. DIA] = "Ӥ",
["и" .. BREVE] = "й",
["И" .. BREVE] = "Й",
["і" .. DIA] = "ї",
["І" .. DIA] = "Ї",
-- Latin letters
["c" .. CARON] = "č",
["C" .. CARON] = "Č",
["e" .. CARON] = "ě",
["E" .. CARON] = "Ě",
["o" .. CARON] = "ǒ",
["O" .. CARON] = "Ǒ",
["o" .. OGONEK] = "ǫ",
["O" .. OGONEK] = "Ǫ",
["s" .. CARON] = "š",
["S" .. CARON] = "Š",
["z" .. CARON] = "ž",
["Z" .. CARON] = "Ž",
-- used in ru-pron:
["ж" .. BREVE] = "ӂ", -- used in ru-pron
["Ж" .. BREVE] = "Ӂ",
["j" .. CFLEX] = "ĵ",
["J" .. CFLEX] = "Ĵ",
["j" .. CARON] = "ǰ",
-- no composed uppercase equivalent of J-caron
["ʒ" .. CARON] = "ǯ",
["Ʒ" .. CARON] = "Ǯ",
}
--[==[
Decompose acute, grave, etc. on letters (esp. Latin) into individivual character + combining accent. But recompose
Cyrillic and Latin characters that we want to treat as units and get caught in the crossfire. We mostly want acute and
grave decomposed; perhaps should just explicitly decompose those and no others.
]==]
function export.decompose(text)
return (ugsub(toNFD(text), ".[" .. BREVE .. DIA .. CARON .. OGONEK .. "]", recomposer))
end
function export.assert_decomposed(text)
assert(not ufind(text, "[áéíóúýàèìòùỳäëïöüÿÁÉÍÓÚÝÀÈÌÒÙỲÄËÏÖÜŸ]"))
end
--[==[
Transliterate text and then apply acute/grave decomposition.
]==]
function export.translit(text, no_include_monosyllabic_jo_accent)
local jo_accent = not no_include_monosyllabic_jo_accent and "mono" or nil
return export.decompose(m_ru_translit.tr(text, nil, nil, jo_accent))
end
--[==[
Recompose acutes and graves into preceding vowels. Probably not necessary.
]==]
function export.recompose(text)
return mw.ustring.toNFC(text)
end
local grave_decomposer = {
["ѐ"] = "е" .. GR,
["Ѐ"] = "Е" .. GR,
["ѝ"] = "и" .. GR,
["Ѝ"] = "И" .. GR,
}
--[==[
Decompose precomposed Cyrillic chars w/grave accent; not necessary for acute accent as there aren't precomposed Cyrillic
chars w/acute accent, and undesirable for precomposed `ё` and `Ё`.
]==]
function export.decompose_grave(word)
return (ugsub(word, "[ѐЀѝЍ]", grave_decomposer))
end
local grave_deaccenter = {
[GR] = "", -- grave accent
["ѐ"] = "е", -- composed Cyrillic chars w/grave accent
["Ѐ"] = "Е",
["ѝ"] = "и",
["Ѝ"] = "И",
}
local deaccenter = mw.clone(grave_deaccenter)
deaccenter[AC] = "" -- acute accent
--[==[
Remove acute and grave accents; don't affect composed diaeresis in `ёЁ` or uncomposed diaeresis in `-ѣ̈-` (as in plural
`сѣ̈дла` of `сѣдло́`). NOTE: Translit must already be decomposed! See comment at top.
]==]
function export.remove_accents(word, tr)
local ru_removed = ugsub(word, "[́̀ѐЀѝЍ]", deaccenter)
if not tr then
return ru_removed, nil
end
return ru_removed, (ugsub(tr, "[" .. AC .. GR .. "]", deaccenter))
end
--[==[
Remove grave accents; don't affect acute or composed diaeresis in `ёЁ` or uncomposed diaeresis in `-ѣ̈-` (as in plural
`сѣ̈дла` of `сѣдло́`). NOTE: Translit must already be decomposed! See comment at top.
]==]
function export.remove_grave_accents(word, tr)
local ru_removed = ugsub(word, "[̀ѐЀѝЍ]", grave_deaccenter)
if not tr then
return ru_removed, nil
end
return ru_removed, (ugsub(tr, GR, ""))
end
--[==[
Remove acute and grave accents in monosyllabic words; don't affect diaeresis (composed or uncomposed) because it
indicates a change in vowel quality, which still applies to monosyllabic words. Don't change suffixes, where a
"monosyllabic" stress is still significant (e.g. `-ча́т` short masculine of `-ча́тый`, vs. `-́чат` short masculine of
`-́чатый`). NOTE: Translit must already be decomposed! See comment at top.
]==]
function export.remove_monosyllabic_accents(word, tr)
if export.is_monosyllabic(word) and not ufind(word, "^%-") then
return export.remove_accents(word, tr)
else
return word, tr
end
end
local destresser = mw.clone(deaccenter)
destresser["ё"] = "е"
destresser["Ё"] = "Е"
destresser[DIA] = "" -- diaeresis
-- Subfunction of split_syllables(). On input we get sections of text consisting of CONSONANT - VOWEL - CONSONANT -
-- VOWEL ... - CONSONANT, where CONSONANT consists of zero or more consonants and VOWEL consists of exactly one vowel
-- plus any following accent(s); we combine these into syllables as required by split_syllables().
local function combine_captures(captures)
if captures[1] and not captures[2] then
return captures
end
local combined = {}
for i = 1, (#captures - 1), 2 do
insert(combined, captures[i] .. captures[i+1])
end
combined[#combined] = combined[#combined] .. captures[#captures]
return combined
end
--[==[
Split Russian text and transliteration into syllables. Syllables end with vowel + accent(s), except for the last
syllable, which includes any trailing consonants. NOTE: Translit must already be decomposed! See comment at top.
]==]
function export.split_syllables(ru, tr)
-- Split into alternating consonant/vowel sequences, as described in
-- combine_captures().
local rusyllables = combine_captures(split(ru, "([" .. export.vowel .. "]" .. export.opt_accent .. ")"))
local trsyllables
if tr then
export.assert_decomposed(tr)
trsyllables = combine_captures(split(tr, "([" .. export.tr_vowel .. "]" .. export.opt_accent .. ")"))
if #rusyllables ~= #trsyllables then
error("Russian " .. ru .. " doesn't have same number of syllables as translit " .. tr)
end
end
--error(concat(rusyllables, "/") .. "(" .. #rusyllables .. (trsyllables and (") || " .. concat(trsyllables, "/") .. "(" .. #trsyllables .. ")") or ""))
return rusyllables, trsyllables
end
--[==[
Split Russian word and transliteration into hyphen-separated components. Rejoining with `concat(..., "-")` will
recover the original word. If the original word ends in a hyphen, that hyphen gets included with the preceding component(this is the only case when an individual component has a hyphen in it).
]==]
function export.split_hyphens(ru, tr)
local rucomponents = split(ru, "%-")
if rucomponents[#rucomponents] == "" and #rucomponents > 1 then
rucomponents[#rucomponents - 1] = rucomponents[#rucomponents - 1] .. "-"
table.remove(rucomponents)
end
local trcomponents
if tr then
trcomponents = split(tr, "%-")
if trcomponents[#trcomponents] == "" and #trcomponents > 1 then
trcomponents[#trcomponents - 1] = trcomponents[#trcomponents - 1] .. "-"
table.remove(trcomponents)
end
if #rucomponents ~= #trcomponents then
error("Russian " .. ru .. " doesn't have same number of hyphenated components as translit " .. tr)
end
end
return rucomponents, trcomponents
end
--[==[
Apply `j` correction, converting `je` to `e` after consonants, `jo` to `o` after a sibilant, `ju` to `u` after hard
sibilant. NOTE: Translit must already be decomposed! See comment at top.
]==]
function export.j_correction(tr)
tr = ugsub(tr, "([" .. export.tr_cons_no_approx .. "]" .. export.opt_accent ..")[Jj]([EeĚě])", "%1%2")
tr = ugsub(tr, "([žščŽŠČ])[Jj]([Oo])", "%1%2")
return (ugsub(tr, "([žšŽŠ])[Jj]([Uu])", "%1%2"))
end
local function make_unstressed_ru(ru)
-- The following regexp has grave+acute+diaeresis after the bracket
return (ugsub(ru, "[̀́̈ёЁѐЀѝЍ]", destresser))
end
--[==[
Remove all stress marks (acute, grave, diaeresis). NOTE: Translit must already be decomposed! See comment at top.
]==]
function export.make_unstressed(ru, tr)
-- so this can be called from a template (specifically {{R:ru:Vasmer}})
if type(ru) == "table" then
ru, tr = ine(ru.args[1]), ine(ru.args[2])
end
if not tr then
return make_unstressed_ru(ru), nil
end
-- In the presence of TR, we need to do things the hard way: Splitting
-- into syllables and only converting Latin o to e opposite a ё.
local rusyl, trsyl = export.split_syllables(ru, tr)
for i=1,#rusyl do
if ufind(rusyl[i], "[ёЁ]") then
trsyl[i] = ugsub(trsyl[i], "[Oo]", {["O"] = "E", ["o"] = "e"})
end
rusyl[i] = make_unstressed_ru(rusyl[i])
-- the following should still work as it will affect accents only
trsyl[i] = make_unstressed_ru(trsyl[i])
end
-- Also need to apply j correction as otherwise we'll have je after cons, etc.
return concat(rusyl, ""), export.j_correction(concat(trsyl, ""))
end
local function remove_jo_ru(word)
return (ugsub(word, "[̈ёЁ]", destresser))
end
local function make_unstressed_once_ru(word)
-- leave graves alone
return (ugsub(word, "([́̈ёЁ])([^́̈ёЁ]*)$", function(x, rest) return destresser[x] .. rest; end, 1))
end
--[==[
Remove diaeresis stress marks only. NOTE: Translit must already be decomposed! See comment at top.
]==]
function export.remove_jo(ru, tr)
if not tr then
return remove_jo_ru(ru), nil
end
-- In the presence of TR, we need to do things the hard way: Splitting
-- into syllables and only converting Latin o to e opposite a ё.
local rusyl, trsyl = export.split_syllables(ru, tr)
for i=1,#rusyl do
if ufind(rusyl[i], "[ёЁ]") then
trsyl[i] = ugsub(trsyl[i], "[Oo]", {["O"] = "E", ["o"] = "e"})
end
rusyl[i] = remove_jo_ru(rusyl[i])
-- the following should still work as it will affect accents only
trsyl[i] = make_unstressed_once_ru(trsyl[i])
end
-- Also need to apply j correction as otherwise we'll have je after cons, etc.
return concat(rusyl, ""),
export.j_correction(concat(trsyl, ""))
end
local function map_last_hyphenated_component(fn, ru, tr)
if ufind(ru, "%-") then
-- If there is a hyphen, do it the hard way by splitting into
-- individual components and doing the last one. Otherwise we just do
-- the whole string.
local rucomponents, trcomponents = export.split_hyphens(ru, tr)
local lastru, lasttr = fn(rucomponents[#rucomponents],
trcomponents and trcomponents[#trcomponents] or nil)
rucomponents[#rucomponents] = lastru
ru = concat(rucomponents, "-")
if trcomponents then
trcomponents[#trcomponents] = lasttr
tr = concat(trcomponents, "-")
end
return ru, tr
end
return fn(ru, tr)
end
-- Make last stressed syllable (acute or diaeresis) unstressed; leave unstressed; leave graves alone; if `NOCONCAT`,
-- return individual syllables. NOTE: Translit must already be decomposed! See comment at top.
local function make_unstressed_once_after_hyphen_split(ru, tr, noconcat)
if not tr then
return make_unstressed_once_ru(ru), nil
end
-- In the presence of TR, we need to do things the hard way, as with
-- make_unstressed().
local rusyl, trsyl = export.split_syllables(ru, tr)
for i=#rusyl,1,-1 do
local stressed = export.is_stressed(rusyl[i])
if stressed then
if ufind(rusyl[i], "[ёЁ]") then
trsyl[i] = ugsub(trsyl[i], "[Oo]", {["O"] = "E", ["o"] = "e"})
end
rusyl[i] = make_unstressed_once_ru(rusyl[i])
-- the following should still work as it will affect accents only
trsyl[i] = make_unstressed_once_ru(trsyl[i])
break
end
end
if noconcat then
return rusyl, trsyl
end
-- Also need to apply j correction as otherwise we'll have je after cons
return concat(rusyl, ""),
export.j_correction(concat(trsyl, ""))
end
--[==[
Make last stressed syllable (acute or diaeresis) to the right of any hyphen unstressed (unless the hyphen is
word-final); leave graves alone. We don't destress a syllable to the left of a hyphen unless the hyphen is word-final
(i.e. a prefix). Otherwise e.g. the accents in the first part of words like ко́е-како́й and а́льфа-лу́ч won't remain. NOTE:
Translit must already be decomposed! See comment at top.
]==]
function export.make_unstressed_once(ru, tr)
return map_last_hyphenated_component(make_unstressed_once_after_hyphen_split, ru, tr)
end
local function make_unstressed_once_at_beginning_ru(word)
-- leave graves alone
return (ugsub(word, "^([^́̈ёЁ]*)([́̈ёЁ])", function(rest, x) return rest .. destresser[x]; end, 1))
end
--[==[
Make first stressed syllable (acute or diaeresis) unstressed; leave graves alone; if `NOCONCAT`, return individual
syllables. NOTE: Translit must already be decomposed! See comment at top.
]==]
function export.make_unstressed_once_at_beginning(ru, tr, noconcat)
if not tr then
return make_unstressed_once_at_beginning_ru(ru), nil
end
-- In the presence of TR, we need to do things the hard way, as with
-- make_unstressed().
local rusyl, trsyl = export.split_syllables(ru, tr)
for i=1,#rusyl do
local stressed = export.is_stressed(rusyl[i])
if stressed then
if ufind(rusyl[i], "[ёЁ]") then
trsyl[i] = ugsub(trsyl[i], "[Oo]", {["O"] = "E", ["o"] = "e"})
end
rusyl[i] = make_unstressed_once_at_beginning_ru(rusyl[i])
-- the following should still work as it will affect accents only
trsyl[i] = make_unstressed_once_at_beginning_ru(trsyl[i])
break
end
end
if noconcat then
return rusyl, trsyl
end
-- Also need to apply j correction as otherwise we'll have je after cons
return concat(rusyl, ""),
export.j_correction(concat(trsyl, ""))
end
--[==[
Subfunction of `make_ending_stressed()`, `make_beginning_stressed()`, which add an acute accent to a syllable that may
already have a grave accent; in such a case, remove the grave. NOTE: Translit must already be decomposed! See comment at
top.
]==]
function export.correct_grave_acute_clash(word, tr)
word = ugsub(word, "([̀ѐЀѝЍ])́", function(x) return grave_deaccenter[x] .. AC; end)
word = ugsub(word, AC .. GR, AC)
if not tr then
return word, nil
end
tr = ugsub(tr, GR .. AC, AC)
tr = ugsub(tr, AC .. GR, AC)
return word, tr
end
local function make_ending_stressed_ru(word)
-- If already ending stressed, just return word so we don't mess up ё
if export.is_ending_stressed(word) then
return word
end
-- Destress the last stressed syllable
word = make_unstressed_once_ru(word)
-- Add an acute to the last syllable
word = ugsub(word, "([" .. export.vowel_no_jo .. "])([^" .. export.vowel .. "]*)$",
"%1́%2")
-- If that caused an acute and grave next to each other, remove the grave
return export.correct_grave_acute_clash(word)
end
-- Remove the last primary stress from the word and put it on the final syllable. Leave grave accents alone except in
-- the last syllable. If final syllable already has primary stress, do nothing. NOTE: Translit must already be
-- decomposed! See comment at top.
local function make_ending_stressed_after_hyphen_split(ru, tr)
if not tr then
return make_ending_stressed_ru(ru), nil
end
-- If already ending stressed, just return ru/tr so we don't mess up ё
if export.is_ending_stressed(ru) then
return ru, tr
end
-- Destress the last stressed syllable; pass in "noconcat" so we get
-- the individual syllables back
local rusyl, trsyl = make_unstressed_once_after_hyphen_split(ru, tr, "noconcat")
-- Add an acute to the last syllable of both Russian and translit
rusyl[#rusyl] = ugsub(rusyl[#rusyl], "([" .. export.vowel_no_jo .. "])",
"%1" .. AC)
trsyl[#trsyl] = ugsub(trsyl[#trsyl], "([" .. export.tr_vowel .. "])",
"%1" .. AC)
-- If that caused an acute and grave next to each other, remove the grave
rusyl[#rusyl], trsyl[#trsyl] =
export.correct_grave_acute_clash(rusyl[#rusyl], trsyl[#trsyl])
-- j correction didn't get applied in make_unstressed_once because
-- we short-circuited it and made it return lists of syllables
return concat(rusyl, ""),
export.j_correction(concat(trsyl, ""))
end
--[==[
Remove the last primary stress from the portion of the word to the right of any hyphen (unless the hyphen is word-final)
and put it on the final syllable. Leave grave accents alone except in the last syllable. If final syllable already has
primary stress, do nothing. (See `make_unstressed_once()` for why we don't affect stresses to the left of a hyphen.)
NOTE: Translit must already be decomposed! See comment at top.
]==]
function export.make_ending_stressed(ru, tr)
return map_last_hyphenated_component(make_ending_stressed_after_hyphen_split, ru, tr)
end
local function make_beginning_stressed_ru(word)
-- If already beginning stressed, just return word so we don't mess up ё
if export.is_beginning_stressed(word) then
return word
end
-- Destress the first stressed syllable
word = make_unstressed_once_at_beginning_ru(word)
-- Add an acute to the first syllable
word = ugsub(word, "^([^" .. export.vowel .. "]*)([" .. export.vowel_no_jo .. "])",
"%1%2́")
-- If that caused an acute and grave next to each other, remove the grave
return export.correct_grave_acute_clash(word)
end
--[==[
Remove the first primary stress from the word and put it on the initial syllable. Leave grave accents alone except in
the first syllable. If initial syllable already has primary stress, do nothing. NOTE: Translit must already be
decomposed! See comment at top.
]==]
function export.make_beginning_stressed(ru, tr)
if not tr then
return make_beginning_stressed_ru(ru), nil
end
-- If already beginning stressed, just return ru/tr so we don't mess up ё
if export.is_beginning_stressed(ru) then
return ru, tr
end
-- Destress the first stressed syllable; pass in "noconcat" so we get
-- the individual syllables back
local rusyl, trsyl = export.make_unstressed_once_at_beginning(ru, tr, "noconcat")
-- Add an acute to the first syllable of both Russian and translit
rusyl[1] = ugsub(rusyl[1], "([" .. export.vowel_no_jo .. "])",
"%1" .. AC)
trsyl[1] = ugsub(trsyl[1], "([" .. export.tr_vowel .. "])",
"%1" .. AC)
-- If that caused an acute and grave next to each other, remove the grave
rusyl[1], trsyl[1] = export.correct_grave_acute_clash(rusyl[1], trsyl[1])
-- j correction didn't get applied in make_unstressed_once_at_beginning
-- because we short-circuited it and made it return lists of syllables
return concat(rusyl, ""),
export.j_correction(concat(trsyl, ""))
end
-- used for tracking and categorization
local hard_cons = {"hard-cons", "cons"}
local hard_vowel = {"vowel", "hard-vowel"}
local i_vowel = {"i", "vowel", "soft-vowel"}
local sibilant_cons = {"sibilant", "cons"}
local soft_vowel = {"vowel", "soft-vowel"}
local velar_cons = {"velar", "cons"}
local trailing_letter_type = {
["ш"] = sibilant_cons,
["щ"] = sibilant_cons,
["ч"] = sibilant_cons,
["ж"] = sibilant_cons,
["ц"] = {"c", "cons"},
["к"] = velar_cons,
["г"] = velar_cons,
["х"] = velar_cons,
["ь"] = {"soft-cons", "cons"},
["ъ"] = hard_cons,
["й"] = {"palatal", "cons"},
["а"] = hard_vowel,
["я"] = soft_vowel,
["э"] = hard_vowel,
["е"] = soft_vowel,
["ѐ"] = soft_vowel,
["ѣ"] = soft_vowel,
["и"] = i_vowel,
["ѝ"] = i_vowel,
["ӥ"] = i_vowel,
["і"] = i_vowel,
["ї"] = i_vowel,
["ѵ"] = i_vowel,
["ы"] = hard_vowel,
["о"] = hard_vowel,
["ё"] = soft_vowel,
["у"] = hard_vowel,
["ю"] = soft_vowel,
}
function export.get_stem_trailing_letter_type(stem)
return trailing_letter_type[ulower(usub(export.remove_accents(stem), -1))] or hard_cons
end
--[==[
Reduce stem by eliminating the "epenthetic" vowel. Applies to nominative singular masculine 2nd-declension hard and
soft, and 3rd-declension feminine in -ь (e.g. [[любовь]]). `STEM` should be the result after calling
`detect_stem_type()`, but with final -й if present. Normally returns two arguments (`STEM` and `TR`), but can be called
from a template or bot using `#invoke` and will return one argument (`STEM`, or `STEM//TR` if `TR` is present). Returns
{nil} if unable to reduce. NOTE: Translit must already be decomposed! See comment at top.
]==]
function export.reduce_stem(stem, tr, soft_n)
local pre, letter, post
local pretr, lettertr, posttr
local combine_tr = false
-- test cases with translit:
-- =p.reduce_stem("фе́ез", "fɛ́jez") -> фе́йз, fɛ́jz
-- =p.reduce_stem("фе́йез", "fɛ́jez") -> фе́йз, fɛ́jz
-- =p.reduce_stem("фе́без", "fɛ́bez") -> фе́бз, fɛ́bz
-- =p.reduce_stem("фе́лез", "fɛ́lez") -> фе́льз, fɛ́lʹz
-- =p.reduce_stem("феёз", p.decompose("fɛjóz")) -> фейз, fɛjz
-- =p.reduce_stem("фейёз", p.decompose("fɛjjóz")) -> фейз, fɛjz
-- =p.reduce_stem("фебёз", p.decompose("fɛbjóz")) -> фебз, fɛbz
-- =p.reduce_stem("фелёз", p.decompose("fɛljóz")) -> фельз, fɛlʹz
-- =p.reduce_stem("фе́бей", "fɛ́bej") -> фе́бь, fɛ́bʹ
-- =p.reduce_stem("фебёй", p.decompose("fɛbjój")) -> фебь, fɛbʹ
-- =p.reduce_stem("фе́ей", "fɛ́jej") -> фе́йй, fɛ́jj
-- =p.reduce_stem("феёй", p.decompose("fɛjój")) -> фейй, fɛjj
-- so this can be called from a template (or usually, a bot)
if type(stem) == "table" then
stem, tr = ine(stem.args[1]), ine(stem.args[2])
combine_tr = true
end
pre, letter, post = umatch(stem, "^(.*)([оОеЕёЁ])́?([" .. export.cons .. "]+)$")
if not pre then
return nil, nil
end
if tr then
-- FIXME, may not be necessary to write the posttr portion as a
-- consonant + zero or more consonant/accent combinations -- when will
-- we ever get an accent after a consonant? That would indicate a
-- failure of the decompose mechanism.
pretr, lettertr, posttr = umatch(tr, "^(.*)([oOeE])́?([" .. export.tr_cons .. "][" .. export.tr_cons .. export.accent .. "]*)$")
if not pretr then
return nil, nil -- should not happen unless tr is really messed up
end
-- Remove any trailing j's on the translit stem which don't have a
-- corresponding й on the Cyrillic stem. This avoids excess j's with
-- cases like индонези́ец//indonɛzíjec, but retains multiple j's where
-- necessary.
pretr = ugsub(pretr, "[jJ]+$", function(m)
return usub(m, 1, ulen(umatch(pre, "[йЙ]*$")))
end)
end
if letter == "О" or letter == "о" then
-- FIXME, what about when the accent is on the removed letter?
if post == "й" or post == "Й" then
-- FIXME, is this correct?
return nil, nil
end
letter = ""
else
local is_upper = ufind(post, "[" .. export.uppercase .. "]")
if ufind(pre, "[" .. export.vowel .. "]́?$") then
letter = is_upper and "Й" or "й"
elseif post == "й" or post == "Й" then
letter = is_upper and "Ь" or "ь"
post = ""
if posttr then
posttr = ""
end
elseif ufind(post, "[" .. export.velar .. "]$") and ufind(pre, "[" .. export.cons_except_sib_c .. "]$") or
ufind(post, "[^йЙ" .. export.velar .. "]$") and ufind(pre, "[лЛ]$") or
soft_n and ufind(pre, "[нН]$") then
letter = is_upper and "Ь" or "ь"
else
letter = ""
end
end
stem = pre .. letter .. post
if tr then
tr = pretr .. export.translit(letter) .. posttr
end
if combine_tr then
return export.combine_russian_tr(stem, tr)
else
return stem, tr
end
end
--[==[
Generate the dereduced stem given `STEM` and `EPENTHETIC_STRESS` (which indicates whether the epenthetic vowel should be
stressed); this is without any terminating non-syllabic ending, which is added if needed by the calling function.
Normally returns two arguments (`STEM` and `TR`), but can be called from a template using `#invoke` (or by bot) and will
return one argument (`STEM`, or `STEM//TR` if `TR` is present). Returns {nil} if unable to dereduce. NOTE: Translit
must already be decomposed! See comment at top.
]==]
function export.dereduce_stem(stem, tr, epenthetic_stress)
local combine_tr = false
-- so this can be called from a template (or usually, a bot)
if type(stem) == "table" then
stem, tr, epenthetic_stress = ine(stem.args[1]), ine(stem.args[2]), ine(stem.args[3])
combine_tr = true
end
if epenthetic_stress then
stem, tr = export.make_unstressed_once(stem, tr)
end
local pre, letter, post
local pretr, lettertr, posttr
-- FIXME!!! Deal with this special case
--if not (z.stem_type == "soft" and _.equals(z.stress_type, {"b", "f"}) -- we should ignore asterix for 2*b and 2*f (so to process it just like 2b or 2f)
-- or _.contains(z.specific, "(2)") and _.equals(z.stem_type, {"velar", "letter-ц", "vowel"})) -- and also the same for (2)-specific and 3,5,6 stem-types
--then
-- I think this corresponds to our -ья and -ье types, which we
-- handle separately
--if z.stem_type == "vowel" then -- 1).
-- if _.equals(z.stress_type, {"b", "c", "e", "f", "f'", "b'" }) then -- gen_pl ending stressed -- TODO: special vars for that
-- z.stems["gen_pl"] = _.replace(z.stems["gen_pl"], "ь$", "е́")
-- else
-- z.stems["gen_pl"] = _.replace(z.stems["gen_pl"], "ь$", "и")
-- end
--end
pre, letter, post = umatch(stem, "^(.*)([" .. export.cons .. "])([" .. export.cons .. "])$")
if tr then
pretr, lettertr, posttr = umatch(tr, "^(.*)(" .. export.tr_cons_acc_re .. ")(" .. export.tr_cons_acc_re .. ")$")
if pre and not pretr then
return nil, nil -- should not happen unless tr is really messed up
end
end
if pre then
local is_upper = ufind(post, "[" .. export.uppercase .. "]")
local epvowel
if ufind(letter, "[ьйЬЙ]") then
letter = ""
lettertr = ""
if ufind(post, "[цЦ]$") or not epenthetic_stress then
epvowel = is_upper and "Е" or "е"
else
epvowel = is_upper and "Ё" or "ё"
end
elseif ufind(letter, "[" .. export.cons_except_sib_c .. "]") and ufind(post, "[" .. export.velar .. "]") or
ufind(letter, "[" .. export.velar .. "]") then
epvowel = is_upper and "О" or "о"
elseif post == "ц" or post == "Ц" then
epvowel = is_upper and "Е" or "е"
elseif epenthetic_stress then
if ufind(letter, "[" .. export.sib .. "]") then
epvowel = is_upper and "О́" or "о́"
else
epvowel = is_upper and "Ё" or "ё"
end
else
epvowel = is_upper and "Е" or "е"
end
assert(epvowel)
stem = pre .. letter .. epvowel .. post
if tr then
tr = pretr .. lettertr .. export.translit(epvowel) .. posttr
tr = export.j_correction(tr)
end
if epenthetic_stress then
stem, tr = export.make_ending_stressed(stem, tr)
end
if combine_tr then
return export.combine_russian_tr(stem, tr)
else
return stem, tr
end
end
return nil, nil
end
--[==[
Parse an entry that potentially has final footnote symbols and initial `*` for a hypothetical entry into initial
symbols, text and final symbols.
]==]
function export.split_symbols(entry, do_subscript)
local prefentry, finalnotes = m_table_tools.separate_notes(entry)
local initnotes, text = umatch(prefentry, "(%*?)(.*)$")
return initnotes, text, finalnotes
end
--------------------------------------------------------------------------
-- Used for manual translit --
--------------------------------------------------------------------------
--[==[
Transliterate text after removing any links. The translit is decomposed in the process.
]==]
function export.translit_no_links(text)
return export.translit(require("Modül:bağlantılar").remove_links(text))
end
--[==[
Split a combined Cyrillic/translit string (either in the form `CYRILLIC//TRANSLIT` or just `CYRILLIC`) into its
components, decompose the translit, and either return a two-element list of `CYRILLIC` and `TRANSLIT` (if `dopair` is
given), or two separate return values (if `dopair` is not specified).
]==]
function export.split_russian_tr(term, dopair)
local ru, tr
if not term:find("//") then
ru = term
else
local splitvals = split(term, "//")
if #splitvals ~= 2 then
error("Must have at most one // in a Russian//translit expr: '" .. term .. "'")
end
ru, tr = splitvals[1], export.decompose(splitvals[2])
end
if dopair then
return {ru, tr}
else
return ru, tr
end
end
--[==[
Combine Cyrillic and translit into a single string separated by `//`. If translit is {nil}, the return value will be
the same as the passed-in Cyrillic. `ru` can be a string (which any manual translit in `tr`) or a two-element table of
`{CYRILLIC, TRANSLIT}`.
]==]
function export.combine_russian_tr(ru, tr)
if type(ru) == "table" then
ru, tr = unpack(ru)
end
if tr then
return ru .. "//" .. tr
else
return ru
end
end
local function concat_maybe_moving_notes(x, y, movenotes)
if movenotes then
local xentry, xnotes = m_table_tools.separate_notes(x)
local yentry, ynotes = m_table_tools.separate_notes(y)
return xentry .. yentry .. xnotes .. ynotes
else
return x .. y
end
end
--[==[
Concatenate two Cyrillic strings `RU1` and `RU2` that may have corresponding manual transliteration `TR1` and `TR2`
(which should be {nil} if there is no manual translit, and otherwise should be decomposed). If `DOPAIR`, return a
two-item list of the combined Cyrillic and manual translit (which will be {nil} if both `TR1` and `TR2` are {nil});
else, return two values, the combined Cyrillic and manual translit. If `MOVENOTES`, extract any footnote symbols at the
end of `RU1` and move them to the end of the concatenated string, before any footnote symbols for `RU2`; same thing goes
for `TR1` and `TR2`.
]==]
function export.concat_russian_tr(ru1, tr1, ru2, tr2, dopair, movenotes)
local ru, tr
if not tr1 and not tr2 then
ru = concat_maybe_moving_notes(ru1, ru2, movenotes)
else
if not tr1 then
tr1 = export.translit_no_links(ru1)
end
if not tr2 then
tr2 = export.translit_no_links(ru2)
end
ru, tr = concat_maybe_moving_notes(ru1, ru2, movenotes), export.j_correction(concat_maybe_moving_notes(tr1, tr2, movenotes))
end
if dopair then
return {ru, tr}
else
return ru, tr
end
end
--[==[
Concatenate two Cyrillic/translit combinations (where each combination is a two-element list of `{CYRILLIC, TRANSLIT}`
where `TRANSLIT` may be nil) by individually concatenating the Cyrillic and translit portions, and return a concatenated
combination as a two-element list. If the manual translit portions of both terms on entry are {nil}, the result will
also have {nil} manual translit. If `MOVENOTES`, extract any footnote symbols at the end of `TERM1` and move them after
the concatenated string and before any footnote symbols at the end of `TERM2`.
]==]
function export.concat_paired_russian_tr(term1, term2, movenotes)
assert(type(term1) == "table")
assert(type(term2) == "table")
local ru1, tr1 = term1[1], term1[2]
local ru2, tr2 = term2[1], term2[2]
return export.concat_russian_tr(ru1, tr1, ru2, tr2, "dopair", movenotes)
end
function export.concat_forms(forms)
local joined_rutr = {}
for _, form in ipairs(forms) do
insert(joined_rutr, export.combine_russian_tr(form))
end
return concat(joined_rutr, ",")
end
--[==[
Given a list of forms, where each form is a two-element list of `{CYRILLIC, TRANSLIT}`, strip footnote symbols from the
end of the Cyrillic and translit.
]==]
function export.strip_notes_from_forms(forms)
local newforms = {}
for _, form in ipairs(forms) do
local ru, tr = form[1], form[2]
ru, _ = m_table_tools.separate_notes(ru)
if tr then
tr, _ = m_table_tools.separate_notes(tr)
end
insert(newforms, {ru, tr})
end
return newforms
end
--[==[
Given a list of forms, where each form is a two-element list of `{CYRILLIC, TRANSLIT}`, unzip into parallel lists of
Cyrillic and translit. The latter list may have gaps in it.
]==]
function export.unzip_forms(forms)
local rulist = {}
local trlist = {}
for i, form in ipairs(forms) do
local ru, tr = form[1], form[2]
rulist[i] = ru
trlist[i] = tr
end
return rulist, trlist
end
--[==[
Given parallel lists of Cyrillic and translit (where the latter list may have gaps in it), return a list of forms,
where each form is a two-element list of `{CYRILLIC, TRANSLIT}`.
]==]
function export.zip_forms(rulist, trlist)
local forms = {}
for i, ru in ipairs(rulist) do
insert(forms, {ru, trlist[i]})
end
return forms
end
local function any_forms_have_translit(forms)
for _, form in ipairs(forms) do
if form[2] then
return true
end
end
return false
end
--[==[
Given a list of forms, where each form is a two-element list of `{CYRILLIC, TRANSLIT}`, combine forms with identical
Cyrillic, concatenating the translit with a comma+space in between.
]==]
function export.combine_translit_of_duplicate_forms(forms)
if not forms[1] then
return forms
end
-- Optimization to avoid creating a new list in the majority case when no translit exists.
if not any_forms_have_translit(forms) then
return forms
end
local newforms = {}
insert(newforms, {forms[1][1], forms[1][2]})
for i = 2, #forms do
local found_duplicate = false
for j = 1, #newforms do
-- If the Russian of the next form is the same as that of the last one, combine their translits and modify
-- newforms[] in-place. Otherwise add the next form to newforms[]. Make sure to clone the form rather than
-- just appending it directly since we may modify it in-place; we don't want to side-effect `forms` as
-- passed in.
if forms[i][1] == newforms[j][1] then
local tr1 = newforms[j][2]
local tr2 = forms[i][2]
if not tr1 and not tr2 then
-- this shouldn't normally happen
else
tr1 = tr1 or export.translit_no_links(newforms[j][1])
tr2 = tr2 or export.translit_no_links(forms[i][1])
if tr1 == tr2 then
-- this shouldn't normally happen
else
newforms[j][2] = tr1 .. ", " .. tr2
end
end
found_duplicate = true
break
end
end
if not found_duplicate then
insert(newforms, {forms[i][1], forms[i][2]})
end
end
return newforms
end
function export.any_termobjs_have_translit(termobjs)
for _, termobj in ipairs(termobjs) do
if termobj.tr then
return true
end
end
return false
end
--[==[
Given a list of term objects, where each object is a table of `{term = CYRILLIC, tr = TRANSLIT, ...}`, combine forms
with identical Cyrillic and identical ancillary properties, concatenating the translit with a comma+space in between.
Also recompose all transliteration.
]==]
function export.combine_translit_of_duplicate_termobjs_and_recompose(termobjs)
if not termobjs[1] then
return termobjs
end
-- Optimization to avoid creating a new list in the majority case when no translit exists.
if not export.any_termobjs_have_translit(termobjs) then
return termobjs
end
local newtermobjs = {}
insert(newtermobjs, m_table.shallowCopy(termobjs[1]))
for i = 2, #termobjs do
local found_duplicate = false
for j = 1, #newtermobjs do
-- If the Russian of the next termobj is the same as that of the last one, combine their translits and
-- modify newtermobjs[] in-place. Otherwise add the next termobj to newtermobjs[]. Make sure to clone the
-- termobj rather than just appending it directly since we may modify it in-place; we don't want to
-- side-effect `termobjs` as passed in.
if termobjs[i].term == newtermobjs[j].term and
m_headword_utilities.termobj_ancillary_properties_equal(termobjs[i], newtermobjs[j]) then
local tr1 = newtermobjs[j].tr
local tr2 = termobjs[i].tr
if not tr1 and not tr2 then
-- this shouldn't normally happen
else
tr1 = tr1 or export.translit_no_links(newtermobjs[j].term)
tr2 = tr2 or export.translit_no_links(termobjs[i].term)
if tr1 == tr2 then
-- this shouldn't normally happen
else
newtermobjs[j].tr = tr1 .. ", " .. tr2
end
end
found_duplicate = true
break
end
end
if not found_duplicate then
insert(newtermobjs, m_table.shallowCopy(termobjs[i]))
end
end
for _, newtermobj in ipairs(newtermobjs) do
if newtermobj.tr then
newtermobj.tr = export.recompose(newtermobj.tr)
end
end
return newtermobjs
end
--[==[
Given a list of forms, where each form is a two-element list of `{CYRILLIC, TRANSLIT}`, split cases where two different
transliterations have been packed into a single translit field by creating two adjacent term/translit pairs. This is
the opposite operation of `combine_translit_of_duplicate_forms()`.
]==]
function export.split_translit_of_duplicate_forms(forms)
if not forms[1] then
return forms
end
-- Optimization to avoid creating a new list in the majority case when no translit exists.
if not export.any_forms_have_translit(forms) then
return forms
end
local newforms = {}
for _, form in ipairs(forms) do
local ru, tr = unpack(form)
if not tr or not tr:find(",") or ru:find(",") then
insert(newforms, form)
else
local split_trs = split(tr, ",%s*")
local default_tr = export.translit_no_links(ru)
for _, split_tr in ipairs(split_trs) do
if split_tr == default_tr then
split_tr = nil
end
insert(newforms, {ru, split_tr})
end
end
end
return newforms
end
--[==[
Given a list of forms, where each form is a two-element list of `{CYRILLIC, TRANSLIT}`, split cases where two different
transliterations have been packed into a single translit field by creating two adjacent term/translit pairs. This is
the opposite operation of `combine_translit_of_duplicate_forms()`.
]==]
function export.split_translit_of_duplicate_termobjs_and_decompose(termobjs)
if not termobjs[1] then
return termobjs
end
-- Optimization to avoid creating a new list in the majority case when no translit exists.
if not export.any_termobjs_have_translit(termobjs) then
return termobjs
end
local newobjs = {}
for _, obj in ipairs(termobjs) do
local tr = obj.tr
if tr then
tr = export.decompose(tr)
end
if not tr or not tr:find(",") or obj.term:find(",[^%s]") then
if not tr or tr == obj.tr then
insert(newobjs, obj)
else
obj = m_table.shallowCopy(obj)
obj.tr = tr
insert(newobjs, obj)
end
else
local term = obj.term
local embedded_comma_in_term = not not term:find(",")
-- If there's an embedded comma in the term, we want to split on commas not followed by a space; otherwise,
-- we split on commas whether or not followed by a space. To implement "comma not followed by space", we
-- can use a "frontier pattern"; the one below matches if the character after the comma is in the specified
-- set (which is anything but a comma or space) and the comma itself is not in the specified set (in other
-- words, it is a comma or space, which matches because it's a comma). This doesn't work correctly if there
-- are two commas in a row, but that should not happen as there should not be an empty translit.
local split_trs = split(tr, embedded_comma_in_term and ",%f[^,%s]" or ",%s*")
local default_tr = export.translit_no_links(term)
for _, split_tr in ipairs(split_trs) do
if split_tr == default_tr then
split_tr = nil
end
local newobj = m_table.shallowCopy(obj)
newobj.tr = split_tr
insert(newobjs, newobj)
end
end
end
return newobjs
end
function export.strip_ending(ru, tr, ending)
local strippedru = ugsub(ru, ending .. "$", "")
if strippedru == ru then
error("Argument " .. ru .. " doesn't end with expected ending " .. ending)
end
ru = strippedru
tr = export.strip_tr_ending(tr, ending)
return ru, tr
end
function export.strip_tr_ending(tr, ending)
if not tr then return nil end
local endingtr = ugsub(export.translit_no_links(ending), "^([Jj])", "%1?")
local strippedtr = ugsub(tr, endingtr .. "$", "")
if strippedtr == tr then
error("Translit " .. tr .. " doesn't end with expected ending " .. endingtr)
end
return strippedtr
end
return export
cp7sa75hz7i2ntcnc8rxlbyy9fbp2bu
Modül:ru-nominal
828
1589237
5672503
5669923
2026-06-29T15:24:44Z
MustafaCavlak
59368
5672503
Scribunto
text/plain
--[[
This module holds functions shared between ru-noun and ru-adjective.
]]
local export = {}
local lang = require("Modül:diller").getirKodaGore("ru")
local m_links = require("Modül:bağlantılar")
local m_table = require("Modül:table")
local com = require("Modül:ru-genel")
local m_ru_translit = require("Modül:ru-alfabeçeviri")
local m_table_tools = require("Modül:table tools")
local u = mw.ustring.char
local rfind = mw.ustring.find
local rsubn = mw.ustring.gsub
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local usub = mw.ustring.sub
local HYPMARKER = "⟐"
-- version of rsubn() that discards all but the first return value
local function rsub(term, foo, bar)
local retval = rsubn(term, foo, bar)
return retval
end
-- Insert an entry into an existing list if not already present, comparing the entry to items in the existing list
-- using a key function. If entry already found, combine it into the existing entry using combine_func, a function of
-- two arguments (the existing and new entries), which should return the combined entry. Return false if entry already
-- found, true if new entry inserted. If combine_func not specified, the existing entry is left alone. If combine_func
-- is specified, the return value will be written over the existing value (i.e. the existing list will be modified
-- in-place).
--
-- FIXME: General enough to consider moving to [[Module:table]].
local function insert_if_not_by_key(list, new_entry, keyfunc, combine_func)
local new_entry_key = keyfunc(new_entry)
for i, item in ipairs(list) do
local item_key = keyfunc(item)
if m_table.deepEquals(item_key, new_entry_key) then
if combine_func then
list[i] = combine_func(item, new_entry)
end
return false
end
end
table.insert(list, new_entry)
return true
end
--------------------------------------------------------------------------
-- Used for manual translit --
--------------------------------------------------------------------------
function export.combine_stem_and_suffix(stem, tr, suf, rules, old)
local first = usub(suf, 1, 1)
if rules then
local conv = rules[first]
if conv then
local ending = usub(suf, 2)
-- The following regexp is not quite the same as com.vowels. For one thing
-- it includes й, which is important. It leaves out ы, which may or may not
-- be important.
if old and conv == "и" and rfind(ending, "^́?[аеёиійоуэюяѣ]") then
conv = "і"
end
suf = conv .. ending
end
end
-- If <adj> is present in the suffix, it means we need to translate it
-- specially; do that now.
local is_adj = rfind(suf, "<adj>")
suf = rsub(suf, "<adj>", "")
local suftr = is_adj and m_ru_translit.tr_adj(suf, "mono")
return com.concat_russian_tr(stem, tr, suf, suftr, "dopair"), suf
end
--------------------------------------------------------------------------
-- Formatting forms for display --
--------------------------------------------------------------------------
-- Generate a string to substitute into a particular form in a Wiki-markup table. `forms` is the list of forms,
-- generated by concat_word_forms(). `is_lemma` is true if we're formatting the entry for use in displaying the lemma
-- in the declension table title. In this case, we don't include the translit, and remove monosyllabic accents from the
-- Cyrillic (but not in multiword expressions). `accel_form` is the form code to speicfy in the accelerator, e.g.
-- 'nom|m|s', or nil for no accelerator. `lemma_forms` is the list of {RU, TR} lemma forms for use in the accelerator,
-- or nil if `accel_form` is nil. `remove_monosyllabic_accents_lemma_only` indicates that monosyllabic accents should
-- be removed only in the lemma; otherwise we remove them from all forms. (FIXME: Rethink why we have this flag; we
-- should be consistent.)
function export.show_form(forms, is_lemma, accel_form, lemma_forms, remove_monosyllabic_accents_lemma_only)
local russianvals = {}
local latinvals = {}
local lemmavals = {}
-- First fetch the lemma forms and translit. If there are adjacent forms that have identical Russian including
-- stress but different translit (e.g. азербайджа́нец with translits 'azerbajdžánec' and 'azɛrbajdžánec'), we
-- combine the translits, comma-separating them. (This is necessary because there is currently only one tr=
-- field per term.) We don't do this when processing the forms below; instead we handle this in a different
-- and more general fashion (see below).
local lemmaru, lemmatr
if accel_form and lemma_forms and lemma_forms[1] ~= "-" then
lemma_forms = com.combine_translit_of_duplicate_forms(com.strip_notes_from_forms(lemma_forms))
for i, form in ipairs(lemma_forms) do
local ru, tr = unpack(lemma_forms[i])
ru, tr = com.remove_monosyllabic_accents(ru, tr)
lemma_forms[i] = {ru, tr}
end
lemmaru, lemmatr = com.unzip_forms(lemma_forms)
end
-- Accumulate separately the Russian and transliteration into RUSSIANVALS and LATINVALS, then concatenate each down
-- below. We need a fair amount of logic here:
-- (1) to separate out footnote symbols;
-- (2) to separate out the hypothetical marker (a footnote symbol but causes display of the Russian and translit
-- in a special font);
-- (3) to maybe remove monosyllabic accents;
-- (4) to deduplicate repeated forms.
-- We used to generate the display (HTML) as we went, but this prevented proper deduplication because the
-- accelerator classes included in the HTML were different for otherwise identical forms. (Specifically, if two
-- forms are the same in the Russian but different in the translit, the Russian will have different display forms
-- because the translit is included in the accelerator classes.) So what we do is accumulate, separately for the
-- Russian and translit, objects containing the entry (Russian or translit), the separated footnote symbols,
-- whether the entry is hypothetical, and (for Russian only) the corresponding translit(s), for accelerator
-- generation. As we accumulate, we duduplicate based only on comparing the entries of two objects. If we need to
-- deduplicate two objects, we also need to combine their footnotes and transliteration (in the latter case, by
-- comma-separating; we do this because there is only one tr= field for each term).
for _, form in ipairs(forms) do
local ru, tr = form[1], form[2]
local ruentry, runotes = m_table_tools.separate_notes(ru)
local trentry, trnotes
if tr then
trentry, trnotes = m_table_tools.separate_notes(tr)
trnotes = rsub(trnotes, HYPMARKER, "")
end
if (is_lemma or not remove_monosyllabic_accents_lemma_only) then
ruentry, trentry = com.remove_monosyllabic_accents(ruentry, trentry)
end
local ishyp = rfind(runotes, HYPMARKER)
if ishyp then
runotes = rsub(runotes, HYPMARKER, "")
end
local ruobj = {entry = ruentry, tr = {trentry or true}, ishyp = ishyp, notes = runotes}
if not trentry then
trentry = com.translit_no_links(ruentry)
end
if not trnotes then
trnotes = com.translit_no_links(runotes)
end
local trobj = {entry = trentry, ishyp = ishyp, notes = trnotes}
local function keyfunc(obj)
return obj.entry
end
local function combine_func_ru(obj1, obj2)
for _, tr in ipairs(obj2.tr) do
m_table.insertIfNot(obj1.tr, tr)
end
obj1.notes = obj1.notes .. obj2.notes
obj1.ishyp = obj1.ishyp or obj2.ishyp
return obj1
end
local function combine_func_tr(obj1, obj2)
obj1.notes = obj1.notes .. obj2.notes
obj1.ishyp = obj1.ishyp or obj2.ishyp
return obj1
end
if is_lemma then
-- m_table.insertIfNot(lemmavals, ruspan .. " (" .. trspan .. ")")
insert_if_not_by_key(lemmavals, ruobj, keyfunc, combine_func_ru)
else
insert_if_not_by_key(russianvals, ruobj, keyfunc, combine_func_ru)
insert_if_not_by_key(latinvals, trobj, keyfunc, combine_func_tr)
end
end
-- Now finally format each object and concatenate them together.
local function concatenate_ru(objs)
local is_missing = false
for i, obj in ipairs(objs) do
local accel = nil
if lemmaru then
local translit = nil
if #obj.tr == 1 and obj.tr[1] == true then
-- no translit
else
for j, tr in ipairs(obj.tr) do
if tr == true then
obj.tr[j] = com.translit_no_links(obj.entry)
end
end
translit = table.concat(obj.tr, ", ")
end
accel = {form = accel_form, translit = translit, lemma = lemmaru, lemma_translit = lemmatr}
end
if obj.entry == "-" and #forms == 1 then
objs[i] = "—"
is_missing = true
end
if obj.ishyp then
-- no accelerator for hypothetical forms
objs[i] = m_links.full_link({lang = lang, term = nil, alt = obj.entry, tr = "-"}, "hypothetical")
else
objs[i] = m_links.full_link({lang = lang, term = obj.entry, tr = "-", accel = accel})
end
objs[i] = objs[i] .. m_table_tools.superscript_notes(obj.notes)
end
return table.concat(objs, ", "), is_missing
end
local function concatenate_tr(objs)
local scriptutils = require("Module:script utilities")
for i, obj in ipairs(objs) do
local trspan = m_links.remove_links(obj.entry) .. m_table_tools.superscript_notes(obj.notes)
if obj.ishyp then
-- FIXME, in the old [[Module:ru-noun]] code, notes were omitted from hypothetical entries. Correct?
objs[i] = scriptutils.tag_text(trspan, lang, require("Module:scripts").getByCode("Latn"),
"hypothetical")
else
objs[i] = scriptutils.tag_translit(trspan, lang, "default", " style=\"color: var(--wikt-palette-grey-8,#888);\"")
end
end
return table.concat(objs, ", ")
end
if is_lemma then
local russian_span, is_missing = concatenate_ru(lemmavals)
return russian_span
else
local russian_span, is_missing = concatenate_ru(russianvals)
if is_missing then
return russian_span
end
local latin_span = concatenate_tr(latinvals)
return russian_span .. "<br />" .. latin_span
end
end
--------------------------------------------------------------------------
-- Sibilant/Velar/ц rules --
--------------------------------------------------------------------------
local stressed_sibilant_rules = {
["я"] = "а",
["ы"] = "и",
["ё"] = "о́",
["ю"] = "у",
}
local stressed_c_rules = {
["я"] = "а",
["ё"] = "о́",
["ю"] = "у",
}
local unstressed_sibilant_rules = {
["я"] = "а",
["ы"] = "и",
["о"] = "е",
["ю"] = "у",
}
local unstressed_c_rules = {
["я"] = "а",
["о"] = "е",
["ю"] = "у",
}
local velar_rules = {
["ы"] = "и",
}
export.stressed_rules = {
["ш"] = stressed_sibilant_rules,
["щ"] = stressed_sibilant_rules,
["ч"] = stressed_sibilant_rules,
["ж"] = stressed_sibilant_rules,
["ц"] = stressed_c_rules,
["к"] = velar_rules,
["г"] = velar_rules,
["х"] = velar_rules,
}
export.unstressed_rules = {
["ш"] = unstressed_sibilant_rules,
["щ"] = unstressed_sibilant_rules,
["ч"] = unstressed_sibilant_rules,
["ж"] = unstressed_sibilant_rules,
["ц"] = unstressed_c_rules,
["к"] = velar_rules,
["г"] = velar_rules,
["х"] = velar_rules,
}
export.nonsyllabic_suffixes = m_table.listToSet({"", "ъ", "ь", "й"})
export.sibilant_suffixes = m_table.listToSet({"ш", "щ", "ч", "ж"})
return export
tfanhpvnmof7n8p3i23x8y7ww8143a1
5672504
5672503
2026-06-29T15:25:52Z
MustafaCavlak
59368
5672504
Scribunto
text/plain
--[[
This module holds functions shared between ru-noun and ru-adjective.
]]
local export = {}
local lang = require("Modül:diller").getirKodaGore("ru")
local m_links = require("Modül:bağlantılar")
local m_table = require("Modül:table")
local com = require("Modül:ru-genel")
local m_ru_translit = require("Modül:ru-alfabeçeviri")
local m_table_tools = require("Modül:table tools")
local u = mw.ustring.char
local rfind = mw.ustring.find
local rsubn = mw.ustring.gsub
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local usub = mw.ustring.sub
local HYPMARKER = "⟐"
-- version of rsubn() that discards all but the first return value
local function rsub(term, foo, bar)
local retval = rsubn(term, foo, bar)
return retval
end
-- Insert an entry into an existing list if not already present, comparing the entry to items in the existing list
-- using a key function. If entry already found, combine it into the existing entry using combine_func, a function of
-- two arguments (the existing and new entries), which should return the combined entry. Return false if entry already
-- found, true if new entry inserted. If combine_func not specified, the existing entry is left alone. If combine_func
-- is specified, the return value will be written over the existing value (i.e. the existing list will be modified
-- in-place).
--
-- FIXME: General enough to consider moving to [[Modül:table]].
local function insert_if_not_by_key(list, new_entry, keyfunc, combine_func)
local new_entry_key = keyfunc(new_entry)
for i, item in ipairs(list) do
local item_key = keyfunc(item)
if m_table.deepEquals(item_key, new_entry_key) then
if combine_func then
list[i] = combine_func(item, new_entry)
end
return false
end
end
table.insert(list, new_entry)
return true
end
--------------------------------------------------------------------------
-- Used for manual translit --
--------------------------------------------------------------------------
function export.combine_stem_and_suffix(stem, tr, suf, rules, old)
local first = usub(suf, 1, 1)
if rules then
local conv = rules[first]
if conv then
local ending = usub(suf, 2)
-- The following regexp is not quite the same as com.vowels. For one thing
-- it includes й, which is important. It leaves out ы, which may or may not
-- be important.
if old and conv == "и" and rfind(ending, "^́?[аеёиійоуэюяѣ]") then
conv = "і"
end
suf = conv .. ending
end
end
-- If <adj> is present in the suffix, it means we need to translate it
-- specially; do that now.
local is_adj = rfind(suf, "<adj>")
suf = rsub(suf, "<adj>", "")
local suftr = is_adj and m_ru_translit.tr_adj(suf, "mono")
return com.concat_russian_tr(stem, tr, suf, suftr, "dopair"), suf
end
--------------------------------------------------------------------------
-- Formatting forms for display --
--------------------------------------------------------------------------
-- Generate a string to substitute into a particular form in a Wiki-markup table. `forms` is the list of forms,
-- generated by concat_word_forms(). `is_lemma` is true if we're formatting the entry for use in displaying the lemma
-- in the declension table title. In this case, we don't include the translit, and remove monosyllabic accents from the
-- Cyrillic (but not in multiword expressions). `accel_form` is the form code to speicfy in the accelerator, e.g.
-- 'nom|m|s', or nil for no accelerator. `lemma_forms` is the list of {RU, TR} lemma forms for use in the accelerator,
-- or nil if `accel_form` is nil. `remove_monosyllabic_accents_lemma_only` indicates that monosyllabic accents should
-- be removed only in the lemma; otherwise we remove them from all forms. (FIXME: Rethink why we have this flag; we
-- should be consistent.)
function export.show_form(forms, is_lemma, accel_form, lemma_forms, remove_monosyllabic_accents_lemma_only)
local russianvals = {}
local latinvals = {}
local lemmavals = {}
-- First fetch the lemma forms and translit. If there are adjacent forms that have identical Russian including
-- stress but different translit (e.g. азербайджа́нец with translits 'azerbajdžánec' and 'azɛrbajdžánec'), we
-- combine the translits, comma-separating them. (This is necessary because there is currently only one tr=
-- field per term.) We don't do this when processing the forms below; instead we handle this in a different
-- and more general fashion (see below).
local lemmaru, lemmatr
if accel_form and lemma_forms and lemma_forms[1] ~= "-" then
lemma_forms = com.combine_translit_of_duplicate_forms(com.strip_notes_from_forms(lemma_forms))
for i, form in ipairs(lemma_forms) do
local ru, tr = unpack(lemma_forms[i])
ru, tr = com.remove_monosyllabic_accents(ru, tr)
lemma_forms[i] = {ru, tr}
end
lemmaru, lemmatr = com.unzip_forms(lemma_forms)
end
-- Accumulate separately the Russian and transliteration into RUSSIANVALS and LATINVALS, then concatenate each down
-- below. We need a fair amount of logic here:
-- (1) to separate out footnote symbols;
-- (2) to separate out the hypothetical marker (a footnote symbol but causes display of the Russian and translit
-- in a special font);
-- (3) to maybe remove monosyllabic accents;
-- (4) to deduplicate repeated forms.
-- We used to generate the display (HTML) as we went, but this prevented proper deduplication because the
-- accelerator classes included in the HTML were different for otherwise identical forms. (Specifically, if two
-- forms are the same in the Russian but different in the translit, the Russian will have different display forms
-- because the translit is included in the accelerator classes.) So what we do is accumulate, separately for the
-- Russian and translit, objects containing the entry (Russian or translit), the separated footnote symbols,
-- whether the entry is hypothetical, and (for Russian only) the corresponding translit(s), for accelerator
-- generation. As we accumulate, we duduplicate based only on comparing the entries of two objects. If we need to
-- deduplicate two objects, we also need to combine their footnotes and transliteration (in the latter case, by
-- comma-separating; we do this because there is only one tr= field for each term).
for _, form in ipairs(forms) do
local ru, tr = form[1], form[2]
local ruentry, runotes = m_table_tools.separate_notes(ru)
local trentry, trnotes
if tr then
trentry, trnotes = m_table_tools.separate_notes(tr)
trnotes = rsub(trnotes, HYPMARKER, "")
end
if (is_lemma or not remove_monosyllabic_accents_lemma_only) then
ruentry, trentry = com.remove_monosyllabic_accents(ruentry, trentry)
end
local ishyp = rfind(runotes, HYPMARKER)
if ishyp then
runotes = rsub(runotes, HYPMARKER, "")
end
local ruobj = {entry = ruentry, tr = {trentry or true}, ishyp = ishyp, notes = runotes}
if not trentry then
trentry = com.translit_no_links(ruentry)
end
if not trnotes then
trnotes = com.translit_no_links(runotes)
end
local trobj = {entry = trentry, ishyp = ishyp, notes = trnotes}
local function keyfunc(obj)
return obj.entry
end
local function combine_func_ru(obj1, obj2)
for _, tr in ipairs(obj2.tr) do
m_table.insertIfNot(obj1.tr, tr)
end
obj1.notes = obj1.notes .. obj2.notes
obj1.ishyp = obj1.ishyp or obj2.ishyp
return obj1
end
local function combine_func_tr(obj1, obj2)
obj1.notes = obj1.notes .. obj2.notes
obj1.ishyp = obj1.ishyp or obj2.ishyp
return obj1
end
if is_lemma then
-- m_table.insertIfNot(lemmavals, ruspan .. " (" .. trspan .. ")")
insert_if_not_by_key(lemmavals, ruobj, keyfunc, combine_func_ru)
else
insert_if_not_by_key(russianvals, ruobj, keyfunc, combine_func_ru)
insert_if_not_by_key(latinvals, trobj, keyfunc, combine_func_tr)
end
end
-- Now finally format each object and concatenate them together.
local function concatenate_ru(objs)
local is_missing = false
for i, obj in ipairs(objs) do
local accel = nil
if lemmaru then
local translit = nil
if #obj.tr == 1 and obj.tr[1] == true then
-- no translit
else
for j, tr in ipairs(obj.tr) do
if tr == true then
obj.tr[j] = com.translit_no_links(obj.entry)
end
end
translit = table.concat(obj.tr, ", ")
end
accel = {form = accel_form, translit = translit, lemma = lemmaru, lemma_translit = lemmatr}
end
if obj.entry == "-" and #forms == 1 then
objs[i] = "—"
is_missing = true
end
if obj.ishyp then
-- no accelerator for hypothetical forms
objs[i] = m_links.full_link({lang = lang, term = nil, alt = obj.entry, tr = "-"}, "hypothetical")
else
objs[i] = m_links.full_link({lang = lang, term = obj.entry, tr = "-", accel = accel})
end
objs[i] = objs[i] .. m_table_tools.superscript_notes(obj.notes)
end
return table.concat(objs, ", "), is_missing
end
local function concatenate_tr(objs)
local scriptutils = require("Modül:alfabe araçları")
for i, obj in ipairs(objs) do
local trspan = m_links.remove_links(obj.entry) .. m_table_tools.superscript_notes(obj.notes)
if obj.ishyp then
-- FIXME, in the old [[Modül:ru-ad]] code, notes were omitted from hypothetical entries. Correct?
objs[i] = scriptutils.tag_text(trspan, lang, require("Modül:alfabeler").getirKodaGore("Latn"),
"hypothetical")
else
objs[i] = scriptutils.tag_translit(trspan, lang, "default", " style=\"color: var(--wikt-palette-grey-8,#888);\"")
end
end
return table.concat(objs, ", ")
end
if is_lemma then
local russian_span, is_missing = concatenate_ru(lemmavals)
return russian_span
else
local russian_span, is_missing = concatenate_ru(russianvals)
if is_missing then
return russian_span
end
local latin_span = concatenate_tr(latinvals)
return russian_span .. "<br />" .. latin_span
end
end
--------------------------------------------------------------------------
-- Sibilant/Velar/ц rules --
--------------------------------------------------------------------------
local stressed_sibilant_rules = {
["я"] = "а",
["ы"] = "и",
["ё"] = "о́",
["ю"] = "у",
}
local stressed_c_rules = {
["я"] = "а",
["ё"] = "о́",
["ю"] = "у",
}
local unstressed_sibilant_rules = {
["я"] = "а",
["ы"] = "и",
["о"] = "е",
["ю"] = "у",
}
local unstressed_c_rules = {
["я"] = "а",
["о"] = "е",
["ю"] = "у",
}
local velar_rules = {
["ы"] = "и",
}
export.stressed_rules = {
["ш"] = stressed_sibilant_rules,
["щ"] = stressed_sibilant_rules,
["ч"] = stressed_sibilant_rules,
["ж"] = stressed_sibilant_rules,
["ц"] = stressed_c_rules,
["к"] = velar_rules,
["г"] = velar_rules,
["х"] = velar_rules,
}
export.unstressed_rules = {
["ш"] = unstressed_sibilant_rules,
["щ"] = unstressed_sibilant_rules,
["ч"] = unstressed_sibilant_rules,
["ж"] = unstressed_sibilant_rules,
["ц"] = unstressed_c_rules,
["к"] = velar_rules,
["г"] = velar_rules,
["х"] = velar_rules,
}
export.nonsyllabic_suffixes = m_table.listToSet({"", "ъ", "ь", "й"})
export.sibilant_suffixes = m_table.listToSet({"ш", "щ", "ч", "ж"})
return export
tdxva6w3kct9tttsryhs9o2avr02q8g
Şablon:ru-eylem-2a-impf
10
1590996
5672485
2026-06-29T14:05:45Z
MustafaCavlak
59368
Yeni sayfa : <div class="NavFrame" style="width:80%"> <div class="NavHead"style="background:#E0B0FF; text-align:left">''{{{1|{{SAYFAADI}}}}}'' eyleminin çekimi</small></div> <div class="NavContent"> {| class="wikitable inflection-table" |+ |- ! colspan="4" style="background:#E6E6FA; | tamamlanmamış bakış açısı |- ! colspan="2" style="background:#89CFF0; | mastar | colspan="2" | {{l-self|ru|{{{1}}}}} |- ! colspan="2" style="background:#E6E6FA; | eylemsiler ! style="background:#E6E6FA...
5672485
wikitext
text/x-wiki
<div class="NavFrame" style="width:80%">
<div class="NavHead"style="background:#E0B0FF; text-align:left">''{{{1|{{SAYFAADI}}}}}'' eyleminin çekimi</small></div>
<div class="NavContent">
{| class="wikitable inflection-table"
|+
|-
! colspan="4" style="background:#E6E6FA; | tamamlanmamış bakış açısı
|-
! colspan="2" style="background:#89CFF0; | mastar
| colspan="2" | {{l-self|ru|{{{1}}}}}
|-
! colspan="2" style="background:#E6E6FA; | eylemsiler
! style="background:#E6E6FA; | şimdiki zaman
! style="background:#E6E6FA; | geçmiş zaman
|-
! colspan="2" style="background:#89CFF0; | etken ortaç
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}у́ющий}}
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}ова́вший}}
|-
! colspan="2" style="background:#89CFF0; | edilgen ortaç
| {{#switch:{{{geçişsiz|}}}|1=—|#default={{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}у́емый}}}}
| {{#switch:{{{ego|}}}|-=—|#default={{l-self|ru|{{{ego|{{#invoke:string|sub|s={{{1}}}|j=-6}}о́ванный}}}}}}}
|-
! colspan="2" style="background:#89CFF0; | ulaç
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}у́я}}
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}ова́в}},<br>{{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}ова́вши}}
|-
! colspan="2" style="background:#E6E6FA; |
! style="background:#E6E6FA; | şimdiki zaman
! style="background:#E6E6FA; | gelecek zaman
|-
! colspan="2" style="background:#89CFF0; | 1. tekil şahıs (я)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}у́ю}}
| {{l-self|ru|бу́ду}} {{l-self|ru|{{{1}}}}}
|-
! colspan="2" style="background:#89CFF0; | 2. tekil şahıs (ты)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}у́ешь}}
| {{l-self|ru|бу́дешь}} {{l-self|ru|{{{1}}}}}
|-
! colspan="2" style="background:#89CFF0; | 3. tekil şahıs (он/она/оно)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}у́ет}}
| {{l-self|ru|бу́дет}} {{l-self|ru|{{{1}}}}}
|-
! colspan="2" style="background:#89CFF0; | 1. çoğul şahıs (мы)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}у́ем}}
| {{l-self|ru|бу́дем}} {{l-self|ru|{{{1}}}}}
|-
! colspan="2" style="background:#89CFF0; | 2. çoğul şahıs (вы)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}у́ете}}
| {{l-self|ru|бу́дете}} {{l-self|ru|{{{1}}}}}
|-
! colspan="2" style="background:#89CFF0; | 3. çoğul şahıs (они)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}у́ют}}
| {{l-self|ru|бу́дут}} {{l-self|ru|{{{1}}}}}
|-
! colspan="2" style="background:#E6E6FA; | emir kipi
! style="background:#E6E6FA; | tekil
! style="background:#E6E6FA; | çoğul
|-
! colspan="2" style="background:#89CFF0; | 2. şahıs (ты/вы)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}у́й}}
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}у́йте}}
|-
! colspan="2" style="background:#E6E6FA; | geçmiş zaman
! style="background:#E6E6FA; | tekil
! style="background:#E6E6FA; | çoğul (мы/вы/они́)
|-
! colspan="2" style="background:#89CFF0; | eril (я/ты/он)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}ова́л}}
|
|-
! colspan="2" style="background:#89CFF0; | dişil (я/ты/она́)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}ова́ла}}
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}ова́ли}}
|-
! colspan="2" style="background:#89CFF0; | nötr (оно́)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}ова́ло}}
|
|}</div></div><noinclude>{{belgeleme}}</noinclude>
j0sc2jcha762ooe36j2fkbhop220szz
5672488
5672485
2026-06-29T14:27:48Z
MustafaCavlak
59368
5672488
wikitext
text/x-wiki
<div class="NavFrame" style="width:80%">
<div class="NavHead"style="background:#E0B0FF; text-align:left">''{{{1|{{SAYFAADI}}}}}'' eyleminin çekimi</small></div>
<div class="NavContent">
{| class="wikitable inflection-table"
|+
|-
! colspan="4" style="background:#E6E6FA; | tamamlanmamış bakış açısı
|-
! colspan="2" style="background:#89CFF0; | mastar
| colspan="2" | {{l-self|ru|{{{1}}}}}
|-
! colspan="2" style="background:#E6E6FA; | eylemsiler
! style="background:#E6E6FA; | şimdiki zaman
! style="background:#E6E6FA; | geçmiş zaman
|-
! colspan="2" style="background:#89CFF0; | etken ortaç
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}у́ющий}}
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}ова́вший}}
|-
! colspan="2" style="background:#89CFF0; | edilgen ortaç
| {{#switch:{{{geçişsiz|}}}|1=—|#default={{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}у́емый}}}}
| {{#switch:{{{ego|}}}|-=—|#default={{l-self|ru|{{{ego|{{#invoke:string|sub|s={{{1}}}|j=-7}}о́ванный}}}}}}}
|-
! colspan="2" style="background:#89CFF0; | ulaç
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}у́я}}
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}ова́в}},<br>{{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}ова́вши}}
|-
! colspan="2" style="background:#E6E6FA; |
! style="background:#E6E6FA; | şimdiki zaman
! style="background:#E6E6FA; | gelecek zaman
|-
! colspan="2" style="background:#89CFF0; | 1. tekil şahıs (я)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}у́ю}}
| {{l-self|ru|бу́ду}} {{l-self|ru|{{{1}}}}}
|-
! colspan="2" style="background:#89CFF0; | 2. tekil şahıs (ты)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}у́ешь}}
| {{l-self|ru|бу́дешь}} {{l-self|ru|{{{1}}}}}
|-
! colspan="2" style="background:#89CFF0; | 3. tekil şahıs (он/она/оно)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}у́ет}}
| {{l-self|ru|бу́дет}} {{l-self|ru|{{{1}}}}}
|-
! colspan="2" style="background:#89CFF0; | 1. çoğul şahıs (мы)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}у́ем}}
| {{l-self|ru|бу́дем}} {{l-self|ru|{{{1}}}}}
|-
! colspan="2" style="background:#89CFF0; | 2. çoğul şahıs (вы)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}у́ете}}
| {{l-self|ru|бу́дете}} {{l-self|ru|{{{1}}}}}
|-
! colspan="2" style="background:#89CFF0; | 3. çoğul şahıs (они)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}у́ют}}
| {{l-self|ru|бу́дут}} {{l-self|ru|{{{1}}}}}
|-
! colspan="2" style="background:#E6E6FA; | emir kipi
! style="background:#E6E6FA; | tekil
! style="background:#E6E6FA; | çoğul
|-
! colspan="2" style="background:#89CFF0; | 2. şahıs (ты/вы)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}у́й}}
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}у́йте}}
|-
! colspan="2" style="background:#E6E6FA; | geçmiş zaman
! style="background:#E6E6FA; | tekil
! style="background:#E6E6FA; | çoğul (мы/вы/они́)
|-
! colspan="2" style="background:#89CFF0; | eril (я/ты/он)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}ова́л}}
|
|-
! colspan="2" style="background:#89CFF0; | dişil (я/ты/она́)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}ова́ла}}
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}ова́ли}}
|-
! colspan="2" style="background:#89CFF0; | nötr (оно́)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}ова́ло}}
|
|}</div></div><noinclude>{{belgeleme}}</noinclude>
6vvnosjxklbb8y547zytioeb641c6qd
Şablon:ru-eylem-2a-pf
10
1590997
5672486
2026-06-29T14:18:57Z
MustafaCavlak
59368
Yeni sayfa : <div class="NavFrame" style="width:80%"> <div class="NavHead"style="background:#E0B0FF; text-align:left">''{{{1|{{SAYFAADI}}}}}'' eyleminin çekimi</small></div> <div class="NavContent"> {| class="wikitable inflection-table" |+ |- ! colspan="4" style="background:#E6E6FA; | tamamlanmış bakış açısı |- ! colspan="2" style="background:#89CFF0; | mastar | colspan="2" | {{l-self|ru|{{{1}}}}} |- ! colspan="2" style="background:#E6E6FA; | eylemsiler ! style="background:#E6E6FA;...
5672486
wikitext
text/x-wiki
<div class="NavFrame" style="width:80%">
<div class="NavHead"style="background:#E0B0FF; text-align:left">''{{{1|{{SAYFAADI}}}}}'' eyleminin çekimi</small></div>
<div class="NavContent">
{| class="wikitable inflection-table"
|+
|-
! colspan="4" style="background:#E6E6FA; | tamamlanmış bakış açısı
|-
! colspan="2" style="background:#89CFF0; | mastar
| colspan="2" | {{l-self|ru|{{{1}}}}}
|-
! colspan="2" style="background:#E6E6FA; | eylemsiler
! style="background:#E6E6FA; | şimdiki zaman
! style="background:#E6E6FA; | geçmiş zaman
|-
! colspan="2" style="background:#89CFF0; | etken ortaç
| —
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}ова́вший}}
|-
! colspan="2" style="background:#89CFF0; | edilgen ortaç
| —
| {{#switch:{{{ego|}}}|-=—|#default={{l-self|ru|{{{ego|{{#invoke:string|sub|s={{{1}}}|j=-6}}о́ванный}}}}}}}
|-
! colspan="2" style="background:#89CFF0; | ulaç
| —
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}ова́в}},<br>{{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}ова́вши}}
|-
! colspan="2" style="background:#E6E6FA; |
! style="background:#E6E6FA; | şimdiki zaman
! style="background:#E6E6FA; | gelecek zaman
|-
! colspan="2" style="background:#89CFF0; | 1. tekil şahıs (я)
| —
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}у́ю}}
|-
! colspan="2" style="background:#89CFF0; | 2. tekil şahıs (ты)
| —
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}у́ешь}}
|-
! colspan="2" style="background:#89CFF0; | 3. tekil şahıs (он/она/оно)
| —
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}у́ет}}
|-
! colspan="2" style="background:#89CFF0; | 1. çoğul şahıs (мы)
| —
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}у́ем}}
|-
! colspan="2" style="background:#89CFF0; | 2. çoğul şahıs (вы)
| —
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}у́ете}}
|-
! colspan="2" style="background:#89CFF0; | 3. çoğul şahıs (они)
| —
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}у́ют}}
|-
! colspan="2" style="background:#E6E6FA; | emir kipi
! style="background:#E6E6FA; | tekil
! style="background:#E6E6FA; | çoğul
|-
! colspan="2" style="background:#89CFF0; | 2. şahıs (ты/вы)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}у́й}}
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}у́йте}}
|-
! colspan="2" style="background:#E6E6FA; | geçmiş zaman
! style="background:#E6E6FA; | tekil
! style="background:#E6E6FA; | çoğul (мы/вы/они́)
|-
! colspan="2" style="background:#89CFF0; | eril (я/ты/он)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}ова́л}}
|
|-
! colspan="2" style="background:#89CFF0; | dişil (я/ты/она́)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}ова́ла}}
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}ова́ли}}
|-
! colspan="2" style="background:#89CFF0; | nötr (оно́)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-6}}ова́ло}}
|
|}</div></div><noinclude>{{belgeleme}}</noinclude>
lmokdb644jtt8hur6a0a31vbhz4bie1
5672489
5672486
2026-06-29T14:29:17Z
MustafaCavlak
59368
5672489
wikitext
text/x-wiki
<div class="NavFrame" style="width:80%">
<div class="NavHead"style="background:#E0B0FF; text-align:left">''{{{1|{{SAYFAADI}}}}}'' eyleminin çekimi</small></div>
<div class="NavContent">
{| class="wikitable inflection-table"
|+
|-
! colspan="4" style="background:#E6E6FA; | tamamlanmış bakış açısı
|-
! colspan="2" style="background:#89CFF0; | mastar
| colspan="2" | {{l-self|ru|{{{1}}}}}
|-
! colspan="2" style="background:#E6E6FA; | eylemsiler
! style="background:#E6E6FA; | şimdiki zaman
! style="background:#E6E6FA; | geçmiş zaman
|-
! colspan="2" style="background:#89CFF0; | etken ortaç
| —
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}ова́вший}}
|-
! colspan="2" style="background:#89CFF0; | edilgen ortaç
| —
| {{#switch:{{{ego|}}}|-=—|#default={{l-self|ru|{{{ego|{{#invoke:string|sub|s={{{1}}}|j=-7}}о́ванный}}}}}}}
|-
! colspan="2" style="background:#89CFF0; | ulaç
| —
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}ова́в}},<br>{{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}ова́вши}}
|-
! colspan="2" style="background:#E6E6FA; |
! style="background:#E6E6FA; | şimdiki zaman
! style="background:#E6E6FA; | gelecek zaman
|-
! colspan="2" style="background:#89CFF0; | 1. tekil şahıs (я)
| —
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}у́ю}}
|-
! colspan="2" style="background:#89CFF0; | 2. tekil şahıs (ты)
| —
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}у́ешь}}
|-
! colspan="2" style="background:#89CFF0; | 3. tekil şahıs (он/она/оно)
| —
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}у́ет}}
|-
! colspan="2" style="background:#89CFF0; | 1. çoğul şahıs (мы)
| —
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}у́ем}}
|-
! colspan="2" style="background:#89CFF0; | 2. çoğul şahıs (вы)
| —
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}у́ете}}
|-
! colspan="2" style="background:#89CFF0; | 3. çoğul şahıs (они)
| —
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}у́ют}}
|-
! colspan="2" style="background:#E6E6FA; | emir kipi
! style="background:#E6E6FA; | tekil
! style="background:#E6E6FA; | çoğul
|-
! colspan="2" style="background:#89CFF0; | 2. şahıs (ты/вы)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}у́й}}
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}у́йте}}
|-
! colspan="2" style="background:#E6E6FA; | geçmiş zaman
! style="background:#E6E6FA; | tekil
! style="background:#E6E6FA; | çoğul (мы/вы/они́)
|-
! colspan="2" style="background:#89CFF0; | eril (я/ты/он)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}ова́л}}
|
|-
! colspan="2" style="background:#89CFF0; | dişil (я/ты/она́)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}ова́ла}}
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}ова́ли}}
|-
! colspan="2" style="background:#89CFF0; | nötr (оно́)
| {{l-self|ru|{{#invoke:string|sub|s={{{1}}}|j=-7}}ова́ло}}
|
|}</div></div><noinclude>{{belgeleme}}</noinclude>
siq8u0anoq2qvgoa0u1wl698uygaixf
рисовать
0
1590998
5672490
2026-06-29T14:29:48Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Köken=== {{nakledilen|ru|pl|rysować}}, {{kökenli|ru|gmh|rīʒen}}, {{kökenli|ru|goh|rīȥan}}, {{kökenli|ru|gmw-pro|*hrītan}}, {{kökenli|ru|gem-pro|*hrītaną}}. ===Söyleniş=== * {{IPA|dil=ru|[rʲɪsɐˈvatʲ]}} * {{ses|dil=ru|Ru-рисовать.ogg}} ===Eylem=== {{ru-eylem|рисова́ть|impf|pf=нарисова́ть}} # [[çizmek]] ====Çekimleme==== {{ru-eylem-2a-impf|рисова́ть}}
5672490
wikitext
text/x-wiki
==Rusça==
===Köken===
{{nakledilen|ru|pl|rysować}}, {{kökenli|ru|gmh|rīʒen}}, {{kökenli|ru|goh|rīȥan}}, {{kökenli|ru|gmw-pro|*hrītan}}, {{kökenli|ru|gem-pro|*hrītaną}}.
===Söyleniş===
* {{IPA|dil=ru|[rʲɪsɐˈvatʲ]}}
* {{ses|dil=ru|Ru-рисовать.ogg}}
===Eylem===
{{ru-eylem|рисова́ть|impf|pf=нарисова́ть}}
# [[çizmek]]
====Çekimleme====
{{ru-eylem-2a-impf|рисова́ть}}
dew3afts7ybd1izpgkefin44uzv6eb6
Kategori:Lehçeden nakledilen Rusça sözcükler
14
1590999
5672491
2026-06-29T14:30:33Z
MustafaCavlak
59368
Yeni sayfa : {{kategori köken|dil=ru|köken=pl|tip=nakledilen}}
5672491
wikitext
text/x-wiki
{{kategori köken|dil=ru|köken=pl|tip=nakledilen}}
c91wx3mik4jy2dy8lm1v7lvk990ce8f
Kategori:Orta Yüksek Almanca kökenli Rusça sözcükler
14
1591000
5672492
2026-06-29T14:30:59Z
MustafaCavlak
59368
Yeni sayfa : {{kategori köken|dil=ru|köken=gmh}}
5672492
wikitext
text/x-wiki
{{kategori köken|dil=ru|köken=gmh}}
71eay48bs3sftnk1fhheu6hsphs4e00
Kategori:Eski Yüksek Almanca kökenli Rusça sözcükler
14
1591001
5672493
2026-06-29T14:31:17Z
MustafaCavlak
59368
Yeni sayfa : {{kategori köken|dil=ru|köken=goh}}
5672493
wikitext
text/x-wiki
{{kategori köken|dil=ru|köken=goh}}
lrez55f603sifgh6jvn7yuqqo051m1g
Kategori:Ana Batı Cermence kökenli Rusça sözcükler
14
1591002
5672494
2026-06-29T14:31:55Z
MustafaCavlak
59368
Yeni sayfa : {{kategori köken|dil=ru|köken=gmw-pro}}
5672494
wikitext
text/x-wiki
{{kategori köken|dil=ru|köken=gmw-pro}}
0zez59kkjvxhf3722uyc8e0erucp7ih
Kategori:Ana Cermence kökenli Rusça sözcükler
14
1591003
5672495
2026-06-29T14:32:11Z
MustafaCavlak
59368
Yeni sayfa : {{kategori köken|dil=ru|köken=gem-pro}}
5672495
wikitext
text/x-wiki
{{kategori köken|dil=ru|köken=gem-pro}}
74bo3qfevd903d5n4duumaes8wcul6p
нарисовать
0
1591004
5672496
2026-06-29T14:34:16Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Köken=== {{ön ek|dil=ru|на|рисова́ть}} ===Söyleniş=== * {{IPA|dil=ru|[nərʲɪsɐˈvatʲ]}} * {{ses|dil=ru|Ru-нарисовать.ogg}} ===Eylem=== {{ru-eylem|нарисова́ть|pf|impf=рисова́ть}} # [[çizmek]] ====Çekimleme==== {{ru-eylem-2a-pf|нарисова́ть}}
5672496
wikitext
text/x-wiki
==Rusça==
===Köken===
{{ön ek|dil=ru|на|рисова́ть}}
===Söyleniş===
* {{IPA|dil=ru|[nərʲɪsɐˈvatʲ]}}
* {{ses|dil=ru|Ru-нарисовать.ogg}}
===Eylem===
{{ru-eylem|нарисова́ть|pf|impf=рисова́ть}}
# [[çizmek]]
====Çekimleme====
{{ru-eylem-2a-pf|нарисова́ть}}
k1u5aciqoeq9iprf5q7qdzxtnlg2vq4
Kategori:Rusça на- ön ekiyle oluşmuş sözcükler
14
1591005
5672497
2026-06-29T14:35:00Z
MustafaCavlak
59368
Yeni sayfa : {{kategori ek|ru|ön|на-}}
5672497
wikitext
text/x-wiki
{{kategori ek|ru|ön|на-}}
ds90ti3sgrg8919yvm37cc5129ta2il
Modül:ru-eylem
828
1591006
5672498
2026-06-29T15:01:53Z
MustafaCavlak
59368
imported from en
5672498
Scribunto
text/plain
--[=[
This module contains functions for creating inflection tables for Russian
verbs.
Author: Benwing, rewritten from early version by Atitarev, earliest version by CodeCat
NOTE: This module is partly converted to support manual translit, in the
form CYRILLIC//LATIN (i.e. with a // separating the Cyrillic and Latin
parts). All the general infrastructure supports manual translit; the
only thing that doesn't is some of the specific verb conjugation functions.
In particular, all of the class 1, 2, 3 and 4 conjugation functions support
manual translit, and the rest don't. To convert another, follow the
model of one of the already-converted functions.
Note that an individual form (an entry in the 'forms' table) can be
either a string (no special manual translit; generally this originates
from the portion of the code that doesn't support manual translit), or
a one-element list {CYRILLIC} (no special manual translit), or a
two-element list {CYRILLIC, LATIN} with manual translit specified.
The code is careful only to generate manual translit when it's needed,
to avoid penalizing the majority of cases where manual transit isn't
needed.
]=]
local m_str_utils = require("Module:string utilities")
local m_utilities = require("Module:utilities")
local m_table = require("Module:table")
local m_links = require("Module:links")
local com = require("Module:ru-common")
local m_debug = require("Module:debug")
local m_table_tools = require("Module:table tools")
-- If enabled, compare this module with new version of module to make
-- sure all conjugations are the same.
local test_new_ru_verb_module = false
local export = {}
-- Within this module, conjugations are the functions that do the actual
-- conjugating by creating the forms of a basic verb.
-- They are defined further down.
local conjugations = {}
local lang = require("Module:languages").getByCode("ru")
local u = m_str_utils.char
local rfind = m_str_utils.find
local rsubn = m_str_utils.gsub
local rmatch = m_str_utils.match
local rsplit = m_str_utils.split
local usub = m_str_utils.sub
local AC = u(0x0301) -- acute = ́
local DIA = u(0x0308) -- diaeresis = ̈
local PSEUDOCONS = u(0xFFF2) -- pseudoconsonant placeholder, matching ru-common
local IRREG = "△"
-- version of rsubn() that discards all but the first return value
local function rsub(term, foo, bar)
local retval = rsubn(term, foo, bar)
return retval
end
-- version of rsubn() that returns a 2nd argument boolean indicating whether
-- a substitution was made.
local function rsubb(term, foo, bar)
local retval, nsubs = rsubn(term, foo, bar)
return retval, nsubs > 0
end
-- Fancy version of ine() (if-not-empty). Converts empty string to nil,
-- but also strips leading/trailing space and then single or double quotes,
-- to allow for embedded spaces.
local function ine(arg)
if not arg then return nil end
arg = rsub(arg, "^%s*(.-)%s*$", "%1")
if arg == "" then return nil end
local inside_quotes = rmatch(arg, '^"(.*)"$')
if inside_quotes then
return inside_quotes
end
inside_quotes = rmatch(arg, "^'(.*)'$")
if inside_quotes then
return inside_quotes
end
return arg
end
local function is_vowel_stem(stem)
return rfind(stem, "[" .. com.vowel .. AC .. DIA .. "]$")
end
-- Return the next number to use as an internal note symbol, starting at 1.
-- We look at existing internal notes to see if the symbol is already used.
local function next_note_symbol(data)
local nextsym = 1
while true do
local sym_already_seen = false
for _, note in ipairs(data.internal_notes) do
if rfind(note, "^" .. nextsym .. " ") then
sym_already_seen = true
break
end
end
if sym_already_seen then
nextsym = nextsym + 1
else
break
end
end
return nextsym
end
-- FIXME: Move to utils
-- Iterate over a chain of parameters, FIRST then PREF2, PREF3, ...,
-- inserting into LIST (newly created if omitted). Return LIST.
local function get_arg_chain(args, first, pref, list)
if not list then
list = {}
end
local val = args[first]
local i = 2
while val do
table.insert(list, val)
val = args[pref .. i]
i = i + 1
end
return list
end
-- FIXME: Move to utils
-- Set a chain of parameters, FIRST then PREF2, PREF3, ..., from LIST.
local function set_arg_chain(args, first, pref, list)
local param = first
local i = 2
for _, val in ipairs(list) do
args[param] = val
param = pref .. i
i = i + 1
end
end
local function normalize_form(form)
if type(form) == "table" and m_table.length(form) == 1 then
return form[1]
end
return form
end
-- For a given form in a conjugation table, we allow either strings or
-- two-element lists {RUSSIAN, TRANSLIT}, where TRANSLIT can be nil
-- (equivalent to a one-element list). When comparing them, we have to take
-- this into account.
local function forms_equal(form1, form2)
return m_table.deepEquals(normalize_form(form1), normalize_form(form2))
end
local function contains_form(forms, form)
for _, f in ipairs(forms) do
if forms_equal(f, form) then
return true
end
end
return false
end
-- FIXME: Move to utils
-- Append to the end of a chain of parameters, FIRST then PREF2, PREF3, ...,
-- if the value isn't already present.
local function append_to_arg_chain(args, first, pref, newval)
local nextarg = first
local i = 2
if newval == "" then
error("Internal error: attempt to insert blank value into arg chain")
end
while true do
if not args[nextarg] then break end
if forms_equal(args[nextarg], newval) then
return nil
end
nextarg = pref .. i
i = i + 1
end
args[nextarg] = newval
return nextarg
end
local function get_true_arg(arg, not_off_by_1)
-- We normally move all params down by one because the first param is the
-- verb type; so reflect this correctly if the arg is numeric and
-- not_off_by_1 isn't given
return (not_off_by_1 or type(arg) ~= "number") and arg or arg + 1
end
local function getarg(args, arg, default, paramdesc, not_off_by_1)
paramdesc = paramdesc or "Parameter " .. get_true_arg(arg, not_off_by_1)
default = default or "-"
--PAGENAME = mw.loadData("Module:headword/data").pagename
local NAMESPACE = mw.title.getCurrentTitle().nsText
return args[arg] or (NAMESPACE == "Template" and default) or error(paramdesc .. " has not been provided")
end
local function check_stressed_arg(val, arg)
-- don't consider suffixes
if not rfind(val, "^%-") and not com.is_nonsyllabic(val) and not com.is_stressed(val) then
error("Argument value " .. val .. " (parameter " .. get_true_arg(arg) .. ") must be stressed")
end
return val
end
local function get_stressed_arg(args, arg, default, paramdesc)
local retval = getarg(args, arg, default, paramdesc)
check_stressed_arg(retval, arg)
return retval
end
local function get_opt_stressed_arg(args, arg)
return args[arg] and get_stressed_arg(args, arg) or nil
end
local function check_unstressed_arg(val, arg)
if com.is_stressed(val) then
error("Argument value " .. val .. " (parameter " .. get_true_arg(arg) .. ") should not be stressed")
end
return val
end
local function get_unstressed_arg(args, arg, default, paramdesc)
local retval = getarg(args, arg, default, paramdesc)
check_unstressed_arg(retval, arg)
return retval
end
local function get_opt_unstressed_arg(args, arg)
return args[arg] and get_unstressed_arg(args, arg) or nil
end
local function no_stray_args(args, maxarg)
for i=(maxarg + 1), 20 do
if args[i] then
error("Value for argument " .. get_true_arg(i) .. " not allowed ("
.. args[i] .. " supplied)")
end
end
end
-- Extract a form spec (either a single string or a two-element table {RU, TR}
-- into the component Russian and transliterated components. Normally, if
-- an explicit manual translit wasn't given, the resulting translit will be
-- nil; but if ALWAYS_TRANSLIT is given, it will be auto-transliterated from
-- the Russian as needed.
local function extract_russian_tr(form, always_translit)
local ru, tr
if type(form) == "table" then
ru, tr = form[1], form[2]
else
ru = form
end
if not tr and always_translit then
tr = ru and com.translit(ru)
end
return ru, tr
end
local function strip_arg_status_prefix(arg)
if not arg then
return arg, ""
end
local subbed
arg, subbed = rsubb(arg, "^awkward%-", "")
if subbed then
return arg, "awkward-"
end
arg, subbed = rsubb(arg, "^none%-", "")
if subbed then
return arg, "none-"
end
return arg, ""
end
local function track(page)
m_debug.track("ru-verb/" .. page)
return true
end
-- Forward functions
local present_e_a
local present_e_b
local present_e_c
local present_je
local present_i
local make_reflexive
local make_pre_reform
local parse_and_stress_override
local handle_forms_and_overrides
local finish_generating_forms
local make_table
local all_verb_types = {
"pf", "pf-intr", "pf-refl",
"pf-impers", "pf-intr-impers", "pf-refl-impers",
"impf", "impf-intr", "impf-refl",
"impf-impers", "impf-intr-impers", "impf-refl-impers"}
-- Examples of alternatives in use:
-- past_m2: со́здал/созда́л, пе́редал/переда́л, о́тдал/отда́л, при́нялся/принялся́
-- past_m3: for verbs with three past masculine sg forms: за́нялся, заня́лся, занялс́я (заня́ться)
-- past_n2: да́ло, дал́о; вз́яло, взяло́
-- past_pl2: разобрали́сь (разобрали́)
-- past_m_short: short forms in 3a (исчез, сох, etc.)
-- past_f_short: short forms in 3a (исчезла, сохла, etc.)
-- past_n_short: short forms in 3a (исчезло, сохло, etc.)
-- past_pl_short: short forms in 3a (исчезли, сохли, etc.)
-- past_adv_parts:
-- тереть: тере́вши, тёрши, short: тере́в
-- умереть: умере́вши, у́мерши, short: умере́в
-- pres_adv_part: сыпля, сыпя, лёжа (лежать)
-- pres_2sg2: сыплешь, сыпешь
-- pres_3sg2: сыплет, сыпет
-- pres_1pl2: сыплем, сыпем
-- pres_2pl2: сыплете, сыпете
-- pres_3pl2: сыплют, сыпют
-- futr_2sg2: насыплешь, насыпешь
-- futr_3sg2: насыплет, насыпет
-- futr_1pl2: насыплем, насыпем
-- futr_2pl2: насыплете, насыпете
-- futr_3pl2: насыплют, насыпют
-- List of all main verb forms. Short forms (those ending in "_short")
-- must be listed after the corresponding non-short forms.
local all_main_verb_forms = {
-- present tense
"pres_1sg", "pres_2sg", "pres_3sg", "pres_1pl", "pres_2pl", "pres_3pl",
-- future tense
"futr_1sg", "futr_2sg", "futr_3sg", "futr_1pl", "futr_2pl", "futr_3pl",
-- present-future tense. The conjugation functions generate the
-- "present-future" tense instead of either the present or future tense,
-- since the same forms are used in the present imperfect and future
-- perfect. These forms are later copied into the present or future in
-- finish_generating_forms().
"pres_futr_1sg", "pres_futr_2sg", "pres_futr_3sg", "pres_futr_1pl", "pres_futr_2pl", "pres_futr_3pl",
-- imperative
"impr_sg", "impr_pl",
-- past
"past_m", "past_f", "past_n", "past_pl",
"past_m_short", "past_f_short", "past_n_short", "past_pl_short",
-- active participles
"pres_actv_part", "past_actv_part",
-- passive participles
"pres_pasv_part", "past_pasv_part",
-- adverbial participles
"pres_adv_part", "past_adv_part", "past_adv_part_short",
-- infinitive
"infinitive"
}
-- List of all verb forms. Each element is a list, where the first element
-- is the "main" form and the remainder are alternatives. The following
-- *MUST* hold:
-- 1. Forms must be given in the order they will appear in the outputted
-- table.
-- 2. Short forms (those ending in "_short") must be listed after the
-- corresponding non-short forms.
-- 3. For each person, e.g. '2sg', there must be the same number of
-- futr_PERSON, pres_PERSON and pres_futr_PERSON forms, and the alternative
-- forms must be listed in the same order.
--
-- FIXME!!! We should fix things so we no longer need to compute this table.
local all_verb_forms = {}
-- Compile all_verb_forms
for _, mainform in ipairs(all_main_verb_forms) do
local entry = {}
table.insert(entry, mainform)
for i=2,9 do
table.insert(entry, mainform .. i)
end
table.insert(all_verb_forms, entry)
end
local prop_aliases = {
pap="past_actv_part",
paptail="past_actv_part_tail",
paptailall="past_actv_part_tailall",
ppp="past_pasv_part",
ppptail="past_pasv_part_tail",
ppptailall="past_pasv_part_tailall",
prap="pres_actv_part",
praptail="pres_actv_part_tail",
praptailall="pres_actv_part_tailall",
prpp="pres_pasv_part",
prpptail="pres_pasv_part_tail",
prpptailall="pres_pasv_part_tailall",
padp="past_adv_part",
padptail="past_adv_part_tail",
padptailall="past_adv_part_tailall",
padp_short="past_adv_part_short",
padp_shorttail="past_adv_part_short_tail",
padp_shorttailall="past_adv_part_short_tailall",
pradp="pres_adv_part",
pradptail="pres_adv_part_tail",
pradptailall="pres_adv_part_tailall",
}
-- Table mapping "main" to the list of all forms in the series (e.g.
-- past_m, past_m2, past_m3, etc.). If a main form (e.g. past_m) is missing,
-- it needs to end up with a value of "", whereas the alternatives
-- (e.g. past_m2, past_m3) need to end up with a value of nil.
local main_to_all_verb_forms = {}
-- List of the main verb forms for the past.
local past_verb_forms = {"past_m", "past_f", "past_n", "past_pl"}
-- List of the main verb forms for the present.
local pres_verb_forms = {"pres_1sg", "pres_2sg", "pres_3sg",
"pres_1pl", "pres_2pl", "pres_3pl"}
-- List of the main verb forms for the future.
local futr_verb_forms = {"futr_1sg", "futr_2sg", "futr_3sg",
"futr_1pl", "futr_2pl", "futr_3pl"}
-- List of the main verb forms for the imperative.
local impr_verb_forms = {"impr_sg", "impr_pl"}
-- List of the main verb forms for participles.
local part_verb_forms = {"pres_actv_part", "past_actv_part",
"pres_pasv_part", "past_pasv_part",
"pres_adv_part", "past_adv_part", "past_adv_part_short"}
-- List of the main verb forms for present participles.
local pres_part_verb_forms = {"pres_actv_part", "pres_pasv_part",
"pres_adv_part"}
-- List of the main verb forms for past participles.
local past_part_verb_forms = {"past_actv_part", "past_pasv_part",
"past_adv_part", "past_adv_part_short"}
-- Compile main_to_all_verb_forms.
for _, proplist in ipairs(all_verb_forms) do
main_to_all_verb_forms[proplist[1]] = proplist
end
-- Map listing the forms to be displayed, and the verb forms used to generate
-- the displayed form, in order. For example, under past_m will be found
-- {"past_m_short", "past_m", "past_m2", "past_m3"} because those forms in
-- that order are displayed in the table under "masculine singular past".
local disp_verb_form_map = {}
for _, proplist in ipairs(all_verb_forms) do
local key = proplist[1]
-- if we find short forms, insert them at the beginning of the list for
-- the corresponding full forms. This requires that short forms are
-- listed in all_verb_forms after the corresponding full forms.
if rfind(key, "_short$") then
local full_key = rsub(key, "_short$", "")
-- short forms should occur in list after full forms
assert(#(disp_verb_form_map[full_key]) > 0)
-- build entry for full form, consisting first of the short forms,
-- in order, then the full forms, in order.
local new_entry = {}
for _, form in ipairs(proplist) do
table.insert(new_entry, form)
end
for _, form in ipairs(disp_verb_form_map[full_key]) do
table.insert(new_entry, form)
end
disp_verb_form_map[full_key] = new_entry
elseif rfind(key, "^pres_futr") then
-- skip these forms, not displayed
else
disp_verb_form_map[key] = mw.clone(proplist)
end
end
local all_verb_props = mw.clone(all_verb_forms)
local non_form_props = {"title", "perf", "intr", "impers", "categories", "notes", "internal_notes"}
for _, prop in ipairs(non_form_props) do
table.insert(all_verb_props, {prop})
end
-- Clone parent's args while also assigning nil to empty strings and splitting
-- arg sets (numeric args separated by "or"), assigning named args to
-- all all sets. Handle aliases in the process. Extract conjugation type
-- from the first arg of the arg set (for the initial arg set, this will be
-- arg 2 because arg 1 is the verb type), assigning to '.conj_type' of the
-- arg set. Return arg sets.
local function split_args_handle_aliases(frame)
local args = frame:getParent().args
local arg_sets = {}
local arg_set = {}
-- Verb type, e.g. impf, pf, impf-intr, pf-intr, impf-refl, pf-refl, etc.
-- Default to impf on the template page so that there is no script error.
local verb_type = getarg(args, 1, "impf", "Verb type (first parameter)")
local offset = 1
-- Find maximum-numbered arg, allowing for holes.
local max_arg = 1 -- needs to be 1 not 0 so template pages display ok
for pname in pairs(args) do
if type(pname) == "number" and pname > max_arg then
max_arg = pname
end
end
-- Now gather the numbered arguments.
for i=2,(max_arg + 1) do
local end_arg_set = false
if i == max_arg + 1 or args[i] == "or" then
end_arg_set = true
end
if end_arg_set then
table.insert(arg_sets, arg_set)
arg_set = {}
offset = i
else
arg_set[i - offset] = ine(args[i])
end
end
-- Insert named arguments into all arg sets, mapping aliases appropriately.
for pname, param in pairs(args) do
if type(pname) == "string" then
local argval = ine(param)
local mainprop, num = rmatch(pname, "^([a-z_]+)([0-9]*)$")
for i=1,#arg_sets do
if not mainprop then
arg_sets[i][pname] = argval
else
mainprop = prop_aliases[mainprop] or mainprop
arg_sets[i][mainprop .. num] = argval
end
end
end
end
-- If we're conjugating a suffix, insert a pseudoconsonant at the beginning
-- of all forms, so they get conjugated as if ending in a consonant.
-- We remove the pseudoconsonant later.
for i=1,#arg_sets do
local asif_prefix = (arg_sets[i]["asif_prefix"] or
arg_sets[i][2] and rfind(arg_sets[i][2], "^%-") and PSEUDOCONS)
if asif_prefix then
for k, v in pairs(arg_sets[i]) do
arg_sets[i][k] = rsub(v, "^%-", "-" .. asif_prefix)
end
end
end
-- Frob conjugation type.
for i=1,#arg_sets do
local arg1 = arg_sets[i][1]
local conj_type
if arg1 then
local orig_arg1 = arg1
-- This complex spec matches matches 3°a, 3oa, 4a1a, 6c1a,
-- 1a6a, 6a1as13, 6a1as14, 11*b, etc.
conj_type = rmatch(arg1, "^([0-9]+[*°o0-9abc]*[abc]s?1?[34]?)")
arg1 = rsub(arg1, "^[0-9]+[*°o0-9abc]*[abc]s?1?[34]?", "")
if not conj_type then
if rfind(arg1, "^irreg") then
conj_type = "irreg"
arg1 = rsub(arg1, "^irreg", "")
end
if not conj_type then
-- Check for Cyrillic, a common mistake (esp. Cyrillic а)
if rfind(orig_arg1, "[абцдеѣфгчийклмнопярстувшхызёюжэщьъ]") then
error("Unrecognized conjugation type (WARNING, has Cyrillic in it): " .. orig_arg1)
else
error("Unrecognized conjugation type: " .. orig_arg1)
end
end
end
-- The * variant is conventionally written e.g. 11*b; if found in
-- the conj_type, move it to the beginning of the remainder
if rfind(conj_type, "%*") then
conj_type = rsub(conj_type, "%*", "")
arg1 = "*" .. arg1
end
arg_sets[i][1] = arg1
else
local NAMESPACE = mw.title.getCurrentTitle().nsText
if NAMESPACE == "Template" and i == 1 then
conj_type = "1a"
else
error("Must specify argument 2 (conjugation type)")
end
end
arg_sets[i]["conj_type"] = conj_type
end
return arg_sets, verb_type
end
function export.do_generate_forms(arg_sets, verb_type, old)
local set1 = arg_sets[1]
local notes = get_arg_chain(set1, "notes", "notes")
local forms = {}
local categories = {}
if not m_table.contains(all_verb_types, verb_type) then
error("Invalid verb type " .. verb_type)
end
local data = {}
data.verb_type = verb_type
--impersonal
data.impers = rfind(verb_type, "impers")
data.intr = rfind(verb_type, "intr")
data.perf = rfind(verb_type, "^pf")
data.iter = set1["iter"]
data.nopres = set1["nopres"]
data.nopast = set1["nopast"]
data.nofutr = set1["nofutr"]
data.noimpr = set1["noimpr"]
if data.iter and data.perf then
error("Iterative verbs must be imperfective")
end
data.old = old
data.has_ppp = set1["has_ppp"]
data.has_prpp = set1["has_prpp"]
data.ppp_override = false
data.prpp_override = false
for _, form in ipairs(main_to_all_verb_forms["past_pasv_part"]) do
if set1[form] then
data.ppp_override = true
break
end
end
data.main_ppp_override = not not set1["past_pasv_part"]
for _, form in ipairs(main_to_all_verb_forms["pres_pasv_part"]) do
if set1[form] then
data.prpp_override = true
break
end
end
data.internal_notes = {}
local titles = {}
for i=1,#arg_sets do
local args = arg_sets[i]
local conj_type = args.conj_type
-- Support e.g. 3oa in place of 3°a
conj_type = rsub(conj_type, "o", "°")
track("conj-" .. conj_type) -- FIXME, convert to regular category
track("conj-" .. conj_type .. "/" .. verb_type) -- FIXME, convert to regular category
data.conj_type = conj_type
data.cat_conj_types = {conj_type}
if conj_type == "irreg" then
data.title = "irregular"
else
data.title = conj_type
end
if not conjugations[conj_type] then
error("Unknown conjugation type '" .. conj_type .. "'")
end
if args[2] then
local inf, tr = com.split_russian_tr(args[2])
if rfind(inf, "[тч]ься$") then
inf = rsub(inf, "ся$", "")
tr = com.strip_tr_ending(tr, "ся")
data.refl = true
elseif rfind(inf, "ти́?сь$") then
-- 7a (вы́вестись), 7b (вести́сь) or derivative of -йти́ (разойти́сь)
inf = rsub(inf, "сь$", "")
tr = com.strip_tr_ending(tr, "сь")
data.refl = true
elseif rfind(inf, "[тч]ь$") then
-- Allow monosyllabic infinitives to be specified without stress
if com.is_monosyllabic(inf) and not rfind(inf, "^%-") then
inf, tr = com.make_ending_stressed(inf, tr)
end
end
if tr then
args[2] = inf .. "//" .. tr
else
args[2] = inf
end
end
if data.refl and data.intr then
error("Can't specify -intr with reflexive verbs")
end
if data.has_ppp or data.has_prpp then
if data.refl then
error("Can't specify has_ppp=y or has_prpp=y with reflexive verbs")
end
if not data.intr then
error("Can only specify has_ppp=y or has_prpp=y with intransitive verbs")
end
end
data.shouldnt_have_ppp = data.refl or not data.has_ppp and data.intr
data.shouldnt_have_prpp = data.refl or not data.has_prpp and data.intr
if data.ppp_override and data.shouldnt_have_ppp then
error("Shouldn't specify past passive participle with reflexive or intransitive verbs, if it's needed use has_ppp=y")
elseif data.perf and not data.shouldnt_have_ppp and not data.ppp_override then
-- possible omissions
track("perfective-no-ppp")
end
if data.prpp_override and data.shouldnt_have_prpp then
error("Shouldn't specify present passive participle with reflexive or intransitive verbs, if it's needed use has_prpp=y")
end
-- Call conjugation function. It will return a table of forms
-- as if it's the first arg set. If it is in fact the first
-- arg set, we just use the table directly (we may destructively
-- modify it if there are later arg sets, but this is OK because
-- no one else but us uses the table). Otherwise we need to
-- append the values from the table to those of the previous
-- arg sets.
local arg_set_forms = conjugations[conj_type](args, data)
if i == 1 then
forms = arg_set_forms
else
for _, all_forms in pairs(main_to_all_verb_forms) do
for _, form in ipairs(all_forms) do
if arg_set_forms[form] then
append_to_arg_chain(forms, all_forms[1], all_forms[1],
arg_set_forms[form])
end
end
end
end
m_table.insertIfNot(titles, data.title)
if conj_type == "irreg" then
table.insert(categories, "Russian irregular verbs")
end
-- For irregular verbs, if the verb didn't set a specific cat_conj_type,
-- it will be the same as the conj_type and be "irreg". In that case,
-- replace it with the title, which might be a proper conjugation type
-- like 4a or 8c/b (and remove anything starting with a slash, to
-- account for cases like 8c/b). After doing this, the cat_conj_type
-- might still begin with "irreg" (for sufficiently irregular verbs that
-- they can't be assigned to any of the normal classes), in which case
-- we don't create a class for the verb beyond "Russian irregular verbs"
-- (set above).
if data.cat_conj_types[1] == "irreg" then
data.cat_conj_types = {rsub(rsub(data.title, "/.*", ""), "[*⑨]", "")}
end
for _, cat_conj_type in ipairs(data.cat_conj_types) do
if not rmatch(cat_conj_type, "^irreg") then
local class_num = rmatch(cat_conj_type, "^([0-9]+)")
assert(class_num and class_num ~= "")
table.insert(categories, "Russian class " .. class_num .. " verbs")
table.insert(categories, "Russian class " .. cat_conj_type .. " verbs")
end
end
end
data.title = "class " .. table.concat(titles, " // ") ..
(data.perf and " perfective" or " imperfective") ..
(data.refl and " reflexive" or data.intr and " intransitive" or " transitive") ..
(data.impers and " impersonal" or "") ..
(data.iter and " iterative" or "")
-- Perfective/imperfective
if data.perf then
table.insert(categories, "Russian perfective verbs")
else
table.insert(categories, "Russian imperfective verbs")
end
handle_forms_and_overrides(set1, forms, data)
local function remove_pseudo(str)
local toremove = set1["asif_prefix"] or PSEUDOCONS
if str == nil then
return str
end
str = rsub(str, "^%-" .. toremove, "-")
-- also handle prefix after space, e.g. in futures
str = rsub(str, " %-" .. toremove, " -")
return str
end
-- Remove pseudoconsonant we may have inserted; if no ending, insert
-- "(no suffix)".
for k in pairs(forms) do
if forms[k] == "-" .. PSEUDOCONS or type(forms[k] == "table") and forms[k][1] == "-" .. PSEUDOCONS then
-- Make the translit empty.
forms[k] = {"(no suffix)", ""}
else
if type(forms[k]) == "table" then
forms[k][1] = remove_pseudo(forms[k][1])
forms[k][2] = remove_pseudo(forms[k][2])
else
forms[k] = remove_pseudo(forms[k])
end
end
end
-- Catch errors in verb arguments that lead to the infinitive not matching
-- page title, but only in the main namespace.
local NAMESPACE = mw.title.getCurrentTitle().nsText
if NAMESPACE == "" then
local PAGENAME = mw.loadData("Module:headword/data").pagename
for _, form in ipairs(main_to_all_verb_forms["infinitive"]) do
local inf = extract_russian_tr(forms[form])
if inf then
inf, _ = m_table_tools.separate_notes(inf) -- remove any footnote symbols (e.g. грясти́)
local inf_noaccent = com.remove_accents(inf)
if inf ~= "-" then
if data.refl then
if rfind(inf_noaccent, "и$") then
inf_noaccent = inf_noaccent .. "сь"
inf = inf .. "сь"
else
inf_noaccent = inf_noaccent .. "ся"
inf = inf .. "ся"
end
end
if inf_noaccent ~= PAGENAME then
error("Infinitive " .. inf .. " doesn't match pagename " ..
PAGENAME)
end
end
end
end
end
-- Reflexive/intransitive/transitive
if set1["reflex_stress"] then
track("reflex-stress")
end
if data.refl then
local reflex_stress = set1["reflex_stress"] or data.default_reflex_stress -- "ся́"
make_reflexive(forms, reflex_stress and reflex_stress ~= "n" and
reflex_stress ~= "no")
table.insert(categories, "Russian reflexive verbs")
elseif data.intr then
table.insert(categories, "Russian intransitive verbs")
else
table.insert(categories, "Russian transitive verbs")
end
-- Impersonal
if data.impers then
table.insert(categories, "Russian impersonal verbs")
end
-- Iterative
if data.iter then
table.insert(categories, "Russian iterative verbs")
end
if data.old then
make_pre_reform(forms)
end
finish_generating_forms(forms, data)
return forms, data.title, data.perf, data.intr or data.refl, data.impers, categories, notes, data.internal_notes
end
local function fetch_forms(forms)
local function fetch_one_form(form)
local val = forms[form]
local ru, tr
if type(val) == "table" then
ru, tr = val[1], val[2]
elseif type(val) == "string" and val ~= "" and val ~= "-" then
ru = val
end
if not ru then
return nil
end
local ruentry = m_table_tools.get_notes(ru)
local trentry, trnotes
if tr then
trentry, trnotes = m_table_tools.get_notes(tr)
end
-- There shouldn't be any links.
-- ruentry = m_links.remove_links(ruentry)
-- There shouldn't be any vertical bars.
-- ruentry = rsub(ruentry, "|", "<!>")
-- if trentry then
-- trentry = rsub(trentry, "|", "<!>")
-- end
return trentry and ruentry .. "//" .. trentry or ruentry
end
local vals = {}
for _, proplist in ipairs(all_verb_forms) do
local vallist = {}
local propname = proplist[1]
if not rfind(propname, "^pres_futr") then
for _, prop in ipairs(proplist) do
local val = fetch_one_form(prop)
if val then
table.insert(vallist, val)
end
end
if #vallist > 0 then
table.insert(vals, propname .. "=" .. table.concat(vallist, ","))
end
end
end
return table.concat(vals, "|")
end
function export.generate_forms(frame)
local arg_sets, verb_type = split_args_handle_aliases(frame)
local old = frame.args["old"] or arg_sets[1]["old"]
local forms = export.do_generate_forms(arg_sets, verb_type, old)
return fetch_forms(forms)
end
-- The main entry point.
-- This is the only function that can be invoked from a template.
function export.show(frame)
local arg_sets, verb_type = split_args_handle_aliases(frame)
local old = frame.args["old"] or arg_sets[1]["old"]
local arg_sets_clone
if test_new_ru_verb_module then
-- arg_sets may be modified by do_generate_forms()
arg_sets_clone = mw.clone(arg_sets)
end
local forms, title, perf, intr, impers, categories, notes, internal_notes =
export.do_generate_forms(arg_sets, verb_type, old)
-- Test code to compare existing module to new one.
if test_new_ru_verb_module then
local m_new_ru_verb = require("Module:User:Benwing2/ru-verb")
local newforms, newtitle, newperf, newintr, newimpers, newcategories, newnotes, newinternal_notes =
m_new_ru_verb.do_generate_forms(arg_sets_clone, verb_type, old)
local vals = mw.clone(forms)
vals.title = title
vals.perf = perf
vals.intr = intr
vals.impers = impers
vals.categories = categories
vals.notes = notes
vals.internal_notes = internal_notes
local newvals = mw.clone(newforms)
newvals.title = newtitle
newvals.perf = newperf
newvals.intr = newintr
newvals.impers = newimpers
newvals.categories = newcategories
newvals.notes = newnotes
newvals.internal_notes = newinternal_notes
local difconj = false
for _, proplist in ipairs(all_verb_props) do
for _, prop in ipairs(proplist) do
local val = vals[prop]
local newval = newvals[prop]
-- deal with impedance mismatch between old style (plain string)
-- and new style (Russian/translit array), and empty string vs. nil
if not m_table.contains(non_form_props, prop) then
if type(val) == "string" then val = {val} end
if val and val[1] == "" then val = nil end
if type(newval) == "string" then newval = {newval} end
if newval and newval[1] == "" then newval = nil end
end
-- Ignore changes in pres_futr_*, which aren't displayed
if not forms_equal(val, newval) and not rfind(prop, "^pres_futr") then
-- Uncomment this to display the particular case and
-- differing forms.
--error(prop .. " " .. (val and concat_vals(val) or "nil") .. " || " .. (newval and concat_vals(newval) or "nil"))
difconj = true
break
end
end
end
track(difconj and "different-conj" or "same-conj")
end
return make_table(forms, title, perf, intr, impers, notes, internal_notes, old) .. m_utilities.format_categories(categories, lang)
end
--[=[
Functions for working with stems, paradigms, Russian/translit
]=]
-- Combine a stem with optional translit with an ending and possibly a foonote
-- symbol (which may be a tuple {RUNOTES, TRNOTES}), returning a tuple
-- {RUSSIAN, TR}.
local function combine(stem, tr, ending, note)
if not ending or ending == "-" then
return nil
end
local arg_status
ending, arg_status = strip_arg_status_prefix(ending)
if stem ~= "" and com.is_stressed(ending) then
stem, tr = com.make_unstressed_once(stem, tr)
end
stem = arg_status .. stem
if not note then
return com.concat_russian_tr(stem, tr, ending, nil, "dopair")
else
local runotes, trnotes = extract_russian_tr(note)
local ruending, trending = com.concat_russian_tr(ending, nil, runotes, trnotes)
return com.concat_russian_tr(stem, tr, ruending, trending, "dopair")
end
end
-- Set an individual form PARAM in FORMS with value based on stem STEM (with
-- optional translit TR), ENDINGS (either a single string or a list of strings)
-- and NOTE (nil, a string, or a tuple {RUSSIAN, TR}). If there are multiple
-- endings listed, they will go successively into PARAM, PARAM2, etc.
-- (e.g. past_m, past_m2, etc.).
local function set_form(forms, param, stem, tr, endings, note)
if type(endings) ~= "table" then
endings = {endings}
end
local entries = {}
for _, val in ipairs(endings) do
m_table.insertIfNot(entries, combine(stem, tr, val, note))
end
set_arg_chain(forms, param, param, entries)
end
-- Append to an individual form PARAM in FORMS with value based on stem STEM
-- (with optional translit TR), ENDINGS (either a single string or a list of
-- strings) and NOTE (nil, a string, or a tuple {RUSSIAN, TR}). If there are
-- multiple endings listed, they will go successively into PARAM, PARAM2, etc.
-- (e.g. past_m, past_m2, etc.), provided there are no existing forms already
-- present. Duplicate forms aren't inserted.
local function append_form(forms, param, stem, tr, endings, note)
if type(endings) ~= "table" then
endings = {endings}
end
for _, val in ipairs(endings) do
append_to_arg_chain(forms, param, param, combine(stem, tr, val, note))
end
end
local function append_pres_futr(forms, stem, tr,
sg1, sg2, sg3, pl1, pl2, pl3, note)
append_form(forms, "pres_futr_1sg", stem, tr, sg1, note)
append_form(forms, "pres_futr_2sg", stem, tr, sg2, note)
append_form(forms, "pres_futr_3sg", stem, tr, sg3, note)
append_form(forms, "pres_futr_1pl", stem, tr, pl1, note)
append_form(forms, "pres_futr_2pl", stem, tr, pl2, note)
append_form(forms, "pres_futr_3pl", stem, tr, pl3, note)
end
local function append_participles_2stem(forms,
pres_stem, pres_tr, past_stem, past_tr,
pres_actv, pres_pasv, pres_adv, past_actv, past_adv, past_adv_short,
pres_note, past_note)
append_form(forms, "pres_actv_part", pres_stem, pres_tr, pres_actv, pres_note)
append_form(forms, "pres_pasv_part", pres_stem, pres_tr, pres_pasv, pres_note)
append_form(forms, "pres_adv_part", pres_stem, pres_tr, pres_adv, pres_note)
append_form(forms, "past_actv_part", past_stem, past_tr, past_actv, past_note)
append_form(forms, "past_adv_part", past_stem, past_tr, past_adv, past_note)
append_form(forms, "past_adv_part_short", past_stem, past_tr, past_adv_short, past_note)
end
local function append_participles(forms, stem, tr,
pres_actv, pres_pasv, pres_adv, past_actv, past_adv, past_adv_short, note)
append_participles_2stem(forms, stem, tr, stem, tr,
pres_actv, pres_pasv, pres_adv, past_actv, past_adv, past_adv_short, note, note)
end
local function set_ppp(forms, stem, tr, ending, note)
set_form(forms, "past_pasv_part", stem, tr, ending, note)
end
local function append_ppp(forms, stem, tr, ending, note)
append_form(forms, "past_pasv_part", stem, tr, ending, note)
end
local function append_imper(forms, stem, tr, sg, pl, note)
append_form(forms, "impr_sg", stem, tr, sg, note)
append_form(forms, "impr_pl", stem, tr, pl, note)
end
local function set_past(forms, stem, tr, m, f, n, pl, note)
set_form(forms, "past_m", stem, tr, m, note)
set_form(forms, "past_f", stem, tr, f, note)
set_form(forms, "past_n", stem, tr, n, note)
set_form(forms, "past_pl", stem, tr, pl, note)
end
local function append_past(forms, stem, tr, m, f, n, pl, note)
append_form(forms, "past_m", stem, tr, m, note)
append_form(forms, "past_f", stem, tr, f, note)
append_form(forms, "past_n", stem, tr, n, note)
append_form(forms, "past_pl", stem, tr, pl, note)
end
-- Prepend a possibly-stressed prefix to all forms; if prefix is stressed,
-- destress the forms before prepending. FIXME: Should support explicit
-- manual translit.
local function prepend_prefix(forms, prefix, pre_two_cons_prefix)
pre_two_cons_prefix = pre_two_cons_prefix or prefix
local stressed_prefix = com.is_stressed(prefix)
for key, form in pairs(forms) do
local ru, tr = extract_russian_tr(form)
if tr then
error("Explicit manual translit not yet supported")
end
-- check for empty string, dashes and nil's
if ru and ru ~= "" and ru ~= "-" then
if stressed_prefix then
ru = com.make_unstressed(ru)
end
if rfind(ru, "^[" .. com.cons .. "][" .. com.cons .. "]") then
forms[key] = pre_two_cons_prefix .. ru
else
forms[key] = prefix .. ru
end
end
end
end
-- Apply regex substitution FROM -> TO to all forms. FIXME: Should support
-- explicit manual translit.
local function rsub_forms(forms, from, to)
for key, form in pairs(forms) do
local ru, tr = extract_russian_tr(form)
if tr then
error("Explicit manual translit not yet supported")
end
-- check for empty string, dashes and nil's
if ru and ru ~= "" and ru ~= "-" then
forms[key] = rsub(ru, from, to)
end
end
end
local variant_to_title = {
["[(2)]"] = "[②]",
["(2)"] = "②",
["[(3)]"] = "[③]",
["(3)"] = "③",
["[(4)]"] = "[④]",
["(4)"] = "④",
["[(5)]"] = "[⑤]",
["(5)"] = "⑤",
["[(6)]"] = "[⑥]",
["(6)"] = "⑥",
["[(7)]"] = "[⑦]",
["(7)"] = "⑦",
["[(8)]"] = "[⑧]",
["(8)"] = "⑧",
["(9)"] = "⑨",
["щ"] = "(-щ-)",
["ё"] = "(-ё-)",
["о"] = "(-о-)",
["жд"] = "(-жд-)",
}
local function prepare_past_stress_indicator(past_stress)
if not past_stress or past_stress == "a" then
return ""
end
past_stress = rsub(past_stress, "%(1%)", "①")
past_stress = rsub(past_stress, "(.),%1①", "%1[①]")
past_stress = rsub(past_stress, "(.)①,%1", "%1[①]")
past_stress = rsub(past_stress, "''", "''")
past_stress = rsub(past_stress, "-nd", "")
past_stress = rsub(past_stress, "-bd", "")
return "/" .. past_stress
end
local function parse_variants(data, variants, allowed)
-- Need to set these to nil in case of multiple arg sets
data.imper_variant = nil
data.var4 = nil
data.var5 = nil
data.var6 = nil
data.ppp = nil
data.var9 = nil
data.shch = nil
data.yo = nil
data.o = nil
data.zhd = nil
data.star = nil
variants = variants or ""
local variant_title = ""
if variants ~= "" then -- short-circuit the most common case
-- Only recognize * variant for long-variant prefix at the beginning
-- of the variant code block (where it gets moved if it's in the
-- middle of the conjugation type, as it normally is) because a *
-- also occurs in b*, a past stress variant code.
if rfind(variants, "^%*") then
-- Specify that the present/future tense has extra -о in the prefix:
-- types 9*b (e.g. растере́ть, futr_1sg разотру́) and 11*b (e.g. изли́ть,
-- futr_1sg изолью́). It can also occur with type 7*b (in -че́сть,
-- e.g. счесть, сочту́; расче́сть, разочту́) and type 8*b (in -же́чь, e.g.
-- сжечь, сожгу́) but these are always irregular and require the
-- present tense to be specified explicitly. It can also occur
-- with type 14*b (e.g. размя́ть, разомну́; сжать, сожну́; подожа́ть, подожму́),
-- but for these verbs the present tense is unpredictable and
-- must be specified explicitly.
--
-- This can also occur where the extra -о occurs in the infinitive
-- and past, but not the present tense: type 5*c (in -гна́ть, e.g.
-- согна́ть, сгоню́; разогна́ться, разгоню́сь), type 6*c (in -стла́ть, e.g.
-- подостла́ть, подстелю́; разостла́ть, расстелю́), type 6°*c
-- (in -зва́ть, -бра́ть, -дра́ть, e.g. подозва́ть, подзову́; разобра́ться, разберу́сь);
-- but these are always irregular and require the present tense
-- to be specified explicitly.
if not m_table.contains(allowed, "*") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.star = true
variants = rsub(variants, "^*", "")
end
-- Allow brackets around both 5 and 6, e.g. [(5)(6)]
variants = rsub(variants, "%[(%([56]%))(%([56]%))%]", "[%1][%2]")
-- Handle all remaining variants. We do this using an rsub() function,
-- where we pull out, parse and remove each variant in turn.
variants = rsub(variants, "(%[?%(?[23456789ёощийьж+][дp]?%)?%]?)", function(var)
if m_table.contains({"(2)", "[(2)]", "(3)", "[(3)]", "и", "й", "ь"}, var) then
if data.imper_variant then
error("Saw two imperative variants " .. data.imper_variant ..
" and " .. var)
end
local is_23 = m_table.contains({"(2)", "[(2)]", "(3)", "[(3)]"}, var)
if is_23 and not m_table.contains(allowed, "23") or
not is_23 and not m_table.contains(allowed, "и") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.imper_variant = var
elseif m_table.contains({"(4)", "[(4)]"}, var) then
if data.var4 then
error("Saw two variant-4 specs " .. data.var4 .. " and " .. var)
end
if not m_table.contains(allowed, "4") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.var4 = var == "(4)" and "req" or "opt"
elseif m_table.contains({"(5)", "[(5)]"}, var) then
if data.var5 then
error("Saw two variant-5 specs " .. data.var5 .. " and " .. var)
end
if not m_table.contains(allowed, "5") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.var5 = var == "(5)" and "req" or "opt"
elseif m_table.contains({"(6)", "[(6)]"}, var) then
if data.var6 then
error("Saw two variant-6 specs " .. data.var6 .. " and " .. var)
end
if not m_table.contains(allowed, "6") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.var6 = var == "(6)" and "req" or "opt"
elseif m_table.contains({"(7)", "[(7)]", "(8)", "[(8)]", "+p"}, var) then
if data.shouldnt_have_ppp then
error("Shouldn't specify past passive participle with reflexive or intransitive verbs, if it's needed use has_ppp=y")
end
if data.ppp then
error("Saw two past passive participle specs " .. data.ppp .. " and " .. var)
end
if m_table.contains({"(7)", "[(7)]"}, var) and not m_table.contains(allowed, "7") or
m_table.contains({"(8)", "[(8)]"}, var) and not m_table.contains(allowed, "8") or
var == "+p" and not m_table.contains(allowed, "+p") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.ppp = var
elseif var == "(9)" then
if data.var9 then
error("Saw (9) twice")
end
if not m_table.contains(allowed, "9") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.var9 = true
elseif var == "щ" then
-- specify that the 1sg pres/futr and past passive participle
-- of class 4/5/6 verbs iotate -т to -щ instead of -ч; cf.
-- похи́тить (похи́щу) (4a), защити́ть (защищу́) (4b),
-- поглоти́ть (поглощу́) (4c), клевета́ть (клевещу́) (6c)
if data.shch then
error("Saw щ twice")
end
if not m_table.contains(allowed, "щ") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.shch = "щ"
elseif var == "ё" then
-- specify that the past passive participle has ё instead of е
if data.yo then
error("Saw ё twice")
end
if not m_table.contains(allowed, "ё") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.yo = true
elseif var == "о" then
-- specify that the past passive participle has о instead of е
-- NOTE: Not currently allowed as a user-specifiable variant
if data.o then
error("Saw о twice")
end
if not m_table.contains(allowed, "о") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.o = true
elseif var == "жд" then
-- specify that the past passive participle of class 4/5/6 verbs
-- iotates -д to -жд instead of -ж
if data.zhd then
error("Saw жд twice")
end
if not m_table.contains(allowed, "жд") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.zhd = true
else
error("Unrecognized variant spec: " .. var)
end
variant_title = variant_title .. (variant_to_title[var] or "")
return ""
end)
variant_title = rsub(variant_title, "%[⑤%]%[⑥%]", "[⑤⑥]")
end
if variants ~= "" and not m_table.contains(allowed, "past") then
error("Past stress " .. variants .. " not allowed for this verb class")
end
if data.yo and not data.ppp then
error("Variant ё specified without calling for past passive participle")
end
if data.o and not data.ppp then
error("Variant о specified without calling for past passive participle")
end
if data.zhd and not data.ppp then
error("Variant жд specified without calling for past passive participle")
end
if data.perf and not data.ppp and not data.ppp_override and not data.shouldnt_have_ppp and not data.impers then
error("For perfective transitive verbs, need to specify past passive participle by variant or override; use |ppp=- if no such participle")
end
data.past_stress = variants == "" and "a" or rsub(variants, "/", "")
data.title = data.title ..
prepare_past_stress_indicator(data.past_stress) ..
variant_title
if data.star then
data.title = rsub(data.title, "^([0-9]+°?)", "%1*")
end
-- If there's an override of past_pasv_part, generate the normal participle
-- so we can determine whether the override is irregular. But set a flag
-- so we erase any automatically generated past passive participles that
-- aren't overridden. This happens for example in обнять, where there are
-- two automatically generated past passive participles but a single
-- ppp=о́внятый override.
if not data.ppp and data.main_ppp_override then
data.ppp = "+p"
data.ppp_auto_generated = true
end
end
local function set_past_by_stress(forms, past_stresses, prefix, prefixtr, base,
basetr, args, data, no_pastml, note)
-- If there isn't manual translit for the prefix, we need to supply it
-- if there's manual translit for the base, because we often concatenate
-- prefix to the base.
local prefixtr = prefixtr or basetr and com.translit(prefix)
for _, past_stress in ipairs(rsplit(past_stresses, ",")) do
local pastml = no_pastml and "" or "л"
local stressed_prefix, stressed_prefixtr
if prefix == "пере" then
stressed_prefix = "пе́ре"
stressed_prefixtr = "pe" .. AC .. "re"
elseif prefix == "раз" then
stressed_prefix = "ро́з"
stressed_prefixtr = "ro" .. AC .. "z"
elseif prefix == "рас" then
-- Does this ever occur?
stressed_prefix = "ро́с"
stressed_prefixtr = "ro" .. AC .. "s"
elseif prefix == "ра" and rfind(base, "^[сз]") then
-- Type 9/11/14/16 with automatically split prefix; may never happen.
stressed_prefix = "ро́"
stressed_prefixtr = "ro" .. AC
else
stressed_prefix, stressed_prefixtr =
com.make_ending_stressed(prefix, prefixtr)
end
-- Normally the base is stressed and the prefix isn't, but it could
-- be the other way around, e.g. in запереть and запереться, where
-- the stress on the prefix is used to get prefix-stressed participles.
-- To deal with this, we usually combine base and prefix unchanged,
-- but in combination with stressed_prefix we always want an unstressed
-- base, and when a stressed -ся́ is called for, we want both of them
-- unstressed.
local ubase, ubasetr = com.make_unstressed(base, basetr)
local uprefix, uprefixtr = com.make_unstressed(prefix, prefixtr)
-- If the prefix is stressed (вы́-), we need to use the unstressed base to avoid getting double stress.
local prefixbase = com.is_stressed(prefix) and prefix .. ubase or prefix .. base
local prefixbasetr = basetr and (com.is_stressed(prefix) and prefixtr .. ubasetr or prefixtr .. basetr)
local stressed_prefix_ubase = stressed_prefix .. ubase
local stressed_prefix_ubasetr = ubasetr and stressed_prefixtr .. ubasetr
local uprefixubase = uprefix .. ubase
local uprefixubasetr = ubasetr and uprefixtr .. ubasetr
if past_stress == "a" then
-- (/под/пере/при/по)забы́ть, раздобы́ть, (/пере/по)забы́ться
append_past(forms, prefixbase, prefixbasetr, pastml,
"ла", "ло", "ли", note)
elseif past_stress == "a(1)" then
-- вы́дать, вы́быть, etc.; also проби́ть with the meaning
-- "to strike (of a clock)" (which is a(1),a or similar)
append_past(forms, stressed_prefix_ubase,
stressed_prefix_ubasetr, pastml, {}, "ло", "ли", note)
-- Retraction to prefix doesn't happen in feminine singular, see the
-- bottom of page 81 of Zaliznyak's 1980 grammar.
append_past(forms, prefixbase, prefixbasetr, {}, "ла", {}, {}, note)
elseif past_stress == "b" then
append_past(forms, prefixbase, prefixbasetr, pastml,
"ла́", "ло́", "ли́", note)
elseif past_stress == "b*" then
if not data.refl then
error("Only reflexive verbs can take past stress variant " .. past_stress)
end
-- See comment in type c''. We want to see whether we actually
-- added an argument, and if so, where.
local argset = append_to_arg_chain(forms, "past_m", "past_m",
combine(uprefixubase, uprefixubasetr, pastml .. (note or "")))
if argset and not args[argset] and not data.impers then
data.default_reflex_stress = "ся́"
end
append_past(forms, prefixbase, prefixbasetr, {}, "ла́", "ло́", "ли́", note)
elseif past_stress == "c" then
-- изда́ть, возда́ть, сдать, пересозда́ть, воссозда́ть, надда́ть, наподда́ть, etc.
-- быть, избы́ть, сбыть
-- клясть, закля́сть
append_past(forms, prefixbase, prefixbasetr, pastml, "ла́", "ло", "ли", note)
elseif past_stress == "c(1)" then
-- прибы́ть, убы́ть
-- прокля́сть
-- also, c(1),c:
-- зада́ть, обда́ть, отда́ть, подда́ть, переда́ть (пе́редал), преда́ть, прода́ть, разда́ть (ро́здал), созда́ть, etc.
-- отбы́ть, побы́ть, пробы́ть
-- also, c,c(1):
-- добы́ть
-- Because the prefix may vary depending on stress (esp. for
-- раздать [ро́здал/раздала́]), we need to separate the endings that
-- take the stressed prefix and those that take the unstressed
-- prefix with stressed ending.
append_past(forms, stressed_prefix_ubase, stressed_prefix_ubasetr,
pastml, {}, "ло", "ли", note)
append_past(forms, prefixbase, prefixbasetr, {}, "ла́", {}, {}, note)
elseif past_stress == "c'" then
-- дать
--same with "взять"
append_past(forms, prefixbase, prefixbasetr,
pastml, "ла́", {"ло", "ло́"}, "ли", note)
elseif past_stress == "c''" or past_stress == "c''-nd" or past_stress == "c''-bd" then
if not data.refl then
error("Only reflexive verbs can take past stress variant " .. past_stress)
end
-- c'' (-ся́ dated): all verbs in -да́ться; избы́ться, сбы́ться; all verbs in -кля́сться
-- c''-nd (-ся́ not dated): various verbs in -ня́ться per Zaliznyak
-- c''-bd (-ся́ becoming dated): various verbs in -ня́ться per ruwikt
local note_symbol = past_stress == "c''-nd" and "" or
next_note_symbol(data)
append_past(forms, prefixbase, prefixbasetr,
pastml, "ла́", {"ло́", "ло"}, {"ли́", "ли"})
-- We want to see whether we actually added an argument, and if
-- so, where.
local argset = append_to_arg_chain(forms, "past_m", "past_m",
combine(uprefixubase, uprefixubasetr, pastml .. note_symbol .. (note or "")))
-- Only display the internal note and set the default reflex
-- stress if the form with the note will be displayed (i.e. not
-- impersonal, and no override of this form). FIXME: We should
-- have a more general mechanism to check for this.
if not args[argset] and not data.impers then
local note = past_stress == "c''" and note_symbol .. " Dated." or
past_stress == "c''-bd" and note_symbol .. " Becoming dated." or
nil
if note then
m_table.insertIfNot(data.internal_notes, note)
end
data.default_reflex_stress = "ся́"
end
elseif past_stress == "c''(1)" then
-- запере́ться
-- See comment in type c''. We want to see whether we actually
-- added an argument, and if so, where.
local argset = append_to_arg_chain(forms, "past_m", "past_m",
combine(uprefixubase, uprefixubasetr, pastml .. (note or "")))
if argset and not args[argset] and not data.impers then
data.default_reflex_stress = "ся́"
end
append_past(forms, prefixbase, prefixbasetr, {}, "ла́", "ло́", "ли́", note)
append_past(forms, stressed_prefix_ubase, stressed_prefix_ubasetr,
pastml, {}, "ло", "ли", note)
else
error("Unrecognized past-stress value " .. past_stress .. ", should be a, a(1), b, b*, c, c(1), c', c'', c''-nd, c''-bd, c''(1) or comma-separated list")
end
end
end
-- Split a verb stem into a possibly multisyllabic prefix (пере-, переиз-,
-- воссоз-, повы́-, etc.) and a single-syllable main verb (-тер-, -ли́-, -гре́-,
-- etc.). Normally the splitting is done simply by looking for alternating
-- vowel/consonant sequences, meaning that e.g. разгре́ will be split as
-- ра + згре́ and растер will be split as ра + стер. For most purposes, this
-- doesn't matter, but for the * variant it does; in that case, if it is
-- known that the main verb base always begins with a single consonant,
-- specify SINGLE_CONS_BASE and then e.g. растер will be split as рас + тер.
local function split_monosyllabic_main_verb(ru, tr, single_cons_base)
local rusyl, trsyl = com.split_syllables(ru, tr)
local last_ru = rusyl[#rusyl]
local last_tr = trsyl and trsyl[#trsyl]
table.remove(rusyl, #rusyl)
local prefix_ru = table.concat(rusyl, "")
local prefix_tr
if trsyl then
table.remove(trsyl, #trsyl)
prefix_tr = table.concat(trsyl, "")
end
if single_cons_base then
local cons_to_move, rest = rmatch(last_ru, "^([" .. com.cons .. "]+)([" .. com.cons .. "].*)$")
if cons_to_move then
prefix_ru = prefix_ru .. cons_to_move
last_ru = rest
end
if last_tr then
cons_to_move, rest = rmatch(last_tr, "^([" .. com.tr_cons .. "]+)([" .. com.tr_cons .. "].*)$")
if cons_to_move then
prefix_tr = prefix_tr .. cons_to_move
last_tr = rest
end
end
end
return prefix_ru, prefix_tr, last_ru, last_tr
end
local function split_known_main_verb(arg, mains)
-- Given an argument (which may be RUSSIAN//TR), split the prefix from
-- the main verb, which should be one of the verbs in MAINS (which can be
-- a -- single verb or a list of verbs, but in either case all verbs
-- need to be stressed). This correctly handles stressed and unstressed
-- prefixes.
local stem, tr = com.split_russian_tr(arg)
if type(mains) ~= "table" then
mains = {mains}
end
for _, main in ipairs(mains) do
assert(com.is_stressed(main))
if rfind(stem, main .. "$") then
stem, tr = com.strip_ending(stem, tr, main)
if com.is_stressed(stem) then
error("Two stresses in " .. arg)
end
return stem, tr, main, nil
end
main = com.make_unstressed_once(main)
if rfind(stem, main .. "$") then
stem, tr = com.strip_ending(stem, tr, main)
if com.is_unstressed(stem) then
error("No stresses in " .. arg)
end
return stem, tr, main, nil
end
end
if #mains == 1 then
error("Argument " .. arg .. " doesn't end in " .. mains[1])
else
error("Argument " .. arg .. " doesn't end in any of " .. table.concat(mains, ","))
end
end
local function construct_long_prefix_variant(prefix)
if rfind(prefix, "рас$") then
return rsub(prefix, "рас$", "разо")
end
if rfind(prefix, "ис$") then
return rsub(prefix, "ис$", "изо")
end
if rfind(prefix, "вс$") then
return rsub(prefix, "вс$", "взо")
end
return prefix .. "о"
end
local function append_imper_by_variant(forms, stem, tr, variant, verbclass, note)
local vowel_stem = is_vowel_stem(stem)
local stress = rmatch(verbclass, "([abc])$")
if not stress then
error("Unrecognized verb class '" .. verbclass .. "', should end with a, b or c")
end
local longend = stress == "a" and "и" or "и́"
local shortend = vowel_stem and (com.is_unstressed(stem) and "́й" -- accent on previous vowel
or "й") or "ь"
local function append_short_imper()
append_imper(forms, stem, tr, shortend, shortend .. "те", note)
end
local function append_long_imper()
append_imper(forms, stem, tr, longend, longend .. "те", note)
end
if variant and variant ~= "" then
track("explicit-imper")
track("explicit-imper/" .. verbclass)
end
if variant == "(2)" then
-- use short variants with вы́- (for these verbs, long is expected)
if not rfind(stem, "^вы́-") then
error("Should only specify imperative variant (2) with verbs in вы́-, not " .. stem)
end
append_short_imper()
elseif variant == "[(2)]" then
-- use both long and short variants
append_long_imper()
append_short_imper()
elseif variant == "(3)" then
-- long in singular, short in plural
append_imper(forms, stem, tr, longend, shortend .. "те", note)
elseif variant == "[(3)]" then
-- long and short in singular, short in plural
append_imper(forms, stem, tr, {longend, shortend}, shortend .. "те", note)
elseif variant == "ь" or variant == "й" then
-- short variants wanted
append_short_imper()
elseif variant == "и" then
-- long variants wanted
append_long_imper()
else
assert(not variant or variant == "")
if vowel_stem then
if verbclass == "4b" or verbclass == "4c" or (
verbclass == "4a" and rfind(stem, "^вы́-")) then
append_long_imper()
else
append_short_imper()
end
else -- consonant stem
if stress == "b" or stress == "c" then
append_long_imper()
else
assert(stress == "a")
-- "и" after вы́-, e.g. вы́садить
-- "и" after final щ, e.g. тара́щиться (although this particular
-- verb has a [(3)] spec attached to it)
if rfind(stem, "^вы́-") or rfind(stem, "щ$") or
-- "и" after two consonants in a row (мо́рщить, зафре́ндить)
rfind(stem, "[бвгджзклмнпрстфхцчшщь][бвгджзклмнпрстфхцчшщ]$") then
append_long_imper()
else
-- "ь" after a single consonant (бре́дить)
append_short_imper()
end
end
end
end
end
-- Compute the past passive participle stem for verbs that require it to be
-- iotated (class 4, and class 5 in -еть).
local function iotated_ppp(data, stem, tr)
local iotated_stem, iotated_tr
if data.zhd then
local subbed
iotated_stem, subbed = rsubb(stem, "з?д$", "жд")
if not subbed then
error("Variant -жд- specified but stem " .. stem .. " doesn't end in -д")
end
if tr then
iotated_tr, subbed = rsubb(tr, "z?d$", "žd")
if not subbed then
error("Variant -жд- specified but translit " .. tr .. " doesn't end in -d")
end
end
else
iotated_stem, iotated_tr = com.iotation(stem, tr, data.shch)
end
return iotated_stem, iotated_tr
end
-- Set the past passive participle of verbs where the stress is moved left
-- from the ending by one syllable (if possible) if the ending is stressed,
-- otherwise left as-is (except class 1a in -е́ть, which has ending-stressed
-- -ённый). This applies to classes 1, 2, 3, 5, 6, 10 and 13. The stem comes
-- from the infinitive, iotated in class 5 -еть/-ѣть verbs. The participle
-- ending is -анный/-янный for verbs in -ать/-ять, -енный/-ённый for verbs in -еть,
-- -ѣнный/-ѣ̈нный for verbs in -ѣть, otherwise -тый.
local function set_moving_ppp(forms, data)
if not data.ppp then
return
end
-- NOTE: No need to check for multiple infinitives because no verbs have
-- them normally, and we probably don't want to check for overrides here
-- (e.g. it would break достичь and related verbs, which have participles
-- based on the infinitive достигнуть).
local infinitive, infinitivetr = extract_russian_tr(forms["infinitive"])
local stem, ending = rmatch(infinitive, "^(.*)([аеѣоуя]́?ть)$")
if not stem then
error("Strange infinitive " .. infinitive .. " when trying to create participle")
end
local tr, endingtr
if infinitivetr then
if ending == "ять" or ending == "я́ть" then
tr, endingtr = rmatch(infinitivetr, "^(.*)(ja" .. AC .. "?tʹ)$")
else
tr, endingtr = rmatch(infinitivetr, "^(.*)([aeěou]" .. AC .. "?tʹ)$")
end
if not tr then
error("Translit " .. infinitivetr .. " doesn't match Cyrillic " ..
infinitive)
end
end
local ending_vowel = usub(ending, 1, 1)
local ppptype = data.ppp
if com.is_nonsyllabic(stem) then
-- e.g. 3b гну́ть (гну́тый); but not -нуть (type 3a, as a suffix)
ppptype = "(7)"
end
if m_table.contains({"5a", "5b", "5c"}, data.conj_type) and
(ending_vowel == "е" or ending_vowel == "ѣ") then
stem, tr = iotated_ppp(data, stem, tr)
end
if not com.is_stressed(stem) then
stem, tr = com.make_ending_stressed(stem, tr)
end
if data.o then
-- цев -> цо́в, e.g. (об)лицева́ть -> (об)лицо́ванный
stem = rsub(stem, "е́", "о́") -- Cyrillic
if tr then
tr = rsub(tr, "e" .. AC, "o" .. AC) -- Latin
end
elseif data.yo then
-- ё occurs with e.g. 1a наверста́ть (навёрстанный)
-- ё occurs with e.g. 3b поверну́ть (повёрнутый)
-- ё occurs with e.g. 5b лежа́ть (лёжанный) but not with 5c держа́ть
-- (де́ржанный)
-- ё occurs always with class 2 in -ева́ть, e.g.
-- (за)тушева́ть ((за)тушёванный) and (за)клева́ть ((за)клёванный)
local subbed
stem, subbed = rsubb(stem, "е́", "ё") -- Cyrillic
if not subbed and data.old then
stem, subbed = rsub(stem, "ѣ́", "ѣ̈")
end
if not subbed then
error("No stressed е" .. (data.old and " or ѣ" or "") ..
" in stem " .. stem ..
" to replace with ё" .. (data.old and " or ѣ̈" or "") ..
" when trying to create participle")
end
if tr then
tr, subbed = rsub(tr, "j[eě]" .. AC, "jo" .. AC) -- Latin
if not subbed then
tr, subbed = rsub(tr, "[eě]" .. AC, "jo" .. AC) -- Latin
end
if not subbed then
error("No stressed е in translit " .. tr .. " to replace with jo when trying to create participle")
end
end
end
if data.conj_type == "1a" and ending_vowel == "е" then
-- 1a, only одоле́ть, преодоле́ть, verbs in -печатле́ть
set_ppp(forms, stem, tr, "ённый")
elseif data.conj_type == "1a" and ending_vowel == "ѣ" then
set_ppp(forms, stem, tr, "ѣ̈нный")
else
local stressed_ending, unstressed_ending
if ending_vowel == "е" then
stressed_ending = "ённый"
unstressed_ending = "енный"
elseif ending_vowel == "ѣ" then
stressed_ending = "ѣ̈нный"
unstressed_ending = "ѣнный"
else
local ppp_ending =
(ending_vowel == "а" or ending_vowel == "я") and "нный" or "тый"
stressed_ending = ending_vowel .. AC .. ppp_ending
unstressed_ending = ending_vowel .. ppp_ending
end
set_ppp(forms, stem, tr,
-- (7) occurs with 1a обуя́ть (обуя́нный)
ppptype == "(7)" and stressed_ending or
-- [(7)] -- when does it occur? may only occur in class 4
ppptype == "[(7)]" and {unstressed_ending, stressed_ending} or
unstressed_ending)
end
end
-- Iterate over the values of a property (e.g. past_m, past_f), handling
-- overrides properly. Call FN on each one, passing in RU, TR, NOTE.
local function iterate_over_prop(forms, args, prop, fn)
for _, form in ipairs(main_to_all_verb_forms[prop]) do
local ru, tr
if args[form] then
local orig_forms = {}
for _, form2 in ipairs(main_to_all_verb_forms[prop]) do
if forms[form2] then
table.insert(orig_forms, forms[form2])
end
end
local override = parse_and_stress_override(form, args[form], forms[form], orig_forms)
ru, tr = extract_russian_tr(override)
end
if (not ru or ru == "" or ru == "-") and forms[form] then
ru, tr = extract_russian_tr(forms[form])
end
-- skip unstressed forms (may occur in the past_m when a stressed
-- reflexive -ся́ should occur; these occur only in запереться and
-- опереться, where they're used to generate the past active part
-- and past adverbial part, and end-stressed forms shouldn't be
-- generated)
if ru and ru ~= "" and ru ~= "-" and not com.is_unstressed(ru) then
local ruentry, runotes = m_table_tools.separate_notes(ru)
local trentry, trnotes
if tr then
trentry, trnotes = m_table_tools.separate_notes(tr)
end
fn(ruentry, trentry, {runotes, trnotes})
end
end
end
-- Set the past passive participle for those classes where it is derived
-- from the past tense masculine singular (9, 11, 12, 14, 15, 16). We need
-- to apply any relevant overrides.
local function set_ppp_from_past_m(forms, args, data)
if not data.ppp then
return
end
iterate_over_prop(forms, args, "past_m", function(ru, tr, note)
if rfind(ru, "л$") then
ru = rsub(ru, "л$", "")
if tr then
tr = rsub(tr, "l$", "")
end
end
append_ppp(forms, ru, tr, "тый", note)
end)
end
-- Set the past passive participle for class-4 verbs.
local function set_class_4_ppp(forms, data, stem, tr, vclass)
if not data.ppp then
return
end
local iotated_stem, iotated_tr = iotated_ppp(data, stem, tr)
vclass = vclass or data.conj_type
if vclass == "4b" then
local stressed_iotated_stem, stressed_iotated_tr =
com.make_ending_stressed(iotated_stem, iotated_tr)
set_ppp(forms, stressed_iotated_stem, stressed_iotated_tr,
-- (8) occurs with 4b скрои́ть (скро́енный)
data.ppp == "(8)" and "енный" or
-- [(8)] occurs with 4b разгроми́ть (разгромлённый, разгро́мленный)
data.ppp == "[(8)]" and {"ённый", "енный"} or "ённый")
else
set_ppp(forms, iotated_stem, iotated_tr,
-- (7) occurs with 4c раздели́ть (разделённый)
data.ppp == "(7)" and "ённый" or
-- [(7)] occurs with 4a осве́домить (осве́домленный, осведомлённый)
-- [(7)] occurs with 4c иссуши́ть (иссу́шенный, иссушённый)
data.ppp == "[(7)]" and {"енный", "ённый"} or "енный")
end
end
-- Set the past passive participle for class-7 and class-8 verbs. These
-- form the PPP by adding to the base of the 3sg pres/futr (i.e. minus
-- -ет/-ёт). The stress follows the stress of the past singular feminine.
-- Only types a, a(1) and b exist, meaning that if the past singular feminine
-- is ending-stressed then the PPP ending is -ённый, otherwise it is -енный
-- with the stress of the 3sg pres/futr base preserved (and added to the
-- last syllable if the base has no stress, as in 7b укра́сть, 3sg украдёт,
-- fem sg past укра́ла, PPP укра́денный).
local function set_class_7_8_ppp(forms, args, data)
if not data.ppp then
return
end
local sg3_bases = {}
-- Extract 3sg bases. There may be more than one possible form, e.g. in
-- обокра́сть, so support this.
-- FIXME: We don't support checking for overrides here; doing so isn't
-- overly hard but is a bit tricky because the overrides will be either
-- pres_3sg or futr_3sg, depending on the aspect of the verb.
-- FIXME: We don't support manual translit here, because neither 7 nor 8
-- support it elsewhere.
for _, form in ipairs(main_to_all_verb_forms["pres_futr_3sg"]) do
local ru, tr
if forms[form] then
ru, tr = extract_russian_tr(forms[form])
end
if ru and ru ~= "" and ru ~= "-" then
local ruentry, runotes = m_table_tools.separate_notes(ru)
ruentry = rsub(ruentry, "[её]т$", "")
if com.is_unstressed(ruentry) then
ruentry = com.make_ending_stressed(ruentry)
end
m_table.insertIfNot(sg3_bases, {ruentry, runotes})
end
end
-- Here we do the same rigmarole as in set_ppp_from_past_m(), to respect
-- any past_f overrides that might have been set. It's unlikely that
-- there is more than one possible form but we support it.
iterate_over_prop(forms, args, "past_f", function(ru, tr, note)
for _, base_and_notes in ipairs(sg3_bases) do
local base, notes = base_and_notes[1], base_and_notes[2]
append_ppp(forms, base, nil,
-- check if past_f is ending-stressed
rfind(ru, AC .. "$") and "ённый" or "енный", notes)
end
end)
end
--[=[
Conjugation functions
]=]
conjugations["1a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"+p", "7", "ё"})
local stem, tr = com.split_russian_tr(get_stressed_arg(args, 2))
if stem == "-" and not tr then
-- Template space; leave it
else
stem, tr = com.strip_ending(stem, tr, "ть")
end
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "ть")
append_participles(forms, stem, tr, "ющий", "емый", "я", "вший", "вши", "в")
set_moving_ppp(forms, data)
present_je(forms, stem, tr, "a")
append_imper(forms, stem, tr, "й", "йте")
set_past(forms, stem, tr, "л", "ла", "ло", "ли")
return forms
end
local function guts_of_2(args, data)
local forms = {}
local inf_stem, inf_tr = com.split_russian_tr(get_stressed_arg(args, 2))
inf_stem, inf_tr = com.strip_ending(inf_stem, inf_tr, "ть")
no_stray_args(args, 2)
local pres_stem, pres_tr = inf_stem, inf_tr
local variants = args[1] or ""
parse_variants(data, variants, {"+p", "7"})
-- If stem ends in -ева́ть and a past passive participle is called for
-- with stress on the -е-, automatically set -о- or -ё- as required.
if data.ppp and data.ppp ~= "(7)" then
if rfind(inf_stem, "цева́") then
if data.ppp == "[(7)]" then
-- FIXME. Theoretically we should support this but there
-- aren't any verbs requiring it. It won't work properly
-- currently because we need the о to appear only when
-- stressed.
error("Variant [(7)] not supported for class 2")
end
-- цев -> цо́в, e.g. (об)лицева́ть -> (об)лицо́ванный
data.o = true
data.title = data.title .. "(-о-)"
elseif rfind(inf_stem, "ева́") then
data.yo = true
data.title = data.title .. "(-ё-)"
end
end
-- all -ова- change to -у-
pres_stem = rsub(pres_stem, "о(́?)ва(́?)$", "у%1%2")
pres_tr = pres_tr and rsub(pres_tr, "o(́?)va(́?)$", "u%1%2")
-- -ева- change to -ю- after most consonants and vowels, to -у- after hissing sounds and ц
if rfind(pres_stem, "[бвгдзклмнпрстфхь" .. com.vowel .. AC .. "]е(́?)ва(́?)$") then
pres_stem = rsub(pres_stem, "е(́?)ва(́?)$", "ю%1%2")
pres_tr = pres_tr and rsub(pres_tr, "e(́?)va(́?)$", "ju%1%2")
elseif rfind(pres_stem, "[жцчшщ]е(́?)ва(́?)$") then
pres_stem = rsub(pres_stem, "е(́?)ва(́?)$", "у%1%2")
pres_tr = pres_tr and rsub(pres_tr, "e(́?)va(́?)$", "u%1%2")
end
forms["infinitive"] = combine(inf_stem, inf_tr, "ть")
if data.conj_type == "2a" then
append_participles_2stem(forms, pres_stem, pres_tr, inf_stem, inf_tr,
"ющий", "емый", "я", "вший", "вши", "в")
present_je(forms, pres_stem, pres_tr, "a")
else
append_participles_2stem(forms, pres_stem, pres_tr, inf_stem, inf_tr,
"ю́щий", "-", "я́", "вший", "вши", "в")
present_je(forms, pres_stem, pres_tr, "b")
end
set_moving_ppp(forms, data)
append_imper(forms, pres_stem, pres_tr, "й", "йте")
set_past(forms, inf_stem, inf_tr, "л", "ла", "ло", "ли")
return forms
end
conjugations["2a"] = function(args, data)
return guts_of_2(args, data)
end
conjugations["2b"] = function(args, data)
return guts_of_2(args, data)
end
conjugations["3°a"] = function(args, data)
local forms = {}
-- (5), [(6)] or similar; imperative indicators
parse_variants(data, args[1], {"5", "6", "23", "и", "+p", "7", "ё"})
local stem, tr = com.split_russian_tr(get_stressed_arg(args, 2))
stem, tr = com.strip_ending(stem, tr, "нуть")
local vowel_stem = is_vowel_stem(stem)
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "нуть")
append_participles(forms, stem, tr,
-- default is blank for pres passive and adverbial
"нущий", "-", "-",
data.var6 == "req" and "нувший" or
data.var6 == "opt" and (vowel_stem and {"вший", "нувший"} or {"ший", "нувший"}) or
vowel_stem and "вший" or "ший",
data.var6 == "req" and "нувши" or
data.var6 == "opt" and (vowel_stem and {"вши", "нувши"} or {"ши", "нувши"}) or
vowel_stem and "вши" or "ши",
data.var6 == "req" and "нув" or
data.var6 == "opt" and (vowel_stem and {"в", "нув"} or "нув") or
vowel_stem and "в" or "-")
set_moving_ppp(forms, data)
present_e_a(forms, stem .. "н", tr and tr .. "n")
append_imper_by_variant(forms, stem .. "н", tr and tr .. "n", data.imper_variant, "3°a")
forms["past_m"] = data.var5 and combine(stem, tr, "нул") or "-"
forms["past_m_short"] = data.var5 ~= "req" and combine(stem, tr, (vowel_stem and "л" or "")) or nil
forms["past_f_short"] = combine(stem, tr, "ла")
forms["past_n_short"] = combine(stem, tr, "ло")
forms["past_pl_short"] = combine(stem, tr, "ли")
return forms
end
conjugations["3a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"23", "и", "+p", "7", "ё"})
local stem, tr = com.split_russian_tr(get_stressed_arg(args, 2))
-- make sure we can strip нуть from the stem and any translit;
com.strip_ending(stem, tr, "нуть")
-- but then just strip the -уть and leave the н
stem, tr = com.strip_ending(stem, tr, "уть")
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "уть")
append_participles(forms, stem, tr,
-- default is blank for pres passive and adverbial
"ущий", "-", "-", "увший", "увши", "ув")
set_moving_ppp(forms, data)
present_e_a(forms, stem, tr)
append_imper_by_variant(forms, stem, tr, data.imper_variant, "3a")
set_past(forms, stem .. "ул", tr and tr .. "ul", "", "а", "о", "и")
return forms
end
local function guts_of_3b_3c(args, data, vclass)
local forms = {}
parse_variants(data, args[1], {"+p", "7", "ё"})
local stem, tr = com.split_russian_tr(get_stressed_arg(args, 2))
-- make sure we can strip нуть from the stem and any translit;
com.strip_ending(stem, tr, "ну́ть")
-- but then just strip the -у́ть and leave the н
stem, tr = com.strip_ending(stem, tr, "у́ть")
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "у́ть")
append_participles(forms, stem, tr,
-- default is blank for pres passive and adverbial
"у́щий", "-", "-", "у́вший", "у́вши", "у́в")
set_moving_ppp(forms, data)
append_imper(forms, stem, tr, "и́", "и́те")
set_past(forms, stem, tr, "у́л", "у́ла", "у́ло", "у́ли")
if data.conj_type == "3b" then
present_e_b(forms, stem, tr)
else
stem, tr = com.make_ending_stressed(stem, tr)
present_e_c(forms, stem, tr)
end
return forms
end
conjugations["3b"] = function(args, data)
return guts_of_3b_3c(args, data)
end
conjugations["3c"] = function(args, data)
return guts_of_3b_3c(args, data)
end
conjugations["4a"] = function(args, data)
local forms = {}
-- imperative variants, also щ, used for verbs like похитить (похи́щу) (4a),
-- защитить (защищу́) (4b), поглотить (поглощу́) (4c) with a different
-- iotation (т -> щ, not ч)
parse_variants(data, args[1], {"23", "и", "щ", "past", "+p", "7", "жд"})
local stem, tr = com.split_russian_tr(get_stressed_arg(args, 2))
stem, tr = com.strip_ending(stem, tr, "ить")
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "ить")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(stem, "[шщжч]$")
append_participles(forms, stem, tr, hushing and "ащий" or "ящий",
"awkward-имый", hushing and "а" or "я", "ивший", "ивши", "ив")
set_class_4_ppp(forms, data, stem, tr)
present_i(forms, stem, tr, "a", data.shch)
append_imper_by_variant(forms, stem, tr, data.imper_variant, "4a")
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, stem .. "и",
tr and tr .. "i", args, data)
return forms
end
conjugations["4a1a"] = function(args, data)
local forms = {}
data.title = "4a // 1a"
data.cat_conj_types = {"1a", "4a"}
-- imperative variants, also щ, used for verbs like похитить (похи́щу) (4a),
-- защитить (защищу́) (4b), поглотить (поглощу́) (4c) with a different
-- iotation (т -> щ, not ч)
parse_variants(data, args[1], {"23", "и", "щ", "past", "+p", "7", "жд"})
local stem4, tr4 = com.split_russian_tr(get_stressed_arg(args, 2))
stem4, tr4 = com.strip_ending(stem4, tr4, "ить")
local hushing = rfind(stem4, "[шщжч]$")
local stem1, tr1
if hushing then
stem1 = stem4 .. "а"
tr1 = tr4 and tr4 .. "a"
else
stem1 = stem4 .. "я"
tr1 = tr4 and tr4 .. "ja"
end
no_stray_args(args, 2)
forms["infinitive"] = combine(stem4, tr4, "ить")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
append_participles(forms, stem4, tr4, hushing and "ащий" or "ящий",
"awkward-имый", hushing and "а" or "я", "ивший", "ивши", "ив")
append_participles(forms, stem1, tr1, "ющий", "емый", "я", {}, {}, {})
set_class_4_ppp(forms, data, stem4, tr4)
present_i(forms, stem4, tr4, "a", data.shch)
present_je(forms, stem1, tr1, "a", data.shch)
append_imper_by_variant(forms, stem4, tr4, data.imper_variant, "4a")
append_imper(forms, stem1, tr1, "й", "йте")
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, stem4 .. "и",
tr4 and tr4 .. "i", args, data)
return forms
end
conjugations["4b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"щ", "past", "+p", "8", "жд"})
local stem, tr = com.split_russian_tr(get_stressed_arg(args, 2))
stem, tr = com.strip_ending(stem, tr, "и́ть")
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "и́ть")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(stem, "[шщжч]$")
append_participles(forms, stem, tr, hushing and "а́щий" or "я́щий",
"awkward-и́мый", hushing and "а́" or "я́", "и́вший", "и́вши", "и́в")
set_class_4_ppp(forms, data, stem, tr)
present_i(forms, stem, tr, "b", data.shch)
append_imper(forms, stem, tr, "и́", "и́те")
-- set prefix to "" as past stem may vary in length and no (1) variants
local stem_noa, tr_noa = com.make_unstressed_once(stem, tr)
set_past_by_stress(forms, data.past_stress, "", nil, stem_noa .. "и́",
tr_noa and tr_noa .. "i" .. AC, args, data)
return forms
end
conjugations["4c"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"щ", "4", "past", "+p", "7", "жд"})
local stem, tr = com.split_russian_tr(get_stressed_arg(args, 2))
stem, tr = com.strip_ending(stem, tr, "и́ть")
stem, tr = com.make_ending_stressed(stem, tr)
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "и́ть")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(stem, "[шщжч]$")
local prap_end_stressed = hushing and "а́щий" or "я́щий"
local prap_stem_stressed = hushing and "ащий" or "ящий"
append_participles(forms, stem, tr, data.var4 == "req" and prap_stem_stressed
or data.var4 == "opt" and {prap_end_stressed, prap_stem_stressed}
or prap_end_stressed,
"awkward-и́мый", hushing and "а́" or "я́", "и́вший", "и́вши", "и́в")
set_class_4_ppp(forms, data, stem, tr)
present_i(forms, stem, tr, "c", data.shch)
append_imper(forms, stem, tr, "и́", "и́те")
local stem_noa, tr_noa = com.make_unstressed_once(stem, tr)
set_past_by_stress(forms, data.past_stress, "", nil, stem_noa .. "и́",
tr_noa and tr_noa .. "i" .. AC, args, data)
return forms
end
-- Combined class 5. But there's enough conditional code that it might make
-- more sense to separate them again.
local function guts_of_5(args, data)
local forms = {}
local is5a = data.conj_type == "5a"
local is5b = data.conj_type == "5b"
-- imperative ending (выгнать - выгони) and past stress; imperative is
-- "й" after any vowel (e.g. выстоять), with or without an acute accent,
-- otherwise ь or и
if is5a or is5b then
parse_variants(data, args[1], {"23", "и", "past", "+p", "7", "ё"})
else
parse_variants(data, args[1], {"23", "и", "past", "+p", "7", "ё", "4"})
end
local inf = get_stressed_arg(args, 2)
local past_stem = com.strip_ending(inf, nil, "ть")
local stem = is5b and get_opt_unstressed_arg(args, 3) or get_opt_stressed_arg(args, 3)
local default_stem = rmatch(past_stem, "^(.*)[еѣая]́?$")
if not default_stem then
error("Argument " .. inf .. " doesn't end in еть, ѣть, ать or ять")
end
if not is5a and not is5b then
default_stem = com.make_ending_stressed(default_stem)
end
stem = stem or default_stem
local pres_note = stem ~= default_stem and IRREG
no_stray_args(args, 3)
forms["infinitive"] = past_stem .. "ть"
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(stem, "[шщжч]$")
if is5a then
append_participles_2stem(forms, stem, nil, past_stem, nil,
hushing and "ащий" or "ящий", "имый", hushing and "а" or "я",
"вший", "вши", "в", pres_note)
elseif is5b then
append_participles_2stem(forms, stem, nil, past_stem, nil,
hushing and "а́щий" or "я́щий", "и́мый", hushing and "а́" or "я́",
"вший", "вши", "в", pres_note)
else
-- var4 occurs with at least терпре́ть and дыша́ть
local prap_end_stressed = hushing and "а́щий" or "я́щий"
local prap_stem_stressed = hushing and "ащий" or "ящий"
append_participles_2stem(forms, stem, nil, past_stem, nil,
data.var4 == "req" and prap_stem_stressed
or data.var4 == "opt" and {prap_end_stressed, prap_stem_stressed}
or prap_end_stressed,
"и́мый", hushing and "а́" or "я́", "вший", "вши", "в", pres_note)
end
set_moving_ppp(forms, data)
present_i(forms, stem, nil, is5a and "a" or is5b and "b" or "c", nil, pres_note)
append_imper_by_variant(forms, stem, nil, data.imper_variant, data.conj_type, pres_note)
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, past_stem, nil,
args, data)
return forms
end
conjugations["5a"] = function(args, data)
return guts_of_5(args, data)
end
conjugations["5b"] = function(args, data)
return guts_of_5(args, data)
end
conjugations["5c"] = function(args, data)
return guts_of_5(args, data)
end
-- Implement 6a, 6°a, 6a1as13, 6a1as14, and 1a6a.
local function guts_of_6a(args, data, vclass)
local forms = {}
-- Type 6a1a, section 13:
-- Forms of both 6a and 1a can occur. They are the same in the infinitive
-- and past. In the present active participle and the present/future, the
-- type 6 forms are preferred and the type 1a forms are colloquial. In the
-- remaining present forms and the imperative, both are equally preferred
-- (we put the type-6 forms first because Zaliznyak lists them first).
-- Type 6a1a section 14, type 1a6a:
-- Forms of both 6a and 1a can occur. They are the same in the infinitive
-- and past. In the present adverbial participle and the imperative, the
-- type 1a forms are preferred and the type 6a forms are dated. In the
-- remaining present forms, one or the other is slightly preferred (type
-- 6a for 6a1a, type 1a for 1a6a).
if vclass == "6a1as13" or vclass == "6a1as14" then
data.title = "6a // 1a"
data.cat_conj_types = {"1a", "6a"}
elseif vclass == "1a6a" then
data.title = "1a // 6a"
data.cat_conj_types = {"1a", "6a"}
end
parse_variants(data, args[1], {"23", "и", "past", "+p", "7", "ё"})
local inf = get_stressed_arg(args, 2)
local inf_past_stem = com.strip_ending(inf, nil, "ть")
local stem = rmatch(inf_past_stem, "^(.*)[ая]́?$")
if not stem then
error("Argument " .. inf .. " doesn't end in ать or ять")
end
if com.is_unstressed(stem) then
-- колыха́ть, колеба́ть, etc.
stem = com.make_ending_stressed(stem)
end
-- вызвать - вы́зову (в́ызов)
local pres_stem = get_opt_stressed_arg(args, 3) or stem
no_stray_args(args, 3)
local pres_note = pres_stem ~= stem and IRREG
-- no iotation, e.g. вырвать - вы́рву
local no_iotation = vclass == "6°a"
-- replace consonants for 1st person singular present/future
local iotated_stem = no_iotation and pres_stem or com.iotation(pres_stem)
forms["infinitive"] = inf_past_stem .. "ть"
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(iotated_stem, "[шщжч]$") or no_iotation
-- Participles
-- pres_pasv_part is normal if infinitive ends in -ять, nonexistent except
-- with certain lexical exceptions (колеба́ть, колыха́ть, глаго́лать,
-- дви́гать with exceptional form дви́жимый) if infinitive ends in -ать
local prpp_status = rfind(inf_past_stem, "я́?$") and "" or "none-"
if vclass == "6a" or vclass == "6°a" or vclass == "6a1as13" then
append_participles_2stem(forms, iotated_stem, nil, inf_past_stem, nil,
hushing and "ущий" or "ющий", prpp_status .. "емый", hushing and "а" or "я",
"вший", "вши", "в", pres_note)
if vclass == "6a1as13" then
-- then all the type 1a forms (both are the same in the past)
append_participles(forms, inf_past_stem, nil, "ющий*", prpp_status .. "емый", "я")
end
elseif vclass == "6a1as14" then
-- first the preferred type 6a present active/passive participles
append_participles(forms, iotated_stem, nil,
hushing and "ущий" or "ющий", prpp_status .. "емый", {}, {}, {}, {}, pres_note)
-- then all the type 1a forms (both are the same in the past)
append_participles(forms, inf_past_stem, nil, "ющий", "емый", "я",
"вший", "вши", "в")
-- then the dated type 6a present adverbial participle
append_participles(forms, iotated_stem, nil,
{}, {}, hushing and "а*" or "я*", {}, {}, {}, pres_note)
else -- type 1a6a
-- first the preferred type 1a forms (both are the same in the past)
append_participles(forms, inf_past_stem, nil, "ющий", "емый", "я",
"вший", "вши", "в")
-- then the type 6a forms (dated in present adverbial participle)
append_participles(forms, iotated_stem, nil,
hushing and "ущий" or "ющий", prpp_status .. "емый", hushing and "а*" or "я*",
{}, {}, {}, pres_note)
end
set_moving_ppp(forms, data)
-- Present/future tense
local function class_6_present()
if no_iotation then
present_e_a(forms, pres_stem, nil, pres_note)
else
present_je(forms, pres_stem, nil, "a", nil, pres_note)
end
end
if vclass == "6a" or vclass == "6°a" then
class_6_present()
elseif vclass == "1a6a" then
-- Do type 1a forms
present_je(forms, inf_past_stem, nil, "a")
class_6_present()
elseif vclass == "6a1as14" then
class_6_present()
-- Do type 1a forms
present_je(forms, inf_past_stem, nil, "a")
else
-- 6a1as13
class_6_present()
-- Do type 1a forms
present_je(forms, inf_past_stem, nil, "a", nil, "*")
end
-- Imperative forms; if 1a6a or 6a1as14, type 6a forms are dated;
-- if 6a1as13, type 6a forms go first.
local function class_1_impr()
append_imper(forms, inf_past_stem, nil, "й", "йте")
end
local function class_6_impr()
local dated_note = ((vclass == "6a1as14" or vclass == "1a6a") and "*" or "") ..
(pres_note or "")
append_imper_by_variant(forms, iotated_stem, nil, data.imper_variant,
"6a", dated_note)
end
if vclass == "6a1as14" or vclass == "1a6a" then
class_1_impr()
class_6_impr()
elseif vclass == "6a1as13" then
class_6_impr()
class_1_impr()
else
class_6_impr()
end
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, inf_past_stem, nil,
args, data)
if vclass == "6a1as14" or vclass == "1a6a" then
m_table.insertIfNot(data.internal_notes, "* Dated.")
elseif vclass == "6a1as13" then
m_table.insertIfNot(data.internal_notes, "* Colloquial; type-6 forms preferred.")
end
return forms
end
conjugations["6a"] = function(args, data)
return guts_of_6a(args, data, "6a")
end
conjugations["6°a"] = function(args, data)
return guts_of_6a(args, data, "6°a")
end
conjugations["6a1as13"] = function(args, data)
return guts_of_6a(args, data, "6a1as13")
end
conjugations["6a1as14"] = function(args, data)
return guts_of_6a(args, data, "6a1as14")
end
conjugations["1a6a"] = function(args, data)
return guts_of_6a(args, data, "1a6a")
end
-- implement 6b, 6°b
local function guts_of_6b(args, data, vclass)
local forms = {}
parse_variants(data, args[1], {"past", "+p", "7", "ё"})
local inf = get_stressed_arg(args, 2)
local stem = rmatch(inf, "^(.*)[ая]́ть$")
if not stem then
error("Argument " .. inf .. " doesn't end in ать or ять")
end
-- звать - зов, драть - дер
local pres_stem = get_opt_unstressed_arg(args, 3) or stem
no_stray_args(args, 3)
-- no iotation, e.g. рвать - рву
local no_iotation = vclass == "6°b"
local vowel_end_stem = is_vowel_stem(stem)
local pres_note = pres_stem ~= stem and IRREG
if no_iotation then
present_e_b(forms, pres_stem, nil, pres_note)
else
present_je(forms, pres_stem, nil, "b", nil, pres_note)
end
local impr_end = vowel_end_stem and "́й" -- accent on the preceding vowel
or "и́"
append_imper(forms, pres_stem, nil, impr_end, impr_end .. "те", pres_note)
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(pres_stem, "[шщжч]$")
-- no pres_pasv_part
local past_stem_with_vowel = stem .. (vowel_end_stem and "я́" or "а́")
append_participles_2stem(
forms, pres_stem, nil, past_stem_with_vowel, nil,
((hushing or no_iotation) and "у́щий" or "ю́щий"), {}, (hushing and "а́" or "я́"),
"вший", "вши", "в", pres_note)
forms["infinitive"] = combine(past_stem_with_vowel, nil, "ть")
set_moving_ppp(forms, data)
-- past_f for ждала́, подождала́ now handled through general mechanism
--for разобрало́сь, past_n2 разобрало́ now handled through general mechanism
--for разобрали́сь, past_pl2 разобрали́ now handled through general mechanism
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil,
stem .. (vowel_end_stem and "я́" or "а́"), nil, args, data)
return forms
end
conjugations["6b"] = function(args, data)
return guts_of_6b(args, data, "6b")
end
conjugations["6°b"] = function(args, data)
return guts_of_6b(args, data, "6°b")
end
-- Implement 6c, 6°c and 6c1a.
local function guts_of_6c(args, data, vclass)
local forms = {}
-- In type 6c1a, forms of both 6c and 1a can occur. They are
-- the same in the infinitive and past. In the present active participle
-- and the present/future, the type 6c forms are preferred and the type 1a
-- forms are colloquial. In the remaining present forms and the imperative,
-- both are equally preferred (we put the 6c forms first because Zaliznyak
-- lists 6c first).
if vclass == "6c1a" then
data.title = "6c // 1a"
data.cat_conj_types = {"1a", "6c"}
end
-- optional щ parameter for verbs like клеветать (клевещу́), past stress
parse_variants(data, args[1], {"щ", "past", "+p", "7", "ё"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "а́ть")
stem = com.make_ending_stressed(stem)
-- разостла́ть - расстелю́, рассте́лешь
local pres_stem = get_opt_stressed_arg(args, 3) or stem
no_stray_args(args, 3)
local pres_note = pres_stem ~= stem and IRREG
-- remove accent for some forms
local stem_noa = com.make_unstressed(stem)
-- applies only to стона́ть, застона́ть, простона́ть
local no_iotation = vclass == "6°c"
-- iotate the stem
local iotated_stem =
no_iotation and pres_stem or com.iotation(pres_stem, nil, data.shch)
local stem1a = stem_noa .. "а́"
forms["infinitive"] = stem_noa .. "а́ть"
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(iotated_stem, "[шщжч]$")
-- Participles
append_participles_2stem(forms, iotated_stem, nil, stem_noa, nil,
(hushing or no_iotation) and "ущий" or "ющий", {},
hushing and "а́" or "я́", "а́вший", "а́вши", "а́в", pres_note)
if vclass == "6c1a" then
-- then all the type 1a forms (both are the same in the past)
append_participles(forms, stem1a, nil, "ющий*", "емый", "я")
end
set_moving_ppp(forms, data)
if no_iotation then
present_e_c(forms, pres_stem, nil, pres_note)
else
present_je(forms, pres_stem, nil, "c", data.shch, pres_note)
end
append_imper(forms, iotated_stem, nil, "и́", "и́те", pres_note)
if vclass == "6c1a" then
present_je(forms, stem1a, nil, "a", nil, "*")
append_imper(forms, stem1a, nil, "й", "йте")
end
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, stem_noa .. "а́", nil,
args, data)
if vclass == "6c1a" then
m_table.insertIfNot(data.internal_notes, "* Colloquial; type-6 forms preferred.")
end
return forms
end
conjugations["6c"] = function(args, data)
return guts_of_6c(args, data, "6c")
end
conjugations["6°c"] = function(args, data)
return guts_of_6c(args, data, "6°c")
end
conjugations["6c1a"] = function(args, data)
return guts_of_6c(args, data, "6c1a")
end
local function convert_last_e_to_yo(form)
return rsub(form,
"([еѣ])[́̀̈]*([^" .. com.vowel .. "]*)$",
function(e, nonvowels)
return (e == "е" and "ё" or "ѣ̈") .. nonvowels
end)
end
local function guts_of_7(args, data, forms)
local is7b = data.conj_type == "7b"
local full_inf = get_stressed_arg(args, 2)
local pres_stems = is7b and get_unstressed_arg(args, 3) or get_stressed_arg(args, 3)
pres_stems = rsplit(pres_stems, ",")
local past_stem
if past_stem ~= "ёе" then
past_stem = get_opt_stressed_arg(args, 4)
end
local past_stem_vowel_alt = past_stem == "ёе"
if past_stem_vowel_alt then
past_stem = nil
end
no_stray_args(args, 4)
forms["infinitive"] = full_inf
-- Construct the default past and present stem by a combination of
-- infinitive and present final consonant.
-- (1) Deduce the final consonant.
local final_cons
for _, pres_stem in ipairs(pres_stems) do
-- Final cons is -ст if pres stem ends in vowel + ст, else
-- single final cons [дтсзбп] (no actual examples of final п).
-- Note that final -з can occur after a consonant (e.g. ползти́).
local this_final_cons = rmatch(pres_stem,
"[" .. com.vowel .. "]" .. AC .. "?(ст)$")
if not this_final_cons then
this_final_cons = rmatch(pres_stem, "([дтсзбп])$")
end
if not this_final_cons then
error("Unable to determine final consonant from present stem " .. pres_stem)
end
if final_cons and this_final_cons ~= final_cons then
error("Present stems with conflicting final consonants specified: " ..
table.concat(pres_stems, ","))
end
final_cons = this_final_cons
end
-- (2) Find the infinitive minus the termination.
local prefix = rmatch(full_inf, "^(.*)[сз]т[иь]" .. AC .."?$")
if not prefix then
error("Strange infinitive " .. full_inf .. "in class 7")
end
-- (3) Combine infinitive with final consonant.
local default_pres_stem = prefix .. final_cons
if is7b then
default_pres_stem = com.make_unstressed(default_pres_stem)
end
local default_past_stem = default_pres_stem
if com.is_unstressed(default_past_stem) then
default_past_stem = com.make_ending_stressed(default_past_stem)
end
-- (4) Past stems ending in -д and -т when the infinitive ends in -сть (but not -сти or -сти́)
-- lose this consonant (page 85 of Zaliznyak, see also footnote 2 on that page).
if rfind(full_inf, "сть$") then
default_past_stem = rsub(default_past_stem, "[дт]$", "")
end
-- (5) If 7b and the past stem wasn't originally specified as ёе, the past stem gets
-- ё in place of е.
if is7b and not past_stem_vowel_alt then
default_past_stem = convert_last_e_to_yo(default_past_stem)
end
for _, pres_stem in ipairs(pres_stems) do
local pres_note = pres_stem ~= default_pres_stem and IRREG
if is7b then
present_e_b(forms, pres_stem, nil, pres_note)
append_imper(forms, pres_stem, nil, "и́", "и́те", pres_note)
else
present_e_a(forms, pres_stem, nil, pres_note)
append_imper_by_variant(forms, pres_stem, nil, data.imper_variant,
"7a", pres_note)
end
end
-- Construct the past stem if not specified. Note that we then derive a separate
-- past-tense stem from this stem, and this stem as such ends up applying only
-- to the past active and adverbial participles.
if not past_stem then
past_stem = default_past_stem
end
local past_note = past_stem ~= default_past_stem and IRREG
-- Derive the past tense stem from the past stem derived above. This has ё instead of е
-- in 7b verbs; it also loses д and т in all cases, when the past stem derived above only loses
-- these consonants in some cases.
local past_tense_stem = past_stem
if is7b then
past_tense_stem = convert_last_e_to_yo(past_tense_stem)
end
past_tense_stem = rsub(past_tense_stem, "[дт]$", "")
local vowel_pp = is_vowel_stem(past_stem)
local pap = vowel_pp and "вши" or "ши"
local var9_note_symbol = next_note_symbol(data)
for _, pres_stem in ipairs(pres_stems) do
local pres_note = pres_stem ~= default_pres_stem and IRREG
append_participles_2stem(forms, pres_stem, nil, past_stem, nil,
is7b and "у́щий" or "ущий", "-", is7b and "я́" or "я",
vowel_pp and "вший" or "ший",
data.var9 and {is7b and "я́" or "я", pap .. var9_note_symbol} or pap,
vowel_pp and not data.var9 and "в" or "-", pres_note, past_note)
end
if data.var9 then
m_table.insertIfNot(data.internal_notes, var9_note_symbol .. " Dated.")
end
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, past_tense_stem, nil,
args, data,
-- 0 ending if the past stem ends in a consonant
not is_vowel_stem(past_tense_stem) and "no-pastml", past_note)
-- set PPP; must be done after both present 3sg and past fem have been set
set_class_7_8_ppp(forms, args, data)
end
conjugations["7a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"23", "и", "9","past", "+p"})
-- лезть - ле́зши - non-existent past_actv_part handled through general mechanism
guts_of_7(args, data, forms)
return forms
end
conjugations["7b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"9", "past", "+p"})
guts_of_7(args, data, forms)
return forms
end
local function class_8a_stem_to_infinitive(stem)
-- map e.g. вы́сек back to высе́чь
return rsub(stem, "[гк]$", "чь")
end
local function class_8b_stem_to_infinitive(stem)
-- map e.g. отвлёк back to отвле́чь
-- map e.g. зажёг back to заже́чь
return com.make_ending_stressed(rsub(rsub(rsub(stem, "ё", "е"), "ѣ̈", "ѣ"), "[гк]$", "чь"))
end
conjugations["8a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local full_inf = get_stressed_arg(args, 2)
local stem = get_stressed_arg(args, 3)
local stressed_past_stem = get_opt_stressed_arg(args, 4) or stem
no_stray_args(args, 4)
forms["infinitive"] = full_inf
local pres_note = class_8a_stem_to_infinitive(stem) ~= full_inf and IRREG
local stressed_past_note =
class_8a_stem_to_infinitive(stressed_past_stem) ~= full_inf and IRREG
-- default for pres_pasv_part is blank
append_participles_2stem(forms, stem, nil, stressed_past_stem, nil,
"ущий", "-", "-", "ший", "ши", "-", pres_note, stressed_past_note)
local iotated_stem = com.iotation(stem)
append_pres_futr(forms, iotated_stem, nil, {}, "ешь", "ет", "ем", "ете", {}, pres_note)
append_pres_futr(forms, stem, nil, "у", {}, {}, {}, {}, "ут", pres_note)
append_imper(forms, stem, nil, "и", "ите", pres_note)
-- set prefix to "" as stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, stem, nil, args, data,
"no-pastml", pres_note)
forms["past_m"] = stressed_past_stem .. (stressed_past_note or "")
-- set PPP; must be done after both present 3sg and past fem have been set
set_class_7_8_ppp(forms, args, data)
return forms
end
conjugations["8b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local full_inf = get_stressed_arg(args, 2)
local stem = get_unstressed_arg(args, 3)
local stressed_past_stems = rsplit(args[4] or "ё", ",")
for _, stressed_past_stem in ipairs(stressed_past_stems) do
if stressed_past_stem ~= "е" then
check_stressed_arg(stressed_past_stem, 4)
end
end
no_stray_args(args, 4)
forms["infinitive"] = full_inf
local pres_note = class_8b_stem_to_infinitive(stem) ~= full_inf and IRREG
local iotated_stem = com.iotation(stem)
append_pres_futr(forms, iotated_stem, nil, {}, "ёшь", "ёт", "ём", "ёте", {}, pres_note)
append_pres_futr(forms, stem, nil, "у́", {}, {}, {}, {}, "у́т", pres_note)
append_imper(forms, stem, nil, "и́", "и́те", pres_note)
-- set prefix to "" as stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil,
com.make_ending_stressed(stem), nil, args, data, "no-pastml", pres_note)
forms["past_m"] = nil
for _, stressed_past_stem in ipairs(stressed_past_stems) do
local pastm_stem, past_part_stem
if stressed_past_stem == "е" then
past_part_stem = com.make_ending_stressed(stem)
pastm_stem = past_part_stem
elseif stressed_past_stem == "ё" then
past_part_stem = convert_last_e_to_yo(com.make_ending_stressed(stem))
pastm_stem = past_part_stem
elseif stressed_past_stem == "ёе" then
past_part_stem = com.make_ending_stressed(stem)
pastm_stem = convert_last_e_to_yo(past_part_stem)
else
pastm_stem = stressed_past_stem
past_part_stem = stressed_past_stem
end
local past_note =
class_8b_stem_to_infinitive(pastm_stem) ~= full_inf and IRREG
-- default for pres_pasv_part is blank; влечь -> влеко́мый handled through
-- general override mechanism
append_participles_2stem(forms, stem, nil, past_part_stem, nil,
"у́щий", "-", "-", "ший", "ши", "-", pres_note, past_note)
append_form(forms, "past_m", pastm_stem, nil, "", past_note)
end
-- set PPP; must be done after both present 3sg and past fem have been set
set_class_7_8_ppp(forms, args, data)
return forms
end
conjugations["9a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "еть")
local pres_stem = get_opt_stressed_arg(args, 3)
no_stray_args(args, 3)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
local default_pres_stem = prefix .. rsub(base, "е", "")
pres_stem = pres_stem or default_pres_stem
local pres_note = pres_stem ~= default_pres_stem and IRREG
forms["infinitive"] = stem .. "еть"
-- perfective only
append_participles(forms, stem, nil, "-", "-", "-", "ший", "ши", "ев")
present_e_a(forms, pres_stem, nil, pres_note)
append_imper(forms, pres_stem, nil, "и", "ите", pres_note)
-- past_m doesn't end in л
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data, "no-pastml")
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["9b"] = function(args, data)
local forms = {}
--for this type, it's important to distinguish impf and pf
local impf = rfind(data.verb_type, "^impf")
parse_variants(data, args[1], {"past", "+p", "*"})
local stem_noa = com.strip_ending(get_stressed_arg(args, 2), nil, "е́ть")
local stem = rsub(stem_noa, "(.*)е", "%1ё")
local pres_stem = get_opt_unstressed_arg(args, 3)
-- stem used for past active and adverbial participles; defaults to past_m
local past_part_stem = get_opt_stressed_arg(args, 4)
no_stray_args(args, 4)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem, nil, "single_cons_base")
local default_pres_stem =
data.star and construct_long_prefix_variant(prefix) .. rsub(base, "[её]", "") or
prefix .. rsub(base, "[её]", "")
pres_stem = pres_stem or default_pres_stem
local pres_note = pres_stem ~= default_pres_stem and IRREG
forms["infinitive"] = stem_noa .. "е́ть"
present_e_b(forms, pres_stem, nil, pres_note)
append_imper(forms, pres_stem, nil, "и́", "и́те", pres_note)
-- past_m doesn't end in л
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data, "no-pastml")
set_ppp_from_past_m(forms, args, data)
append_participles_2stem(forms, pres_stem, nil, stem, nil, "у́щий", {}, {},
-- impf: тереть -> тёрши
-- pf: растереть -> растёрши, растере́в
-- we handle (рас)тёрши down below because the stress depends on the
-- past_m: запереть -> за́пер, за́перши(й)
{}, {}, impf and {} or "е́в", pres_note)
if past_part_stem then
for _, ppstem in ipairs(rsplit(past_part_stem, ",")) do
append_participles(forms, ppstem, nil, {}, {}, {}, "ший", "ши", {})
end
else
iterate_over_prop(forms, args, "past_m", function(ru, tr, note)
append_participles(forms, ru, tr, {}, {}, {}, "ший", "ши", {}, note)
end)
end
return forms
end
conjugations["10a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"+p", "7"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "оть")
no_stray_args(args, 2)
forms["infinitive"] = stem .. "оть"
-- These verbs are perfective-only, no present participles
append_participles(forms, stem, nil, "-", "-", "-", "овший", "овши", "ов")
set_moving_ppp(forms, data)
present_je(forms, stem, nil, "a")
append_imper(forms, stem, nil, "и", "ите")
set_past(forms, stem .. "ол", nil, "", "а", "о", "и")
return forms
end
conjugations["10c"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"+p", "7"})
local inf_stem = com.strip_ending(get_stressed_arg(args, 2), nil, "ть")
-- present tense stressed stem "моло́ть" - ме́лет
local pres_stem = get_opt_stressed_arg(args, 3)
no_stray_args(args, 3)
local default_pres_stem =
com.make_ending_stressed(com.strip_ending(inf_stem, nil, "о́"))
pres_stem = pres_stem or default_pres_stem
-- remove accent for some forms
local pres_stem_noa = com.remove_accents(pres_stem)
local pres_note = pres_stem ~= default_pres_stem and IRREG
forms["infinitive"] = inf_stem .. "ть"
-- default for pres_pasv_part is blank
append_participles_2stem(forms, pres_stem, nil, inf_stem, nil,
"ющий", "-", "я́", "вший", "вши", "в", pres_note)
set_moving_ppp(forms, data)
present_je(forms, pres_stem, nil, "c", nil, pres_note)
append_imper(forms, pres_stem_noa, nil, "и́", "и́те", pres_note)
set_past(forms, inf_stem .. "л", nil, "", "а", "о", "и")
return forms
end
conjugations["11a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "ить")
no_stray_args(args, 2)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem .. "и")
forms["infinitive"] = stem .. "ить"
-- perfective only
append_participles(forms, stem, nil, "-", "-", "-", "ивший", "ивши", "ив")
present_je(forms, stem .. "ь", nil, "a")
append_imper(forms, stem .. "ей", nil, "", "те")
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["11b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p", "*"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "и́ть")
local pres_stem = get_opt_unstressed_arg(args, 3)
no_stray_args(args, 3)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem .. "и́", nil, "single_cons_base")
local default_pres_stem =
data.star and construct_long_prefix_variant(prefix) .. rsub(base, "и́$", "") or
stem
pres_stem = pres_stem or default_pres_stem
local pres_note = pres_stem ~= default_pres_stem and IRREG
forms["infinitive"] = stem .. "и́ть"
append_participles_2stem(forms, pres_stem, nil, stem, nil,
"ью́щий", "-", "ья́", "и́вший", "и́вши", "и́в", pres_note)
present_je(forms, pres_stem .. "ь", nil, "b", nil, pres_note)
append_imper(forms, stem .. "е́й", nil, "", "те")
-- e.g. пила́, лила́
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["12a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = get_opt_stressed_arg(args, 3)
no_stray_args(args, 3)
local default_pres_stem = stem
pres_stem = pres_stem or default_pres_stem
local pres_note = pres_stem ~= default_pres_stem and IRREG
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
append_participles_2stem(forms, pres_stem, nil, stem, nil,
"ющий", "емый", "я", "вший", "вши", "в", pres_note)
present_je(forms, pres_stem, nil, "a", nil, pres_note)
append_imper(forms, pres_stem .. "й", nil, "", "те", pres_note)
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["12b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = get_opt_unstressed_arg(args, 3)
no_stray_args(args, 3)
local default_pres_stem = com.make_unstressed_once(stem)
pres_stem = pres_stem or default_pres_stem
local pres_note = pres_stem ~= default_pres_stem and IRREG
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
append_participles_2stem(forms, pres_stem, nil, stem, nil,
"ю́щий", "-", "я́", "вший", "вши", "в", pres_note)
present_je(forms, pres_stem, nil, "b", nil, pres_note)
-- the preceding vowel is stressed
append_imper(forms, pres_stem .. "́й", nil, "", "те", pres_note)
-- e.g. гнила́ but пе́ла
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["13b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"+p"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = com.strip_ending(stem, nil, "ва́")
no_stray_args(args, 2)
forms["infinitive"] = stem .. "ть"
-- tricky to use append_participles_2stem() because only pres_actv_part
-- uses pres_stem, not all present participles
forms["pres_actv_part"] = pres_stem .. "ю́щий"
forms["pres_pasv_part"] = stem .. "емый"
forms["pres_adv_part"] = stem .. "я"
forms["past_actv_part"] = stem .. "вший"
forms["past_adv_part"] = stem .. "вши"
forms["past_adv_part_short"] = stem .. "в"
set_moving_ppp(forms, data)
present_je(forms, pres_stem, nil, "b")
forms["impr_sg"] = stem .. "й"
forms["impr_pl"] = stem .. "йте"
set_past(forms, stem .. "л", nil, "", "а", "о", "и")
return forms
end
conjugations["14a"] = function(args, data)
-- only one verb: вы́жать
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = get_stressed_arg(args, 3)
no_stray_args(args, 3)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- perfective only
append_participles(forms, stem, nil, "-", "-", "-", "вший", "вши", "в")
present_e_a(forms, pres_stem)
forms["impr_sg"] = pres_stem .. "и"
forms["impr_pl"] = pres_stem .. "ите"
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["14b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = get_unstressed_arg(args, 3)
no_stray_args(args, 3)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
append_participles_2stem(forms, pres_stem, nil, stem, nil,
"у́щий", "-", "я́", "вший", "вши", "в")
present_e_b(forms, pres_stem)
forms["impr_sg"] = pres_stem .. "и́"
forms["impr_pl"] = pres_stem .. "и́те"
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["14c"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = get_stressed_arg(args, 3)
local pres_stem_noa = com.make_unstressed(pres_stem)
no_stray_args(args, 3)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
append_participles_2stem(forms, pres_stem, nil, stem, nil,
"у́щий", "-", "я́", "вший", "вши", "в")
present_e_c(forms, pres_stem)
forms["impr_sg"] = pres_stem_noa .. "и́"
forms["impr_pl"] = pres_stem_noa .. "и́те"
--two forms for past_m: при́нялся, приня́лся
--изъя́ла but приняла́
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["15a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"+p"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "ть")
no_stray_args(args, 2)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, stem, nil, "нущий", "-", "-", "вший", "вши", "в")
present_e_a(forms, stem .. "н")
forms["impr_sg"] = stem .. "нь"
forms["impr_pl"] = stem .. "ньте"
set_past(forms, stem .. "л", nil, "", "а", "о", "и")
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["16a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "ть")
no_stray_args(args, 2)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, stem, nil, "ву́щий", "-", "-", "вший", "вши", "в")
present_e_a(forms, stem .. "в")
forms["impr_sg"] = stem .. "ви"
forms["impr_pl"] = stem .. "вите"
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["16b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local stem_noa = com.make_unstressed(stem)
no_stray_args(args, 2)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
append_participles(forms, stem, nil, "ву́щий", "-", "вя́", "вший", "вши", "в")
present_e_b(forms, stem_noa .. "в")
forms["impr_sg"] = stem_noa .. "ви́"
forms["impr_pl"] = stem_noa .. "ви́те"
-- e.g. прижило́сь, прижи́лось
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["irreg"] = function(args, data)
local main = select(3, split_known_main_verb(get_stressed_arg(args, 2),
-- честь must go before есть
{"бежа́ть", "бѣжа́ть", "хоте́ть", "хотѣ́ть", "да́ть", "че́сть",
"е́сть", "ѣ́сть", "сы́пать", "лга́ть", "мо́чь", "идти́", "йти́",
"е́хать", "ѣ́хать", "мину́ть", "живописа́ть", "ле́чь",
"зи́ждить", "зы́бить", "кля́сть", "стели́ть", "бы́ть", "сса́ть", "сца́ть",
"чти́ть", "шиби́ть", "реве́ть", "има́ть", "вня́ть", "обя́зывать"}))
main = com.make_unstressed_once(main)
if not conjugations["irreg-" .. main] then
error("Strange, can't find conjugation for main verb " .. main)
end
return conjugations["irreg-" .. main](args, data)
end
conjugations["irreg-бежать"] = function(args, data)
-- irregular, only for verbs derived from бежать with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2),
{"бежа́ть", "бѣжа́ть"})
data.title = com.is_stressed(prefix) and "5a" or "5b"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "бежа́ть"
append_participles_2stem(forms, "бег", nil, "бежа́", nil,
"у́щий", "-", "-", "вший", "вши", "в", IRREG)
append_imper(forms, "беги́", nil, "", "те", IRREG)
append_pres_futr(forms, "бе", nil,
"гу́" .. IRREG, "жи́шь", "жи́т", "жи́м", "жи́те", "гу́т" .. IRREG)
set_past(forms, "бежа́л", nil, "", "а", "о", "и")
if data.old then
rsub_forms(forms, "^бе", "бѣ")
end
prepend_prefix(forms, prefix)
-- no PPP's for any derivatives of бежать
return forms
end
conjugations["irreg-бѣжать"] = conjugations["irreg-бежать"]
conjugations["irreg-хотеть"] = function(args, data)
-- irregular, only for verbs derived from хотеть with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2),
{"хоте́ть", "хотѣ́ть"})
data.title = "5c'"
data.cat_conj_types = {"5c"} -- no class for 5c', no point in creating for just this verb
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "хоте́ть"
append_participles_2stem(forms, "хот", nil, "хоте́", nil,
"я́щий", "-", "я́", "вший", "вши", "в")
append_imper(forms, "хоти́", nil, "", "те")
append_pres_futr(forms, "", nil,
"хочу́", "хо́чешь" .. IRREG, "хо́чет" .. IRREG, "хоти́м", "хоти́те", "хотя́т")
set_past(forms, "хоте́л", nil, "", "а", "о", "и")
if data.old then
rsub_forms(forms, "^хоте", "хотѣ")
end
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-хотѣть"] = conjugations["irreg-хотеть"]
conjugations["irreg-дать"] = function(args, data)
-- irregular, only for verbs derived from дать with the same stress pattern and вы́дать
local forms = {}
--for this type, it's important to distinguish if it's reflexive to set some stress patterns
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "да́ть")
data.title = com.is_stressed(prefix) and "irreg-a" or "irreg-b"
parse_variants(data, args[1], {"past", "+p"})
no_stray_args(args, 2)
forms["infinitive"] = "да́ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, "", nil, "даю́щий", "-", "-",
"да́вший", "да́вши", "да́в")
append_imper(forms, "да́й", nil, "", "те")
append_pres_futr(forms, "", nil,
"да́м", "да́шь", "да́ст", "дади́м", "дади́те", "даду́т")
prepend_prefix(forms, prefix)
set_past_by_stress(forms, data.past_stress, prefix, nil, "да́", nil,
args, data)
if data.ppp then
if prefix == "пере" then
set_ppp(forms, "", nil, "пе́реданный")
elseif prefix == "раз" then
set_ppp(forms, "", nil, "ро́зданный")
else
set_moving_ppp(forms, data)
end
end
return forms
end
conjugations["irreg-есть"] = function(args, data)
-- irregular, only for verbs derived from есть
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2),
{"е́сть", "ѣ́сть"})
data.title = com.is_stressed(prefix) and "irreg-a" or "irreg-b"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "е́сть"
append_participles_2stem(forms, "ед", nil, "е́", nil,
"я́щий", "о́мый", "я́", "вший", "вши", "в")
if data.ppp then
set_ppp(forms, "е́д", nil, "енный")
end
append_imper(forms, "е́шь", nil, "", "те")
append_pres_futr(forms, "е́", nil,
"м", "шь", "ст", "ди́м", "ди́те", "дя́т")
set_past(forms, "е́л", nil, "", "а", "о", "и")
if data.old then
rsub_forms(forms, "^е", "ѣ")
end
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-ѣсть"] = conjugations["irreg-есть"]
conjugations["irreg-сыпать"] = function(args, data)
-- irregular, only for verbs derived from сыпать
local forms = {}
--for this type, it's important to distinguish if it's reflexive for вы́сыпаться vs. вы́сыпать imperative
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "сы́пать")
data.title = "6a"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "сы́пать"
append_participles(forms, "сы́п", nil,
"лющий", "лемый", {"ля", "я" .. IRREG}, "авший", "авши", "ав")
append_imper(forms, "сы́п", nil,
-- вы́сыпать (but not вы́сыпаться) has two imperative singulars
com.is_stressed(prefix) and not data.refl and {"и", "ь"} or "ь", "ьте", IRREG)
present_je(forms, "сы́пл", nil, "a")
append_pres_futr(forms, "сы́п", nil,
{}, "ешь", "ет", "ем", "ете", {}, IRREG)
set_past(forms, "сы́пал", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
set_moving_ppp(forms, data)
return forms
end
conjugations["irreg-лгать"] = function(args, data)
-- irregular, only for verbs derived from лгать with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "лга́ть")
data.title = "6°b/c"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "лга́ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, "лг", nil,
"у́щий", "-", "-", "а́вший", "а́вши", "а́в")
append_imper(forms, "лги́", nil, "", "те")
append_pres_futr(forms, "", nil,
"лгу́", "лжёшь" .. IRREG, "лжёт" .. IRREG, "лжём" .. IRREG, "лжёте" .. IRREG, "лгу́т")
set_past(forms, "лга́л", nil, "", "а́", "о", "и")
prepend_prefix(forms, prefix)
set_moving_ppp(forms, data)
return forms
end
conjugations["irreg-мочь"] = function(args, data)
-- irregular, only for verbs derived from мочь with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "мо́чь")
data.title = "8c/b"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "мо́чь"
-- no passive or adverbial participles
append_participles(forms, "мо́г", nil,
"у́щий", "-", "-", "ший", "-", "-")
append_imper(forms, "моги́", nil, "", "те")
append_pres_futr(forms, "", nil,
"могу́", "мо́жешь", "мо́жет", "мо́жем", "мо́жете", "мо́гут")
set_past(forms, "мо́г", nil, "", "ла́", "ло́", "ли́")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-идти"] = function(args, data)
-- irregular, only for verbs derived from идти, including прийти́ and в́ыйти
local forms = {}
local prefix = args[2] == "идти́" and "" or
split_known_main_verb(get_stressed_arg(args, 2), "йти́")
data.title = com.is_stressed(prefix) and "irreg-a" or "irreg-b/b"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
-- no pres_pasv_part
if prefix == "" then
-- only идти, present imperfective
forms["infinitive"] = "идти́"
append_imper(forms, "иди́", nil, "", "те")
present_e_b(forms, "ид")
-- no past_adv_part_short
append_participles(forms, "", nil,
"иду́щий", "-", "идя́", "ше́дший", "ше́дши", "-")
elseif rfind(prefix, "и$") then -- при
forms["infinitive"] = "йти́"
append_imper(forms, "ди́", nil, "", "те")
present_e_b(forms, "д")
append_participles(forms, "", nil,
"-", "-", "-", "ше́дший", "ше́дши", "дя́")
else
forms["infinitive"] = "йти́"
append_imper(forms, "йди́", nil, "", "те")
present_e_b(forms, "йд")
append_participles(forms, "", nil,
"-", "-", "-", "ше́дший", "ше́дши", "йдя́")
end
set_past(forms, "", nil, "шёл", "шла́", "шло́", "шли́")
prepend_prefix(forms, prefix)
if data.ppp then
if prefix == "на" or prefix == "про" then
-- найти́ and пройти́ exceptionally have the stress on the prefix
set_ppp(forms, prefix, nil, "́йденный")
else
-- вы́йти and прийти́ are intransitive so we don't have to worry about them
set_ppp(forms, prefix, nil, "йдённый")
end
end
return forms
end
conjugations["irreg-йти"] = conjugations["irreg-идти"]
conjugations["irreg-ехать"] = function(args, data)
-- irregular, only for verbs derived from ехать
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2),
{"е́хать", "ѣ́хать"})
data.title = "irreg-a"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "е́хать"
-- no pres_pasv_part
-- no pres_adv_part
append_participles_2stem(forms, "е́д", nil, "е́х", nil,
"ущий", "-", "-", "авший", "авши", "ав")
present_e_a(forms, "е́д")
set_past(forms, "е́хал", nil, "", "а", "о", "и")
if data.old then
rsub_forms(forms, "^е", "ѣ")
end
prepend_prefix(forms, prefix)
--special-case the imperative
--literary (special) imperative forms for ехать are поезжа́й, поезжа́йте
local impstem = data.old and "ѣзжа́й" or "езжа́й"
if prefix == "" then
append_imper(forms, "по" .. impstem, nil, "", "те")
append_imper(forms, impstem, nil, "", "те")
elseif com.is_stressed(prefix) then
append_imper(forms, com.make_unstressed_once(prefix) .. impstem, nil, "", "те")
else
append_imper(forms, prefix .. impstem, nil, "", "те")
end
return forms
end
conjugations["irreg-ѣхать"] = conjugations["irreg-ехать"]
conjugations["irreg-минуть"] = function(args, data)
-- for the irregular verb "мину́ть"
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "мину́ть")
data.title = "3c"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "мину́ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, "ми́н", nil,
"у́щий", "-", "-", "у́вший", "у́вши", "у́в")
present_e_c(forms, "ми́н")
forms["pres_futr_1sg"] = "-" -- no futr 1sg
-- no imperative
-- two possible variants, one with root-only stress, the other with
-- either root or suffix stress.
if not args["root_past_stress"] then
append_past(forms, "мину́л", nil, "", "а", "о", "и")
end
append_past(forms, "ми́нул", nil, "", "а", "о", "и", IRREG)
prepend_prefix(forms, prefix)
set_moving_ppp(forms, data)
return forms
end
conjugations["irreg-живописать"] = function(args, data)
-- for irregular verb "живописа́ть", mixture of types 1 and 2
local forms = {}
local inf = get_stressed_arg(args, 2)
data.title = "1a"
parse_variants(data, args[1], {"+p"})
local inf_stem = com.strip_ending(inf, nil, "ть")
local pres_stem = rfind(inf_stem, "а́$") and rsub(inf_stem, "а́$", "у́")
or error("Unexpected infinitive " .. inf)
no_stray_args(args, 2)
forms["infinitive"] = inf_stem .. "ть"
-- no pres_pasv_part
append_participles_2stem(forms, pres_stem, nil, inf_stem, nil,
"ющий", "-", "я", "вший", "вши", "в", IRREG)
set_moving_ppp(forms, data)
present_je(forms, pres_stem, nil, "a", nil, IRREG)
append_imper(forms, pres_stem .. "й", nil, "", "те", IRREG)
set_past(forms, inf_stem .. "л", nil, "", "а", "о", "и")
return forms
end
conjugations["irreg-лечь"] = function(args, data)
-- irregular, only for verbs derived from лечь with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "ле́чь")
data.title = "8a/b"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "ле́чь"
-- no pres parts because always perfective
-- no past_adv_part_short
append_participles(forms, "лёг", nil,
"-", "-", "-", "ший", "ши", "-")
append_imper(forms, "ля́г", nil, "", "те", IRREG)
append_pres_futr(forms, "ля́", nil,
"гу", "жешь", "жет", "жем", "жете", "гут", IRREG)
set_past(forms, "", nil, "лёг", "легла́", "легло́", "легли́")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-честь"] = function(args, data)
-- irregular, only for verbs derived from идти, including прийти́ and в́ыйти
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "че́сть")
local pre_two_cons_prefix =
prefix == "об" and "обо" or
prefix == "с" and "со" or
prefix == "рас" and "разо" or
prefix
data.title = prefix == "" and "7b/b" or com.is_stressed(prefix) and "7a⑨" or
pre_two_cons_prefix ~= prefix and "7*b/b⑨" or "7b/b⑨"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
-- no pres_pasv_part
forms["infinitive"] = "че́сть"
append_imper(forms, "чти́", nil, "", "те", IRREG)
present_e_b(forms, "чт", nil, IRREG)
if prefix == "" then
append_participles(forms, "", nil,
"чту́щий", "-", "чтя́", "чти́вший", "чти́вши", "чти́в", IRREG)
elseif com.is_stressed(prefix) then
append_participles(forms, "", nil,
"-", "-", "-", "-", "чтя́", "-", IRREG)
else
append_participles(forms, "", nil,
"-", "-", "-", "-", {"чтя́" .. IRREG, "чётши*"}, "-")
m_table.insertIfNot(data.internal_notes, "* Dated.")
end
if data.ppp then
set_ppp(forms, "", nil, "чтённый" .. IRREG)
end
set_past(forms, "", nil, "чёл", "чла́" .. IRREG, "чло́" .. IRREG, "чли́" .. IRREG)
prepend_prefix(forms, prefix, pre_two_cons_prefix)
return forms
end
conjugations["irreg-зиждить"] = function(args, data)
-- irregular, only for verbs derived from зиждить(ся) with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "зи́ждить")
data.title = "irreg-a"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "зи́ждить"
append_participles(forms, "зи́жд", nil,
"ущий", "емый", "я", "ивший", "ивши", "ив")
if data.ppp then
set_ppp(forms, "зи́жд", nil, "енный")
end
append_imper(forms, "зи́жди", nil, "", "те")
present_e_a(forms, "зи́жд")
set_past(forms, "зи́ждил", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-зыбить"] = function(args, data)
-- irregular, only for verbs derived from зыбить
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "зы́бить")
data.title = "irreg-a"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "зы́бить"
append_participles(forms, "зы́б", nil,
"лющий", "лемый", "ля", "ивший", "ивши", "ив")
append_imper(forms, "зы́бли", nil, "", "те")
present_je(forms, "зы́б", nil, "a")
set_past(forms, "зы́бил", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-клясть"] = function(args, data)
-- irregular, only for verbs derived from клясть with the same stress pattern
local forms = {}
--for this type, it's important to distinguish if it's reflexive to set some stress patterns
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "кля́сть")
data.title = "irreg-b"
parse_variants(data, args[1], {"past", "+p"})
no_stray_args(args, 2)
forms["infinitive"] = "кля́сть"
append_participles_2stem(forms, "клян", nil, "кля́", nil,
"у́щий", "и́мый", "я́", "вший", "вши", "в")
append_imper(forms, "кляни́", nil, "", "те")
present_e_b(forms, "клян")
prepend_prefix(forms, prefix)
set_past_by_stress(forms, data.past_stress, prefix, nil, "кля́", nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["irreg-стелить"] = function(args, data)
-- irregular, only for verbs derived from стелить
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "стели́ть")
data.title = com.is_stressed(prefix) and "4a" or "4c"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "стели́ть"
append_participles(forms, "сте́л", nil,
"ющий" .. IRREG, "и́мый", "я́", "и́вший", "и́вши", "и́в")
set_class_4_ppp(forms, data, "сте́л", nil, data.title)
append_imper(forms, "стели́", nil, "", "те")
append_pres_futr(forms, "сте́л", nil, "ю́", {}, {}, {}, {}, {})
append_pres_futr(forms, "сте́л", nil, {}, "ешь", "ет", "ем", "ете", "ют", IRREG)
set_past(forms, "стели́л", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-быть"] = function(args, data)
-- irregular, only for verbs derived from быть with various stress patterns, the actual verb быть different from its derivatives
local forms = {}
--for this type, it's important to distinguish if it's reflexive to set some stress patterns
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "бы́ть")
data.title = "irreg-a"
parse_variants(data, args[1], {"past", "+p"})
no_stray_args(args, 2)
forms["infinitive"] = "бы́ть"
-- no pres_pasv_part
append_participles(forms, "", nil, "су́щий", "-", "бу́дучи",
"бы́вший", "бы́вши", "бы́в")
append_imper(forms, "бу́дь", nil, "", "те")
prepend_prefix(forms, prefix)
-- only for "бы́ть", some forms are archaic
if forms["infinitive"] == "бы́ть" then
append_pres_futr(forms, "", nil, "есть", "есть", "есть", "есть", "есть", "есть")
elseif com.is_stressed(prefix) then
-- if the prefix is stressed, e.g. "вы́быть"
present_e_a(forms, prefix .. "буд")
else
present_e_a(forms, prefix .. "бу́д")
end
set_past_by_stress(forms, data.past_stress, prefix, nil, "бы́", nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["irreg-ссать-сцать"] = function(args, data)
-- irregular, only for verbs derived from ссать and сцать (both vulgar!)
local forms = {}
local prefix, _, stem = split_known_main_verb(get_stressed_arg(args, 2),
{"сса́ть", "сца́ть"})
data.title = com.is_stressed(prefix) and "irreg-a" or "irreg-b"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
stem = com.strip_ending(stem, nil, "ть")
local pres_stem = rsub(stem, "а́?$", "")
no_stray_args(args, 2)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, pres_stem, nil, "у́щий", "-", "-",
"а́вший", "а́вши", "а́в")
append_imper(forms, pres_stem, nil, "ы́", "ы́те")
append_pres_futr(forms, pres_stem, nil,
"у́", "ы́шь", "ы́т", "ы́м", "ы́те", "у́т")
set_past(forms, stem .. "л", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-ссать"] = conjugations["irreg-ссать-сцать"]
conjugations["irreg-сцать"] = conjugations["irreg-ссать-сцать"]
conjugations["irreg-чтить"] = function(args, data)
-- irregular, only for verbs derived from чтить
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "чти́ть")
data.title = "4b"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "чти́ть"
append_participles_2stem(forms, "чт", nil, "чти́", nil,
{"я́щий", "у́щий" .. IRREG}, "и́мый", "я́", "вший", "вши", "в")
if data.ppp then
set_ppp(forms, "чт", nil, "ённый")
end
append_imper(forms, "чти́", nil, "", "те")
append_pres_futr(forms, "чт", nil,
"у́" .. IRREG, "и́шь", "и́т", "и́м", "и́те", {"я́т", "у́т" .. IRREG})
set_past(forms, "чти́л", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-шибить"] = function(args, data)
-- irregular, only for verbs in -шибить(ся)
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "шиби́ть")
data.title = com.is_stressed(prefix) and "irreg-a" or "irreg-b"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
-- no present participles
forms["infinitive"] = "шиби́ть"
append_participles(forms, "шиби́", nil,
"-", "-", "-", "вший", "вши", "в")
if data.ppp then
set_ppp(forms, "ши́бл", nil, "енный")
end
append_imper(forms, "шиби́", nil, "", "те")
present_e_b(forms, "шиб")
set_past(forms, "ши́б", nil, "", "ла", "ло", "ли")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-реветь"] = function(args, data)
-- irregular, only for verbs derived from "реветь"
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "реве́ть")
data.title = "irreg-b"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "реве́ть"
-- no pres_pasv_part
append_participles_2stem(forms, "рев", nil, "реве́", nil,
"у́щий", "-", "я́", "вший", "вши", "в")
present_e_b(forms, "рев")
append_imper(forms, "реви́", nil, "", "те")
set_past(forms, "реве́л", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-имать"] = function(args, data)
-- irregular, only for внимать and certain archaic verbs (e.g. имать as
-- conjugated in the 18th century, отъимать)
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "има́ть")
data.title = "1a // 6a"
data.cat_conj_types = {"1a", "6a"}
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "има́ть"
-- handle внемл- forms
append_participles(forms, "е́мл", nil,
"ющий", "емый", {"я", "я́"}, {}, {}, {})
-- handle внима́- forms
append_participles(forms, "има́", nil,
"ющий", "емый", "я", "вший", "вши", "в")
if data.ppp then
-- FIXME, do class-1a-type ppp's (e.g. вни́манный) exist?
-- ruwikt marks them with a *
set_ppp(forms, "е́мл", nil, "енный")
end
append_imper(forms, "", nil, {"е́мли", "емли́", "има́й"},
{"е́млите", "емли́те", "има́йте"})
present_je(forms, "е́мл", nil, "a")
-- Both вне́млю and внемлю́ are possible
append_pres_futr(forms, "емл", nil, "ю́", {}, {}, {}, {}, {})
present_je(forms, "има́", nil, "a")
set_past(forms, "има́л", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-внять"] = function(args, data)
-- irregular, only for внять
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "вня́ть")
data.title = "14c/c"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "вня́ть"
-- perfective only; no present participles
append_participles(forms, "вня́", nil,
"-", "-", "-", "вший", "вши", "в")
append_imper(forms, "вними́", nil, "", "те")
append_imper(forms, "вонми́", nil, "", "те")
present_e_c(forms, "вни́м")
present_e_c(forms, "во́нм")
set_past(forms, "вня́л", nil, "", "а́", "о", "и")
set_ppp_from_past_m(forms, args, data)
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-обязывать"] = function(args, data)
-- irregular, only for обязывать and обязываться
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "обя́зывать")
data.title = "1a"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "обя́зывать"
append_participles_2stem(forms, "обя́з", nil, "обя́зыва", nil,
{"ывающий", "у́ющий"}, {"ываемый", "у́емый"}, {"ывая", "у́я"}, "вший", "вши", "в")
append_imper(forms, "обя́зывай", nil, "", "те")
append_imper(forms, "обязу́й", nil, "", "те")
present_je(forms, "обя́зыва", nil, "a")
present_je(forms, "обязу́", nil, "a")
set_past(forms, "обя́зывал", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
--[=[
Partial conjugation functions
]=]
-- Present forms with -e-, no j-vowels.
present_e_a = function(forms, stem, tr, note)
append_pres_futr(forms, stem, tr, "у", "ешь", "ет", "ем", "ете", "ут", note)
end
present_e_b = function(forms, stem, tr, note)
append_pres_futr(forms, stem, tr, "у́", "ёшь", "ёт", "ём", "ёте", "у́т", note)
end
present_e_c = function(forms, stem, tr, note)
append_pres_futr(forms, stem, tr, "у́", "ешь", "ет", "ем", "ете", "ут", note)
end
-- Present forms with -e- and iotated stem. ABC = "a", "b" or "c", indicating
-- the accent pattern. If SHCH is set, iotate final т as щ, not ч. If NOTE
-- is given, add it to each form.
present_je = function(forms, stem, tr, abc, shch, note)
local iotated_stem, iotated_tr = com.iotation(stem, tr, shch)
assert(abc == "a" or abc == "b" or abc == "c")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(iotated_stem, "[шщжч]$") -- or no_iotation
local ending_1sg =
hushing and (abc == "a" and "у" or "у́") or
not hushing and (abc == "a" and "ю" or "ю́")
if abc == "b" then
append_pres_futr(forms, iotated_stem, iotated_tr,
{}, "ёшь", "ёт", "ём", "ёте", (hushing and "у́т" or "ю́т"), note)
else
append_pres_futr(forms, iotated_stem, iotated_tr,
{}, "ешь", "ет", "ем", "ете", (hushing and "ут" or "ют"), note)
end
append_pres_futr(forms, iotated_stem, iotated_tr,
ending_1sg, {}, {}, {}, {}, {}, note)
end
-- Present forms with -i- (and iotated stem in the 1sg). ABC = "a", "b" or "c",
-- indicating the accent pattern. If SHCH is set, iotate final т as щ, not ч.
-- If NOTE is given, add it to each form.
present_i = function(forms, stem, tr, abc, shch, note)
local iotated_stem, iotated_tr = com.iotation(stem, tr, shch)
assert(abc == "a" or abc == "b" or abc == "c")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local iotated_hushing = rfind(iotated_stem, "[шщжч]$")
local hushing = rfind(stem, "[шщжч]$")
local ending_1sg =
iotated_hushing and (abc == "a" and "у" or "у́") or
not iotated_hushing and (abc == "a" and "ю" or "ю́")
if abc == "b" then
append_pres_futr(forms, stem, tr,
{}, "и́шь", "и́т", "и́м", "и́те", hushing and "а́т" or "я́т", note)
else
append_pres_futr(forms, stem, tr,
{}, "ишь", "ит", "им", "ите", hushing and "ат" or "ят", note)
end
append_pres_futr(forms, iotated_stem, iotated_tr,
ending_1sg, {}, {}, {}, {}, {}, note)
end
-- Add the reflexive particle to all verb forms
make_reflexive = function(forms, reflex_stress)
for key, form in pairs(forms) do
local ru, tr = extract_russian_tr(form)
-- check for empty string, dashes and nil's
if ru and ru ~= "" and ru ~= "-" then
local ruentry, runotes = m_table_tools.separate_notes(ru)
local trentry, trnotes
if tr then
trentry, trnotes = m_table_tools.separate_notes(tr)
end
if is_vowel_stem(ruentry) then
forms[key] = {ruentry .. "сь" .. runotes, trentry and trentry .. "sʹ" .. trnotes}
-- if a past_m form doesn't contain a stress, add a stressed
-- particle "ся́" if called for
elseif reflex_stress and com.is_unstressed(ruentry) and rfind(key, "^past_m") then
forms[key] = {ruentry .. "ся́" .. runotes, trentry and trentry .. "sja" .. AC .. trnotes}
else
forms[key] = {ruentry .. "ся" .. runotes, trentry and trentry .. "sja" .. trnotes}
end
end
end
end
-- Convert verb forms to pre-reform style by adding ъ to consonant-final
-- forms (excluding those ending in й and ь) and converting -ий to -ій and
-- -ийся to -ійся
make_pre_reform = function(forms)
for key, form in pairs(forms) do
local ru, tr = extract_russian_tr(form)
-- check for empty string, dashes and nil's
if ru and ru ~= "" and ru ~= "-" then
local ruentry, runotes = m_table_tools.separate_notes(ru)
if rfind(ruentry, "[бцдфгчклмнпрствшхзжщ]$") then
forms[key] = {ruentry .. "ъ" .. runotes, tr}
else
forms[key] = {rsub(rsub(ruentry, "ий$", "ій"), "ийся$", "ійся") .. runotes, tr}
end
end
end
end
local function setup_pres_futr(forms, perf, old)
-- Copy the main form FROMFORM to the main form TOFORM, and copy all
-- associated alternative forms.
local function copy_form(fromform, toform)
local fromforms = main_to_all_verb_forms[fromform]
local toforms = main_to_all_verb_forms[toform]
local numforms = #fromforms
assert(#toforms == numforms)
for i=1,numforms do
forms[toforms[i]] = forms[fromforms[i]]
end
end
-- Copy pres_futr_* to pres_* (imperfective) or futr_* (perfective).
if perf then
copy_form("pres_futr_1sg", "futr_1sg")
copy_form("pres_futr_2sg", "futr_2sg")
copy_form("pres_futr_3sg", "futr_3sg")
copy_form("pres_futr_1pl", "futr_1pl")
copy_form("pres_futr_2pl", "futr_2pl")
copy_form("pres_futr_3pl", "futr_3pl")
else
copy_form("pres_futr_1sg", "pres_1sg")
copy_form("pres_futr_2sg", "pres_2sg")
copy_form("pres_futr_3sg", "pres_3sg")
copy_form("pres_futr_1pl", "pres_1pl")
copy_form("pres_futr_2pl", "pres_2pl")
copy_form("pres_futr_3pl", "pres_3pl")
end
local futr_data = {
{"futr_1sg", "бу́ду", "búdu"},
{"futr_2sg", "бу́дешь", "búdešʹ"},
{"futr_3sg", "бу́дет" .. (old and "ъ" or ""), "búdet"},
{"futr_1pl", "бу́дем" .. (old and "ъ" or ""), "búdem"},
{"futr_2pl", "бу́дете", "búdete"},
{"futr_3pl", "бу́дут" .. (old and "ъ" or ""), "búdut"}
}
local function insert_future(inf, inf_tr)
for _, fut in ipairs(futr_data) do
append_to_arg_chain(forms, fut[1], fut[1],
{fut[2] .. inf, inf_tr and fut[3] .. inf_tr})
end
end
-- Insert future, if required (there may conceivably be multiple infitives).
for _, form in ipairs(main_to_all_verb_forms["infinitive"]) do
local infinitive = forms[form]
if infinitive then
local inf, inf_tr = extract_russian_tr(forms[form])
-- only for "бы́ть" the future forms are бу́ду, бу́дешь, etc.
if inf == "бы́ть" then
insert_future("", nil)
elseif not perf then
insert_future(" " .. inf, inf_tr and " " .. inf_tr)
end
end
end
end
parse_and_stress_override = function(form, val, existing, all_existing)
if rfind(form, "^pres_futr") then
error("Overrides of pres_futr* are illegal, use pres_* or futr_*")
end
local allow_unaccented
val, allow_unaccented = rsubb(val, "^%*", "")
local ru, tr = com.split_russian_tr(val)
-- past_m can be unaccented in connection with reflex_stress=ся́
if not allow_unaccented and not rfind(form, "^past_m") then
if tr and com.is_unstressed(ru) ~= com.is_unstressed(tr) then
error("Override " .. form .. "=" .. ru .. " and translit " .. tr .. " must have same accent pattern")
end
if com.is_monosyllabic(ru) then
ru, tr = com.make_ending_stressed(ru, tr)
elseif com.needs_accents(ru) then
error("Override " .. form .. "=" .. ru .. " requires an accent")
end
end
if rfind(ru, "%+") then
-- If either the existing or override has manual translit, the resulting
-- form should have manual translit. We specify ALWAYS_TRANSLIT if
-- the override has manual translit, so that we can substitute the
-- existing translit into the override translit.
local existing_ru, existing_tr = extract_russian_tr(existing, not not tr)
-- used especially for present participles; substitute existing form,
-- minus any "awkward-" or "none-" prefixes.
ru = rsub(ru, "%+", strip_arg_status_prefix(existing_ru))
-- If there's existing translit but not in the override, make sure it's
-- carried along.
if existing_tr and not tr then
tr = com.translit(ru)
end
tr = tr and rsub(tr, "%+", strip_arg_status_prefix(existing_tr))
end
-- If there's an override and it doesn't match an existing form, it's
-- irregular and indicate it using the IRREG marker. We don't do this if
-- the override simply removes a form. We do do this if there aren't any
-- existing forms, on the theory that the presence of a form when none is
-- normally called for is an irregularity. When comparing against the
-- existing forms, strip any status prefix (e.g. 'awkward-').
if all_existing then
local all_existing_stripped = {}
for _, ae in ipairs(all_existing) do
local existing_ru, existing_tr = extract_russian_tr(ae)
existing_ru = strip_arg_status_prefix(existing_ru)
existing_tr = existing_tr and strip_arg_status_prefix(existing_tr)
table.insert(all_existing_stripped, {existing_ru, existing_tr})
end
if ru ~= "-" and not contains_form(all_existing_stripped, {ru, tr}) then
ru = ru .. IRREG
tr = tr and tr .. IRREG
end
end
return {ru, tr}
end
-- Set up pres_* or futr_*; handle *sym/*tail/*tailall notes and overrides.
handle_forms_and_overrides = function(args, forms, data)
setup_pres_futr(forms, data.perf, data.old)
--handle overrides (formerly we only had past_pasv_part as a
--general override, plus scattered main-form overrides in particular
--conjugation classes)
for _, all_forms in pairs(main_to_all_verb_forms) do
local i = 0
local orig_forms = {}
for _, form in ipairs(all_forms) do
if forms[form] then
table.insert(orig_forms, forms[form])
end
end
for _, form in ipairs(all_forms) do
i = i + 1
-- If we auto-generated the past passive participle in order to
-- check for irregular overrides, make sure to erase any such
-- participles that weren't overridden. This happens for example
-- in обнять, where there are two automatically generated past
-- passive participles but a single ppp=о́внятый override.
local override = args[form] or (
data.ppp_auto_generated and rfind(form, "^past_pasv_part") and "-"
)
if override then
forms[form] = parse_and_stress_override(form, override,
forms[form], orig_forms)
elseif i == 1 then
forms[form] = forms[form] or ""
end
end
end
local function append_value(forms, prop, value)
if forms[prop] and forms[prop] ~= "" and forms[prop] ~= "-" then
value = com.split_russian_tr(value, "dopair")
local curval = forms[prop]
if type(curval) == "string" then
curval = {curval}
end
forms[prop] = com.concat_paired_russian_tr(curval, value)
end
end
local function append_note_all(forms, proplist, value)
for _, prop in ipairs(proplist) do
append_value(forms, prop, value)
end
end
local function append_note_last(forms, proplist, value, gt_one)
local numprops = 0
local lastprop
-- Find the last property in the series with a value
for _, prop in ipairs(proplist) do
if forms[prop] and forms[prop] ~= "" and forms[prop] ~= "-" then
numprops = numprops + 1
lastprop = prop
end
end
if numprops > (gt_one and 1 or 0) then
append_value(forms, lastprop, value)
end
end
for _, proplist in ipairs(all_verb_forms) do
-- Handle PROP_sym, which applies to all overridable properties, including
-- alternative forms, and applies to exactly that property.
for _, prop in ipairs(proplist) do
if args[prop .. "_sym"] then
append_value(forms, prop, args[prop .. "_sym"])
end
end
local propname = proplist[1]
-- Handle PROP_tail, which applies to a series of properties (e.g. past_m,
-- past_m2, ...) and appends to the last one.
if args[propname .. "_tail"] then
append_note_last(forms, proplist, args[propname .. "_tail"])
end
-- Handle PROP_tailall, which applies to a series of properties and
-- appends to all.
if args[propname .. "_tailall"] then
append_note_all(forms, proplist, args[propname .. "_tailall"])
end
end
-- Now handle pasttail, pasttailall, prestail, prestailall, etc.
-- Table listing tail-arg prefix and corresponding verb forms.
local tailargs = {
{"past", past_verb_forms},
{"pres", pres_verb_forms},
{"futr", futr_verb_forms},
{"impr", impr_verb_forms},
{"part", part_verb_forms},
{"prespart", pres_part_verb_forms},
{"pastpart", past_part_verb_forms},
{"", all_main_verb_forms}
}
for _, tailspec in ipairs(tailargs) do
local tailforms = tailspec[2]
-- Handle the ...tail variants.
local tailarg = tailspec[1] .. "tail"
if args[tailarg] then
track(tailarg)
for _, prop in ipairs(tailforms) do
append_note_last(forms, main_to_all_verb_forms[prop], args[tailarg], ">1")
end
end
-- Handle the ...tailall variants.
local tailallarg = tailspec[1] .. "tailall"
if args[tailallarg] then
track(tailallarg)
for _, prop in ipairs(tailforms) do
append_note_all(forms, main_to_all_verb_forms[prop], args[tailallarg])
end
end
end
end
-- Finish generating the forms; primarily, clear out unused forms.
finish_generating_forms = function(forms, data)
-- Convert any main form that's nil (meaning no forms at all corresponding
-- to this main form) to the empty string.
for main_form, _ in pairs(main_to_all_verb_forms) do
if not forms[main_form] then
forms[main_form] = ""
end
end
-- Set the main form FORM to the empty string, and corresponding alt forms
-- to nil.
local function clear_form(form)
local i = 0
for _, altform in ipairs(main_to_all_verb_forms[form]) do
i = i + 1
if i == 1 then
forms[altform] = ""
else
forms[altform] = nil
end
end
end
-- Intransitive and reflexive verbs have no passive participles
-- (unless has_prpp=y and/or has_ppp=y).
if data.intr or data.refl then
if not data.has_prpp then
clear_form("pres_pasv_part")
end
if not data.has_ppp then
clear_form("past_pasv_part")
end
end
if data.refl then
-- no past_adv_part_short for reflexive verbs
clear_form("past_adv_part_short")
end
-- Impersonal verbs normally have no passive participles, but allow them
-- if there's specifically an override. We only do this for the present
-- passive participle because the past passive participle isn't inserted
-- by default, and we still want +p to work, which doesn't currently set
-- data.ppp_override.
if data.impers and not data.prpp_override then
clear_form("pres_pasv_part")
end
if data.impers then
clear_form("pres_1sg")
clear_form("pres_2sg")
clear_form("pres_1pl")
clear_form("pres_2pl")
clear_form("pres_3pl")
clear_form("futr_1sg")
clear_form("futr_2sg")
clear_form("futr_1pl")
clear_form("futr_2pl")
clear_form("futr_3pl")
clear_form("past_m")
clear_form("past_f")
clear_form("past_pl")
clear_form("past_m_short")
clear_form("past_f_short")
clear_form("past_pl_short")
clear_form("pres_actv_part")
clear_form("past_actv_part")
clear_form("pres_adv_part")
clear_form("past_adv_part")
clear_form("past_adv_part_short")
clear_form("impr_sg")
clear_form("impr_pl")
end
-- Perfective and iterative verbs have no present forms, as well as
-- verbs marked nopres=1.
if data.perf or data.iter or data.nopres then
clear_form("pres_actv_part")
clear_form("pres_pasv_part")
clear_form("pres_adv_part")
clear_form("pres_1sg")
clear_form("pres_2sg")
clear_form("pres_3sg")
clear_form("pres_1pl")
clear_form("pres_2pl")
clear_form("pres_3pl")
end
-- Some verbs (e.g. грясти́, густи́) have no past
if data.nopast then
clear_form("past_m")
clear_form("past_f")
clear_form("past_n")
clear_form("past_pl")
clear_form("past_m_short")
clear_form("past_f_short")
clear_form("past_n_short")
clear_form("past_pl_short")
clear_form("past_actv_part")
clear_form("past_pasv_part")
clear_form("past_adv_part")
clear_form("past_adv_part_short")
end
-- Iterative verbs and verbs marked noimpr=1 have no imperative forms.
if data.iter or data.noimpr then
clear_form("impr_sg")
clear_form("impr_pl")
end
-- Iterative verbs and verbs marked nofutr=1 have no future forms.
if data.iter or data.nofutr then
clear_form("futr_1sg")
clear_form("futr_2sg")
clear_form("futr_3sg")
clear_form("futr_1pl")
clear_form("futr_2pl")
clear_form("futr_3pl")
end
--handle "none-" and "awkward-" prefixes (used especially for pres_pasv_part)
local footnote_sym = nil
for _, all_forms in pairs(main_to_all_verb_forms) do
local i = 0
for _, form in ipairs(all_forms) do
i = i + 1
if forms[form] then
local formru, formtr = extract_russian_tr(forms[form])
if rfind(formru, "^none%-") then
if i == 1 then
forms[form] = ""
else
forms[form] = nil
end
elseif rfind(formru, "^awkward%-") then
if not footnote_sym then
footnote_sym = next_note_symbol(data)
m_table.insertIfNot(data.internal_notes, footnote_sym .. " Rare and awkward.")
end
forms[form] = {rsub(formru, "^awkward%-", "") .. footnote_sym,
formtr and rsub(formtr, "^awkward%-", "") .. footnote_sym}
end
end
end
end
--Insert footnote for IRREG symbol if present.
for _, all_forms in pairs(main_to_all_verb_forms) do
for _, form in ipairs(all_forms) do
if forms[form] then
local formru = extract_russian_tr(forms[form])
if rfind(formru, IRREG) then
m_table.insertIfNot(data.internal_notes, IRREG .. " Irregular.")
end
end
end
end
end
local accel_forms = {
-- present tense
pres_1sg = "1|s|pres|ind",
pres_2sg = "2|s|pres|ind",
pres_3sg = "3|s|pres|ind",
pres_1pl = "1|p|pres|ind",
pres_2pl = "2|p|pres|ind",
pres_3pl = "3|p|pres|ind",
-- future tense
futr_1sg = "1|s|fut|ind",
futr_2sg = "2|s|fut|ind",
futr_3sg = "3|s|fut|ind",
futr_1pl = "1|p|fut|ind",
futr_2pl = "2|p|fut|ind",
futr_3pl = "3|p|fut|ind",
-- imperative
impr_sg = "2|s|imp",
impr_pl = "2|p|imp",
-- past
past_m = "m|s|past|ind",
past_f = "f|s|past|ind",
past_n = "n|s|past|ind",
past_pl = "p|past|ind",
past_m_short = "short|m|s|past|ind",
past_f_short = "short|f|s|past|ind",
past_n_short = "short|n|s|past|ind",
past_pl_short = "short|p|past|ind",
-- active participles
pres_actv_part = "pres|act|part",
past_actv_part = "past|act|part",
-- passive participles
pres_pasv_part = "pres|pass|part",
past_pasv_part = "past|pass|part",
-- adverbial participles
pres_adv_part = "pres|adv|part",
past_adv_part = "past|adv|part",
past_adv_part_short = "short|past|adv|part",
-- infinitive
infinitive = "inf",
}
-- Make the table
make_table = function(forms, title, perf, intr, impers, notes, internal_notes, old)
local infinitives = {}
for _, form in ipairs(main_to_all_verb_forms["infinitive"]) do
local infinitive = forms[form]
if infinitive then
local inf = extract_russian_tr(forms[form])
if inf ~= "-" then
m_table.insertIfNot(infinitives, inf)
end
end
end
-- Group forms together for a given key and combine adjacent forms with the same
-- Russian (they should always have different translits). Take care not to introduce
-- manual translit unnecessarily.
local grouped_forms = {}
for dispform, sourceforms in pairs(disp_verb_form_map) do
local entry = {}
for _, form in ipairs(sourceforms) do
local ru, tr = extract_russian_tr(forms[form])
-- check for empty strings, dashes and nil's
if ru and ru ~= "" and ru ~= "-" and ru ~= "—" then
if #entry > 0 then
local lastru, lasttr = extract_russian_tr(entry[#entry])
if lastru == ru then
if not lasttr and not tr or lasttr == tr then
error("Russian form " .. ru .. " is duplicated, probably due to a duplicative override")
end
lasttr = lasttr or com.translit(lastru)
tr = tr or com.translit(ru)
entry[#entry] = {ru, lasttr .. " ''or'' " .. tr}
else
table.insert(entry, {ru, tr})
end
else
table.insert(entry, {ru, tr})
end
end
end
grouped_forms[dispform] = entry
end
local title = (old and "Pre-reform conjugation" or "Conjugation") .. (#infinitives == 0 and "" or
" of <span lang=\"ru\" class=\"Cyrl\">''" .. table.concat(infinitives, ", ") .. "''</span>") ..
(title and " (" .. title .. ")" or "")
local function add_links(ru, rusuf, runotes, tr, trnotes, accel)
local ruspan
ruspan = m_links.full_link({lang = lang, term = ru, accel = accel, tr = "-"})
if rusuf ~= "" then
rusuf = "<span lang=\"ru\" class=\"Cyrl\">" .. rusuf .. "</span>"
end
return ruspan .. rusuf .. runotes .. "<br/>" .. require("Module:script utilities").tag_translit(tr .. trnotes, lang, "default", 'style="color:var(--wikt-palette-grey-8,#888);"')
end
-- NOTE: No need to check for multiple infinitives because the accel system
-- doesn't support multiple lemmas.
local lemma, lemmatr = extract_russian_tr(forms["infinitive"])
-- check for empty strings, dashes and nil's
if lemma and lemma ~= "" and lemma ~= "-" and lemma ~= "—" then
lemma = m_table_tools.separate_notes(lemma)
if lemmatr then
lemmatr = m_table_tools.separate_notes(lemmatr)
end
else
-- In case the lemma is an empty string or dash, set to nil so we don't
-- set a lemma in the accelerator and fall back to the page name.
lemma = nil
lemmatr = nil
end
-- Convert to displayed form
local disp = {}
for key, entry in pairs(grouped_forms) do
for i, form in ipairs(entry) do
local ru, origtr = extract_russian_tr(form)
local tr = origtr or ru and com.translit(ru)
local ruentry, runotes = m_table_tools.get_notes(ru)
local trentry, trnotes = m_table_tools.get_notes(tr)
local accel_form = accel_forms[key]
if not accel_form then
error("Unrecognized key " .. key .. " when looking up accelerator form")
end
local accel
if origtr and origtr:find(" ''or'' ") then
-- Multiple translits for a given Russian term.
-- FIXME! Support this.
accel = nil
else
accel = { form = accel_form, translit = origtr,
lemma = lemma, lemma_translit = lemmatr}
end
if rfind(key, "^futr") then
-- Add link to first word (form of 'to be')
local tobe, inf = rmatch(ruentry, "^([^ ]*) ([^ ]*)$")
if tobe then
-- No accelerators for imperfective future, as it's just the future of "to be"
-- plus the infinitive.
entry[i] = add_links(tobe, " " .. inf, runotes, trentry, trnotes, nil)
else
entry[i] = add_links(ruentry, "", runotes, trentry, trnotes, accel)
end
else
entry[i] = add_links(ruentry, "", runotes, trentry, trnotes, accel)
end
end
disp[key] = table.concat(entry, ",<br/>")
if disp[key] == "" then
disp[key] = "—"
end
end
local all_notes = {}
for _, note in ipairs(internal_notes) do
local symbol, entry = m_table_tools.get_initial_notes(note)
table.insert(all_notes, symbol .. entry)
end
for _, note in ipairs(notes) do
local symbol, entry = m_table_tools.get_initial_notes(note)
table.insert(all_notes, symbol .. entry)
end
local notes_text
table.insert(all_notes, 1,
"Note: For declension of participles, see their entries. Adverbial participles are indeclinable.")
notes_text = table.concat(all_notes, "<br />") .. "\n"
return [=[<div class="NavFrame" style="max-width:49.6em;">
<div class="NavHead" style="text-align:left; background:var(--wikt-palette-lightindigo, #e9e9ff);">]=] .. title .. [=[</div>
<div class="NavContent">
{| class="inflection inflection-ru inflection-verb inflection-table"
|+ ]=] .. notes_text .. [=[
|- class="rowgroup"
! colspan="3" | ]=] .. (perf and [=[[[совершенный вид|perfective aspect]]]=] or [=[[[несовершенный вид|imperfective aspect]]]=]) .. [=[
|-
! [[неопределённая форма|infinitive]]
| colspan="2" | ]=] .. disp.infinitive .. [=[
|- class="rowgroup"
! style="width:15em" | [[причастие|participles]]
! [[настоящее время|present tense]]
! [[прошедшее время|past tense]]
|-
! [[действительный залог|active]]
| ]=] .. disp.pres_actv_part .. [=[ || ]=] .. disp.past_actv_part .. [=[
|-
! [[страдательный залог|passive]]
| ]=] .. disp.pres_pasv_part .. [=[ || ]=] .. disp.past_pasv_part .. [=[
|-
! [[деепричастие|adverbial]]
| ]=] .. disp.pres_adv_part .. [=[ || ]=] .. disp.past_adv_part .. [=[
|- class="rowgroup"
!
! [[настоящее время|present tense]]
! [[будущее время|future tense]]
|-
! [[первое лицо|1st]] [[единственное число|singular]] (<span lang="ru" class="Cyrl">я</span>)
| ]=] .. disp.pres_1sg .. [=[ || ]=] .. disp.futr_1sg .. [=[
|-
! [[второе лицо|2nd]] [[единственное число|singular]] (<span lang="ru" class="Cyrl">ты</span>)
| ]=] .. disp.pres_2sg .. [=[ || ]=] .. disp.futr_2sg .. [=[
|-
! [[третье лицо|3rd]] [[единственное число|singular]] (<span lang="ru" class="Cyrl">он/она́/оно́</span>)
| ]=] .. disp.pres_3sg .. [=[ || ]=] .. disp.futr_3sg .. [=[
|-
! [[первое лицо|1st]] [[множественное число|plural]] (<span lang="ru" class="Cyrl">мы</span>)
| ]=] .. disp.pres_1pl .. [=[ || ]=] .. disp.futr_1pl .. [=[
|-
! [[второе лицо|2nd]] [[множественное число|plural]] (<span lang="ru" class="Cyrl">вы</span>)
| ]=] .. disp.pres_2pl .. [=[ || ]=] .. disp.futr_2pl .. [=[
|-
! [[третье лицо|3rd]] [[множественное число|plural]] (<span lang="ru" class="Cyrl">они́</span>)
| ]=] .. disp.pres_3pl .. [=[ || ]=] .. disp.futr_3pl .. [=[
|- class="rowgroup"
! [[повелительное наклонение|imperative]]
! [[единственное число|singular]]
! [[множественное число|plural]]
|-
! [[второе лицо|2nd]] (<span lang="ru" class="Cyrl">ты/вы</span>)
| ]=] .. disp.impr_sg .. [=[ || ]=] .. disp.impr_pl .. [=[
|- class="rowgroup"
! [[прошедшее время|past tense]]
! [[единственное число|singular]]
! [[множественное число|plural]]<br/>(<span lang="ru" class="Cyrl">мы/вы/они́</span>)
|-
! [[мужской род|masculine]] (<span lang="ru" class="Cyrl">я/ты/он</span>)
| ]=] .. disp.past_m .. [=[ || rowspan="3" | ]=] .. disp.past_pl .. [=[
|-
! [[женский род|feminine]] (<span lang="ru" class="Cyrl">я/ты/она́</span>)
| ]=] .. disp.past_f .. [=[
|-
! [[средний род|neuter]] (<span lang="ru" class="Cyrl">оно́</span>)
| ]=] .. disp.past_n .. [=[
|}
</div>
</div>]=]
end
return export
rno0j7hrjcr4ihczr4cfa0do83sr2b1
5672499
5672498
2026-06-29T15:08:54Z
MustafaCavlak
59368
5672499
Scribunto
text/plain
--[=[
This module contains functions for creating inflection tables for Russian
verbs.
Author: Benwing, rewritten from early version by Atitarev, earliest version by CodeCat
NOTE: This module is partly converted to support manual translit, in the
form CYRILLIC//LATIN (i.e. with a // separating the Cyrillic and Latin
parts). All the general infrastructure supports manual translit; the
only thing that doesn't is some of the specific verb conjugation functions.
In particular, all of the class 1, 2, 3 and 4 conjugation functions support
manual translit, and the rest don't. To convert another, follow the
model of one of the already-converted functions.
Note that an individual form (an entry in the 'forms' table) can be
either a string (no special manual translit; generally this originates
from the portion of the code that doesn't support manual translit), or
a one-element list {CYRILLIC} (no special manual translit), or a
two-element list {CYRILLIC, LATIN} with manual translit specified.
The code is careful only to generate manual translit when it's needed,
to avoid penalizing the majority of cases where manual transit isn't
needed.
]=]
local m_str_utils = require("Modül:string araçları")
local m_utilities = require("Modül:araçlar")
local m_table = require("Modül:table")
local m_links = require("Modül:bağlantılar")
local com = require("Modül:ru-genel")
local m_debug = require("Modül:debug")
local m_table_tools = require("Modül:table tools")
-- If enabled, compare this module with new version of module to make
-- sure all conjugations are the same.
local test_new_ru_verb_module = false
local export = {}
-- Within this module, conjugations are the functions that do the actual
-- conjugating by creating the forms of a basic verb.
-- They are defined further down.
local conjugations = {}
local lang = require("Modül:diller").getirKodaGore("ru")
local u = m_str_utils.char
local rfind = m_str_utils.find
local rsubn = m_str_utils.gsub
local rmatch = m_str_utils.match
local rsplit = m_str_utils.split
local usub = m_str_utils.sub
local AC = u(0x0301) -- acute = ́
local DIA = u(0x0308) -- diaeresis = ̈
local PSEUDOCONS = u(0xFFF2) -- pseudoconsonant placeholder, matching ru-common
local IRREG = "△"
-- version of rsubn() that discards all but the first return value
local function rsub(term, foo, bar)
local retval = rsubn(term, foo, bar)
return retval
end
-- version of rsubn() that returns a 2nd argument boolean indicating whether
-- a substitution was made.
local function rsubb(term, foo, bar)
local retval, nsubs = rsubn(term, foo, bar)
return retval, nsubs > 0
end
-- Fancy version of ine() (if-not-empty). Converts empty string to nil,
-- but also strips leading/trailing space and then single or double quotes,
-- to allow for embedded spaces.
local function ine(arg)
if not arg then return nil end
arg = rsub(arg, "^%s*(.-)%s*$", "%1")
if arg == "" then return nil end
local inside_quotes = rmatch(arg, '^"(.*)"$')
if inside_quotes then
return inside_quotes
end
inside_quotes = rmatch(arg, "^'(.*)'$")
if inside_quotes then
return inside_quotes
end
return arg
end
local function is_vowel_stem(stem)
return rfind(stem, "[" .. com.vowel .. AC .. DIA .. "]$")
end
-- Return the next number to use as an internal note symbol, starting at 1.
-- We look at existing internal notes to see if the symbol is already used.
local function next_note_symbol(data)
local nextsym = 1
while true do
local sym_already_seen = false
for _, note in ipairs(data.internal_notes) do
if rfind(note, "^" .. nextsym .. " ") then
sym_already_seen = true
break
end
end
if sym_already_seen then
nextsym = nextsym + 1
else
break
end
end
return nextsym
end
-- FIXME: Move to utils
-- Iterate over a chain of parameters, FIRST then PREF2, PREF3, ...,
-- inserting into LIST (newly created if omitted). Return LIST.
local function get_arg_chain(args, first, pref, list)
if not list then
list = {}
end
local val = args[first]
local i = 2
while val do
table.insert(list, val)
val = args[pref .. i]
i = i + 1
end
return list
end
-- FIXME: Move to utils
-- Set a chain of parameters, FIRST then PREF2, PREF3, ..., from LIST.
local function set_arg_chain(args, first, pref, list)
local param = first
local i = 2
for _, val in ipairs(list) do
args[param] = val
param = pref .. i
i = i + 1
end
end
local function normalize_form(form)
if type(form) == "table" and m_table.length(form) == 1 then
return form[1]
end
return form
end
-- For a given form in a conjugation table, we allow either strings or
-- two-element lists {RUSSIAN, TRANSLIT}, where TRANSLIT can be nil
-- (equivalent to a one-element list). When comparing them, we have to take
-- this into account.
local function forms_equal(form1, form2)
return m_table.deepEquals(normalize_form(form1), normalize_form(form2))
end
local function contains_form(forms, form)
for _, f in ipairs(forms) do
if forms_equal(f, form) then
return true
end
end
return false
end
-- FIXME: Move to utils
-- Append to the end of a chain of parameters, FIRST then PREF2, PREF3, ...,
-- if the value isn't already present.
local function append_to_arg_chain(args, first, pref, newval)
local nextarg = first
local i = 2
if newval == "" then
error("Internal error: attempt to insert blank value into arg chain")
end
while true do
if not args[nextarg] then break end
if forms_equal(args[nextarg], newval) then
return nil
end
nextarg = pref .. i
i = i + 1
end
args[nextarg] = newval
return nextarg
end
local function get_true_arg(arg, not_off_by_1)
-- We normally move all params down by one because the first param is the
-- verb type; so reflect this correctly if the arg is numeric and
-- not_off_by_1 isn't given
return (not_off_by_1 or type(arg) ~= "number") and arg or arg + 1
end
local function getarg(args, arg, default, paramdesc, not_off_by_1)
paramdesc = paramdesc or "Parameter " .. get_true_arg(arg, not_off_by_1)
default = default or "-"
--PAGENAME = mw.loadData("Modül:başlık başı/veri").pagename
local NAMESPACE = mw.title.getCurrentTitle().nsText
return args[arg] or (NAMESPACE == "Template" and default) or error(paramdesc .. " has not been provided")
end
local function check_stressed_arg(val, arg)
-- don't consider suffixes
if not rfind(val, "^%-") and not com.is_nonsyllabic(val) and not com.is_stressed(val) then
error("Argument value " .. val .. " (parameter " .. get_true_arg(arg) .. ") must be stressed")
end
return val
end
local function get_stressed_arg(args, arg, default, paramdesc)
local retval = getarg(args, arg, default, paramdesc)
check_stressed_arg(retval, arg)
return retval
end
local function get_opt_stressed_arg(args, arg)
return args[arg] and get_stressed_arg(args, arg) or nil
end
local function check_unstressed_arg(val, arg)
if com.is_stressed(val) then
error("Argument value " .. val .. " (parameter " .. get_true_arg(arg) .. ") should not be stressed")
end
return val
end
local function get_unstressed_arg(args, arg, default, paramdesc)
local retval = getarg(args, arg, default, paramdesc)
check_unstressed_arg(retval, arg)
return retval
end
local function get_opt_unstressed_arg(args, arg)
return args[arg] and get_unstressed_arg(args, arg) or nil
end
local function no_stray_args(args, maxarg)
for i=(maxarg + 1), 20 do
if args[i] then
error("Value for argument " .. get_true_arg(i) .. " not allowed ("
.. args[i] .. " supplied)")
end
end
end
-- Extract a form spec (either a single string or a two-element table {RU, TR}
-- into the component Russian and transliterated components. Normally, if
-- an explicit manual translit wasn't given, the resulting translit will be
-- nil; but if ALWAYS_TRANSLIT is given, it will be auto-transliterated from
-- the Russian as needed.
local function extract_russian_tr(form, always_translit)
local ru, tr
if type(form) == "table" then
ru, tr = form[1], form[2]
else
ru = form
end
if not tr and always_translit then
tr = ru and com.translit(ru)
end
return ru, tr
end
local function strip_arg_status_prefix(arg)
if not arg then
return arg, ""
end
local subbed
arg, subbed = rsubb(arg, "^awkward%-", "")
if subbed then
return arg, "awkward-"
end
arg, subbed = rsubb(arg, "^none%-", "")
if subbed then
return arg, "none-"
end
return arg, ""
end
local function track(page)
m_debug.track("ru-verb/" .. page)
return true
end
-- Forward functions
local present_e_a
local present_e_b
local present_e_c
local present_je
local present_i
local make_reflexive
local make_pre_reform
local parse_and_stress_override
local handle_forms_and_overrides
local finish_generating_forms
local make_table
local all_verb_types = {
"pf", "pf-intr", "pf-refl",
"pf-impers", "pf-intr-impers", "pf-refl-impers",
"impf", "impf-intr", "impf-refl",
"impf-impers", "impf-intr-impers", "impf-refl-impers"}
-- Examples of alternatives in use:
-- past_m2: со́здал/созда́л, пе́редал/переда́л, о́тдал/отда́л, при́нялся/принялся́
-- past_m3: for verbs with three past masculine sg forms: за́нялся, заня́лся, занялс́я (заня́ться)
-- past_n2: да́ло, дал́о; вз́яло, взяло́
-- past_pl2: разобрали́сь (разобрали́)
-- past_m_short: short forms in 3a (исчез, сох, etc.)
-- past_f_short: short forms in 3a (исчезла, сохла, etc.)
-- past_n_short: short forms in 3a (исчезло, сохло, etc.)
-- past_pl_short: short forms in 3a (исчезли, сохли, etc.)
-- past_adv_parts:
-- тереть: тере́вши, тёрши, short: тере́в
-- умереть: умере́вши, у́мерши, short: умере́в
-- pres_adv_part: сыпля, сыпя, лёжа (лежать)
-- pres_2sg2: сыплешь, сыпешь
-- pres_3sg2: сыплет, сыпет
-- pres_1pl2: сыплем, сыпем
-- pres_2pl2: сыплете, сыпете
-- pres_3pl2: сыплют, сыпют
-- futr_2sg2: насыплешь, насыпешь
-- futr_3sg2: насыплет, насыпет
-- futr_1pl2: насыплем, насыпем
-- futr_2pl2: насыплете, насыпете
-- futr_3pl2: насыплют, насыпют
-- List of all main verb forms. Short forms (those ending in "_short")
-- must be listed after the corresponding non-short forms.
local all_main_verb_forms = {
-- present tense
"pres_1sg", "pres_2sg", "pres_3sg", "pres_1pl", "pres_2pl", "pres_3pl",
-- future tense
"futr_1sg", "futr_2sg", "futr_3sg", "futr_1pl", "futr_2pl", "futr_3pl",
-- present-future tense. The conjugation functions generate the
-- "present-future" tense instead of either the present or future tense,
-- since the same forms are used in the present imperfect and future
-- perfect. These forms are later copied into the present or future in
-- finish_generating_forms().
"pres_futr_1sg", "pres_futr_2sg", "pres_futr_3sg", "pres_futr_1pl", "pres_futr_2pl", "pres_futr_3pl",
-- imperative
"impr_sg", "impr_pl",
-- past
"past_m", "past_f", "past_n", "past_pl",
"past_m_short", "past_f_short", "past_n_short", "past_pl_short",
-- active participles
"pres_actv_part", "past_actv_part",
-- passive participles
"pres_pasv_part", "past_pasv_part",
-- adverbial participles
"pres_adv_part", "past_adv_part", "past_adv_part_short",
-- infinitive
"infinitive"
}
-- List of all verb forms. Each element is a list, where the first element
-- is the "main" form and the remainder are alternatives. The following
-- *MUST* hold:
-- 1. Forms must be given in the order they will appear in the outputted
-- table.
-- 2. Short forms (those ending in "_short") must be listed after the
-- corresponding non-short forms.
-- 3. For each person, e.g. '2sg', there must be the same number of
-- futr_PERSON, pres_PERSON and pres_futr_PERSON forms, and the alternative
-- forms must be listed in the same order.
--
-- FIXME!!! We should fix things so we no longer need to compute this table.
local all_verb_forms = {}
-- Compile all_verb_forms
for _, mainform in ipairs(all_main_verb_forms) do
local entry = {}
table.insert(entry, mainform)
for i=2,9 do
table.insert(entry, mainform .. i)
end
table.insert(all_verb_forms, entry)
end
local prop_aliases = {
pap="past_actv_part",
paptail="past_actv_part_tail",
paptailall="past_actv_part_tailall",
ppp="past_pasv_part",
ppptail="past_pasv_part_tail",
ppptailall="past_pasv_part_tailall",
prap="pres_actv_part",
praptail="pres_actv_part_tail",
praptailall="pres_actv_part_tailall",
prpp="pres_pasv_part",
prpptail="pres_pasv_part_tail",
prpptailall="pres_pasv_part_tailall",
padp="past_adv_part",
padptail="past_adv_part_tail",
padptailall="past_adv_part_tailall",
padp_short="past_adv_part_short",
padp_shorttail="past_adv_part_short_tail",
padp_shorttailall="past_adv_part_short_tailall",
pradp="pres_adv_part",
pradptail="pres_adv_part_tail",
pradptailall="pres_adv_part_tailall",
}
-- Table mapping "main" to the list of all forms in the series (e.g.
-- past_m, past_m2, past_m3, etc.). If a main form (e.g. past_m) is missing,
-- it needs to end up with a value of "", whereas the alternatives
-- (e.g. past_m2, past_m3) need to end up with a value of nil.
local main_to_all_verb_forms = {}
-- List of the main verb forms for the past.
local past_verb_forms = {"past_m", "past_f", "past_n", "past_pl"}
-- List of the main verb forms for the present.
local pres_verb_forms = {"pres_1sg", "pres_2sg", "pres_3sg",
"pres_1pl", "pres_2pl", "pres_3pl"}
-- List of the main verb forms for the future.
local futr_verb_forms = {"futr_1sg", "futr_2sg", "futr_3sg",
"futr_1pl", "futr_2pl", "futr_3pl"}
-- List of the main verb forms for the imperative.
local impr_verb_forms = {"impr_sg", "impr_pl"}
-- List of the main verb forms for participles.
local part_verb_forms = {"pres_actv_part", "past_actv_part",
"pres_pasv_part", "past_pasv_part",
"pres_adv_part", "past_adv_part", "past_adv_part_short"}
-- List of the main verb forms for present participles.
local pres_part_verb_forms = {"pres_actv_part", "pres_pasv_part",
"pres_adv_part"}
-- List of the main verb forms for past participles.
local past_part_verb_forms = {"past_actv_part", "past_pasv_part",
"past_adv_part", "past_adv_part_short"}
-- Compile main_to_all_verb_forms.
for _, proplist in ipairs(all_verb_forms) do
main_to_all_verb_forms[proplist[1]] = proplist
end
-- Map listing the forms to be displayed, and the verb forms used to generate
-- the displayed form, in order. For example, under past_m will be found
-- {"past_m_short", "past_m", "past_m2", "past_m3"} because those forms in
-- that order are displayed in the table under "masculine singular past".
local disp_verb_form_map = {}
for _, proplist in ipairs(all_verb_forms) do
local key = proplist[1]
-- if we find short forms, insert them at the beginning of the list for
-- the corresponding full forms. This requires that short forms are
-- listed in all_verb_forms after the corresponding full forms.
if rfind(key, "_short$") then
local full_key = rsub(key, "_short$", "")
-- short forms should occur in list after full forms
assert(#(disp_verb_form_map[full_key]) > 0)
-- build entry for full form, consisting first of the short forms,
-- in order, then the full forms, in order.
local new_entry = {}
for _, form in ipairs(proplist) do
table.insert(new_entry, form)
end
for _, form in ipairs(disp_verb_form_map[full_key]) do
table.insert(new_entry, form)
end
disp_verb_form_map[full_key] = new_entry
elseif rfind(key, "^pres_futr") then
-- skip these forms, not displayed
else
disp_verb_form_map[key] = mw.clone(proplist)
end
end
local all_verb_props = mw.clone(all_verb_forms)
local non_form_props = {"title", "perf", "intr", "impers", "categories", "notes", "internal_notes"}
for _, prop in ipairs(non_form_props) do
table.insert(all_verb_props, {prop})
end
-- Clone parent's args while also assigning nil to empty strings and splitting
-- arg sets (numeric args separated by "or"), assigning named args to
-- all all sets. Handle aliases in the process. Extract conjugation type
-- from the first arg of the arg set (for the initial arg set, this will be
-- arg 2 because arg 1 is the verb type), assigning to '.conj_type' of the
-- arg set. Return arg sets.
local function split_args_handle_aliases(frame)
local args = frame:getParent().args
local arg_sets = {}
local arg_set = {}
-- Verb type, e.g. impf, pf, impf-intr, pf-intr, impf-refl, pf-refl, etc.
-- Default to impf on the template page so that there is no script error.
local verb_type = getarg(args, 1, "impf", "Verb type (first parameter)")
local offset = 1
-- Find maximum-numbered arg, allowing for holes.
local max_arg = 1 -- needs to be 1 not 0 so template pages display ok
for pname in pairs(args) do
if type(pname) == "number" and pname > max_arg then
max_arg = pname
end
end
-- Now gather the numbered arguments.
for i=2,(max_arg + 1) do
local end_arg_set = false
if i == max_arg + 1 or args[i] == "or" then
end_arg_set = true
end
if end_arg_set then
table.insert(arg_sets, arg_set)
arg_set = {}
offset = i
else
arg_set[i - offset] = ine(args[i])
end
end
-- Insert named arguments into all arg sets, mapping aliases appropriately.
for pname, param in pairs(args) do
if type(pname) == "string" then
local argval = ine(param)
local mainprop, num = rmatch(pname, "^([a-z_]+)([0-9]*)$")
for i=1,#arg_sets do
if not mainprop then
arg_sets[i][pname] = argval
else
mainprop = prop_aliases[mainprop] or mainprop
arg_sets[i][mainprop .. num] = argval
end
end
end
end
-- If we're conjugating a suffix, insert a pseudoconsonant at the beginning
-- of all forms, so they get conjugated as if ending in a consonant.
-- We remove the pseudoconsonant later.
for i=1,#arg_sets do
local asif_prefix = (arg_sets[i]["asif_prefix"] or
arg_sets[i][2] and rfind(arg_sets[i][2], "^%-") and PSEUDOCONS)
if asif_prefix then
for k, v in pairs(arg_sets[i]) do
arg_sets[i][k] = rsub(v, "^%-", "-" .. asif_prefix)
end
end
end
-- Frob conjugation type.
for i=1,#arg_sets do
local arg1 = arg_sets[i][1]
local conj_type
if arg1 then
local orig_arg1 = arg1
-- This complex spec matches matches 3°a, 3oa, 4a1a, 6c1a,
-- 1a6a, 6a1as13, 6a1as14, 11*b, etc.
conj_type = rmatch(arg1, "^([0-9]+[*°o0-9abc]*[abc]s?1?[34]?)")
arg1 = rsub(arg1, "^[0-9]+[*°o0-9abc]*[abc]s?1?[34]?", "")
if not conj_type then
if rfind(arg1, "^irreg") then
conj_type = "irreg"
arg1 = rsub(arg1, "^irreg", "")
end
if not conj_type then
-- Check for Cyrillic, a common mistake (esp. Cyrillic а)
if rfind(orig_arg1, "[абцдеѣфгчийклмнопярстувшхызёюжэщьъ]") then
error("Unrecognized conjugation type (WARNING, has Cyrillic in it): " .. orig_arg1)
else
error("Unrecognized conjugation type: " .. orig_arg1)
end
end
end
-- The * variant is conventionally written e.g. 11*b; if found in
-- the conj_type, move it to the beginning of the remainder
if rfind(conj_type, "%*") then
conj_type = rsub(conj_type, "%*", "")
arg1 = "*" .. arg1
end
arg_sets[i][1] = arg1
else
local NAMESPACE = mw.title.getCurrentTitle().nsText
if NAMESPACE == "Template" and i == 1 then
conj_type = "1a"
else
error("Must specify argument 2 (conjugation type)")
end
end
arg_sets[i]["conj_type"] = conj_type
end
return arg_sets, verb_type
end
function export.do_generate_forms(arg_sets, verb_type, old)
local set1 = arg_sets[1]
local notes = get_arg_chain(set1, "notes", "notes")
local forms = {}
local categories = {}
if not m_table.contains(all_verb_types, verb_type) then
error("Invalid verb type " .. verb_type)
end
local data = {}
data.verb_type = verb_type
--impersonal
data.impers = rfind(verb_type, "impers")
data.intr = rfind(verb_type, "intr")
data.perf = rfind(verb_type, "^pf")
data.iter = set1["iter"]
data.nopres = set1["nopres"]
data.nopast = set1["nopast"]
data.nofutr = set1["nofutr"]
data.noimpr = set1["noimpr"]
if data.iter and data.perf then
error("Iterative verbs must be imperfective")
end
data.old = old
data.has_ppp = set1["has_ppp"]
data.has_prpp = set1["has_prpp"]
data.ppp_override = false
data.prpp_override = false
for _, form in ipairs(main_to_all_verb_forms["past_pasv_part"]) do
if set1[form] then
data.ppp_override = true
break
end
end
data.main_ppp_override = not not set1["past_pasv_part"]
for _, form in ipairs(main_to_all_verb_forms["pres_pasv_part"]) do
if set1[form] then
data.prpp_override = true
break
end
end
data.internal_notes = {}
local titles = {}
for i=1,#arg_sets do
local args = arg_sets[i]
local conj_type = args.conj_type
-- Support e.g. 3oa in place of 3°a
conj_type = rsub(conj_type, "o", "°")
track("conj-" .. conj_type) -- FIXME, convert to regular category
track("conj-" .. conj_type .. "/" .. verb_type) -- FIXME, convert to regular category
data.conj_type = conj_type
data.cat_conj_types = {conj_type}
if conj_type == "irreg" then
data.title = "irregular"
else
data.title = conj_type
end
if not conjugations[conj_type] then
error("Unknown conjugation type '" .. conj_type .. "'")
end
if args[2] then
local inf, tr = com.split_russian_tr(args[2])
if rfind(inf, "[тч]ься$") then
inf = rsub(inf, "ся$", "")
tr = com.strip_tr_ending(tr, "ся")
data.refl = true
elseif rfind(inf, "ти́?сь$") then
-- 7a (вы́вестись), 7b (вести́сь) or derivative of -йти́ (разойти́сь)
inf = rsub(inf, "сь$", "")
tr = com.strip_tr_ending(tr, "сь")
data.refl = true
elseif rfind(inf, "[тч]ь$") then
-- Allow monosyllabic infinitives to be specified without stress
if com.is_monosyllabic(inf) and not rfind(inf, "^%-") then
inf, tr = com.make_ending_stressed(inf, tr)
end
end
if tr then
args[2] = inf .. "//" .. tr
else
args[2] = inf
end
end
if data.refl and data.intr then
error("Can't specify -intr with reflexive verbs")
end
if data.has_ppp or data.has_prpp then
if data.refl then
error("Can't specify has_ppp=y or has_prpp=y with reflexive verbs")
end
if not data.intr then
error("Can only specify has_ppp=y or has_prpp=y with intransitive verbs")
end
end
data.shouldnt_have_ppp = data.refl or not data.has_ppp and data.intr
data.shouldnt_have_prpp = data.refl or not data.has_prpp and data.intr
if data.ppp_override and data.shouldnt_have_ppp then
error("Shouldn't specify past passive participle with reflexive or intransitive verbs, if it's needed use has_ppp=y")
elseif data.perf and not data.shouldnt_have_ppp and not data.ppp_override then
-- possible omissions
track("perfective-no-ppp")
end
if data.prpp_override and data.shouldnt_have_prpp then
error("Shouldn't specify present passive participle with reflexive or intransitive verbs, if it's needed use has_prpp=y")
end
-- Call conjugation function. It will return a table of forms
-- as if it's the first arg set. If it is in fact the first
-- arg set, we just use the table directly (we may destructively
-- modify it if there are later arg sets, but this is OK because
-- no one else but us uses the table). Otherwise we need to
-- append the values from the table to those of the previous
-- arg sets.
local arg_set_forms = conjugations[conj_type](args, data)
if i == 1 then
forms = arg_set_forms
else
for _, all_forms in pairs(main_to_all_verb_forms) do
for _, form in ipairs(all_forms) do
if arg_set_forms[form] then
append_to_arg_chain(forms, all_forms[1], all_forms[1],
arg_set_forms[form])
end
end
end
end
m_table.insertIfNot(titles, data.title)
if conj_type == "irreg" then
table.insert(categories, "Russian irregular verbs")
end
-- For irregular verbs, if the verb didn't set a specific cat_conj_type,
-- it will be the same as the conj_type and be "irreg". In that case,
-- replace it with the title, which might be a proper conjugation type
-- like 4a or 8c/b (and remove anything starting with a slash, to
-- account for cases like 8c/b). After doing this, the cat_conj_type
-- might still begin with "irreg" (for sufficiently irregular verbs that
-- they can't be assigned to any of the normal classes), in which case
-- we don't create a class for the verb beyond "Russian irregular verbs"
-- (set above).
if data.cat_conj_types[1] == "irreg" then
data.cat_conj_types = {rsub(rsub(data.title, "/.*", ""), "[*⑨]", "")}
end
for _, cat_conj_type in ipairs(data.cat_conj_types) do
if not rmatch(cat_conj_type, "^irreg") then
local class_num = rmatch(cat_conj_type, "^([0-9]+)")
assert(class_num and class_num ~= "")
table.insert(categories, "Russian class " .. class_num .. " verbs")
table.insert(categories, "Russian class " .. cat_conj_type .. " verbs")
end
end
end
data.title = "class " .. table.concat(titles, " // ") ..
(data.perf and " perfective" or " imperfective") ..
(data.refl and " reflexive" or data.intr and " intransitive" or " transitive") ..
(data.impers and " impersonal" or "") ..
(data.iter and " iterative" or "")
-- Perfective/imperfective
if data.perf then
table.insert(categories, "Russian perfective verbs")
else
table.insert(categories, "Russian imperfective verbs")
end
handle_forms_and_overrides(set1, forms, data)
local function remove_pseudo(str)
local toremove = set1["asif_prefix"] or PSEUDOCONS
if str == nil then
return str
end
str = rsub(str, "^%-" .. toremove, "-")
-- also handle prefix after space, e.g. in futures
str = rsub(str, " %-" .. toremove, " -")
return str
end
-- Remove pseudoconsonant we may have inserted; if no ending, insert
-- "(no suffix)".
for k in pairs(forms) do
if forms[k] == "-" .. PSEUDOCONS or type(forms[k] == "table") and forms[k][1] == "-" .. PSEUDOCONS then
-- Make the translit empty.
forms[k] = {"(no suffix)", ""}
else
if type(forms[k]) == "table" then
forms[k][1] = remove_pseudo(forms[k][1])
forms[k][2] = remove_pseudo(forms[k][2])
else
forms[k] = remove_pseudo(forms[k])
end
end
end
-- Catch errors in verb arguments that lead to the infinitive not matching
-- page title, but only in the main namespace.
local NAMESPACE = mw.title.getCurrentTitle().nsText
if NAMESPACE == "" then
local PAGENAME = mw.loadData("Modül:başlık başı/veri").pagename
for _, form in ipairs(main_to_all_verb_forms["infinitive"]) do
local inf = extract_russian_tr(forms[form])
if inf then
inf, _ = m_table_tools.separate_notes(inf) -- remove any footnote symbols (e.g. грясти́)
local inf_noaccent = com.remove_accents(inf)
if inf ~= "-" then
if data.refl then
if rfind(inf_noaccent, "и$") then
inf_noaccent = inf_noaccent .. "сь"
inf = inf .. "сь"
else
inf_noaccent = inf_noaccent .. "ся"
inf = inf .. "ся"
end
end
if inf_noaccent ~= PAGENAME then
error("Infinitive " .. inf .. " doesn't match pagename " ..
PAGENAME)
end
end
end
end
end
-- Reflexive/intransitive/transitive
if set1["reflex_stress"] then
track("reflex-stress")
end
if data.refl then
local reflex_stress = set1["reflex_stress"] or data.default_reflex_stress -- "ся́"
make_reflexive(forms, reflex_stress and reflex_stress ~= "n" and
reflex_stress ~= "no")
table.insert(categories, "Russian reflexive verbs")
elseif data.intr then
table.insert(categories, "Russian intransitive verbs")
else
table.insert(categories, "Russian transitive verbs")
end
-- Impersonal
if data.impers then
table.insert(categories, "Russian impersonal verbs")
end
-- Iterative
if data.iter then
table.insert(categories, "Russian iterative verbs")
end
if data.old then
make_pre_reform(forms)
end
finish_generating_forms(forms, data)
return forms, data.title, data.perf, data.intr or data.refl, data.impers, categories, notes, data.internal_notes
end
local function fetch_forms(forms)
local function fetch_one_form(form)
local val = forms[form]
local ru, tr
if type(val) == "table" then
ru, tr = val[1], val[2]
elseif type(val) == "string" and val ~= "" and val ~= "-" then
ru = val
end
if not ru then
return nil
end
local ruentry = m_table_tools.get_notes(ru)
local trentry, trnotes
if tr then
trentry, trnotes = m_table_tools.get_notes(tr)
end
-- There shouldn't be any links.
-- ruentry = m_links.remove_links(ruentry)
-- There shouldn't be any vertical bars.
-- ruentry = rsub(ruentry, "|", "<!>")
-- if trentry then
-- trentry = rsub(trentry, "|", "<!>")
-- end
return trentry and ruentry .. "//" .. trentry or ruentry
end
local vals = {}
for _, proplist in ipairs(all_verb_forms) do
local vallist = {}
local propname = proplist[1]
if not rfind(propname, "^pres_futr") then
for _, prop in ipairs(proplist) do
local val = fetch_one_form(prop)
if val then
table.insert(vallist, val)
end
end
if #vallist > 0 then
table.insert(vals, propname .. "=" .. table.concat(vallist, ","))
end
end
end
return table.concat(vals, "|")
end
function export.generate_forms(frame)
local arg_sets, verb_type = split_args_handle_aliases(frame)
local old = frame.args["old"] or arg_sets[1]["old"]
local forms = export.do_generate_forms(arg_sets, verb_type, old)
return fetch_forms(forms)
end
-- The main entry point.
-- This is the only function that can be invoked from a template.
function export.show(frame)
local arg_sets, verb_type = split_args_handle_aliases(frame)
local old = frame.args["old"] or arg_sets[1]["old"]
local arg_sets_clone
if test_new_ru_verb_module then
-- arg_sets may be modified by do_generate_forms()
arg_sets_clone = mw.clone(arg_sets)
end
local forms, title, perf, intr, impers, categories, notes, internal_notes =
export.do_generate_forms(arg_sets, verb_type, old)
-- Test code to compare existing module to new one.
if test_new_ru_verb_module then
local m_new_ru_verb = require("Modül:User:Benwing2/ru-verb")
local newforms, newtitle, newperf, newintr, newimpers, newcategories, newnotes, newinternal_notes =
m_new_ru_verb.do_generate_forms(arg_sets_clone, verb_type, old)
local vals = mw.clone(forms)
vals.title = title
vals.perf = perf
vals.intr = intr
vals.impers = impers
vals.categories = categories
vals.notes = notes
vals.internal_notes = internal_notes
local newvals = mw.clone(newforms)
newvals.title = newtitle
newvals.perf = newperf
newvals.intr = newintr
newvals.impers = newimpers
newvals.categories = newcategories
newvals.notes = newnotes
newvals.internal_notes = newinternal_notes
local difconj = false
for _, proplist in ipairs(all_verb_props) do
for _, prop in ipairs(proplist) do
local val = vals[prop]
local newval = newvals[prop]
-- deal with impedance mismatch between old style (plain string)
-- and new style (Russian/translit array), and empty string vs. nil
if not m_table.contains(non_form_props, prop) then
if type(val) == "string" then val = {val} end
if val and val[1] == "" then val = nil end
if type(newval) == "string" then newval = {newval} end
if newval and newval[1] == "" then newval = nil end
end
-- Ignore changes in pres_futr_*, which aren't displayed
if not forms_equal(val, newval) and not rfind(prop, "^pres_futr") then
-- Uncomment this to display the particular case and
-- differing forms.
--error(prop .. " " .. (val and concat_vals(val) or "nil") .. " || " .. (newval and concat_vals(newval) or "nil"))
difconj = true
break
end
end
end
track(difconj and "different-conj" or "same-conj")
end
return make_table(forms, title, perf, intr, impers, notes, internal_notes, old) .. m_utilities.format_categories(categories, lang)
end
--[=[
Functions for working with stems, paradigms, Russian/translit
]=]
-- Combine a stem with optional translit with an ending and possibly a foonote
-- symbol (which may be a tuple {RUNOTES, TRNOTES}), returning a tuple
-- {RUSSIAN, TR}.
local function combine(stem, tr, ending, note)
if not ending or ending == "-" then
return nil
end
local arg_status
ending, arg_status = strip_arg_status_prefix(ending)
if stem ~= "" and com.is_stressed(ending) then
stem, tr = com.make_unstressed_once(stem, tr)
end
stem = arg_status .. stem
if not note then
return com.concat_russian_tr(stem, tr, ending, nil, "dopair")
else
local runotes, trnotes = extract_russian_tr(note)
local ruending, trending = com.concat_russian_tr(ending, nil, runotes, trnotes)
return com.concat_russian_tr(stem, tr, ruending, trending, "dopair")
end
end
-- Set an individual form PARAM in FORMS with value based on stem STEM (with
-- optional translit TR), ENDINGS (either a single string or a list of strings)
-- and NOTE (nil, a string, or a tuple {RUSSIAN, TR}). If there are multiple
-- endings listed, they will go successively into PARAM, PARAM2, etc.
-- (e.g. past_m, past_m2, etc.).
local function set_form(forms, param, stem, tr, endings, note)
if type(endings) ~= "table" then
endings = {endings}
end
local entries = {}
for _, val in ipairs(endings) do
m_table.insertIfNot(entries, combine(stem, tr, val, note))
end
set_arg_chain(forms, param, param, entries)
end
-- Append to an individual form PARAM in FORMS with value based on stem STEM
-- (with optional translit TR), ENDINGS (either a single string or a list of
-- strings) and NOTE (nil, a string, or a tuple {RUSSIAN, TR}). If there are
-- multiple endings listed, they will go successively into PARAM, PARAM2, etc.
-- (e.g. past_m, past_m2, etc.), provided there are no existing forms already
-- present. Duplicate forms aren't inserted.
local function append_form(forms, param, stem, tr, endings, note)
if type(endings) ~= "table" then
endings = {endings}
end
for _, val in ipairs(endings) do
append_to_arg_chain(forms, param, param, combine(stem, tr, val, note))
end
end
local function append_pres_futr(forms, stem, tr,
sg1, sg2, sg3, pl1, pl2, pl3, note)
append_form(forms, "pres_futr_1sg", stem, tr, sg1, note)
append_form(forms, "pres_futr_2sg", stem, tr, sg2, note)
append_form(forms, "pres_futr_3sg", stem, tr, sg3, note)
append_form(forms, "pres_futr_1pl", stem, tr, pl1, note)
append_form(forms, "pres_futr_2pl", stem, tr, pl2, note)
append_form(forms, "pres_futr_3pl", stem, tr, pl3, note)
end
local function append_participles_2stem(forms,
pres_stem, pres_tr, past_stem, past_tr,
pres_actv, pres_pasv, pres_adv, past_actv, past_adv, past_adv_short,
pres_note, past_note)
append_form(forms, "pres_actv_part", pres_stem, pres_tr, pres_actv, pres_note)
append_form(forms, "pres_pasv_part", pres_stem, pres_tr, pres_pasv, pres_note)
append_form(forms, "pres_adv_part", pres_stem, pres_tr, pres_adv, pres_note)
append_form(forms, "past_actv_part", past_stem, past_tr, past_actv, past_note)
append_form(forms, "past_adv_part", past_stem, past_tr, past_adv, past_note)
append_form(forms, "past_adv_part_short", past_stem, past_tr, past_adv_short, past_note)
end
local function append_participles(forms, stem, tr,
pres_actv, pres_pasv, pres_adv, past_actv, past_adv, past_adv_short, note)
append_participles_2stem(forms, stem, tr, stem, tr,
pres_actv, pres_pasv, pres_adv, past_actv, past_adv, past_adv_short, note, note)
end
local function set_ppp(forms, stem, tr, ending, note)
set_form(forms, "past_pasv_part", stem, tr, ending, note)
end
local function append_ppp(forms, stem, tr, ending, note)
append_form(forms, "past_pasv_part", stem, tr, ending, note)
end
local function append_imper(forms, stem, tr, sg, pl, note)
append_form(forms, "impr_sg", stem, tr, sg, note)
append_form(forms, "impr_pl", stem, tr, pl, note)
end
local function set_past(forms, stem, tr, m, f, n, pl, note)
set_form(forms, "past_m", stem, tr, m, note)
set_form(forms, "past_f", stem, tr, f, note)
set_form(forms, "past_n", stem, tr, n, note)
set_form(forms, "past_pl", stem, tr, pl, note)
end
local function append_past(forms, stem, tr, m, f, n, pl, note)
append_form(forms, "past_m", stem, tr, m, note)
append_form(forms, "past_f", stem, tr, f, note)
append_form(forms, "past_n", stem, tr, n, note)
append_form(forms, "past_pl", stem, tr, pl, note)
end
-- Prepend a possibly-stressed prefix to all forms; if prefix is stressed,
-- destress the forms before prepending. FIXME: Should support explicit
-- manual translit.
local function prepend_prefix(forms, prefix, pre_two_cons_prefix)
pre_two_cons_prefix = pre_two_cons_prefix or prefix
local stressed_prefix = com.is_stressed(prefix)
for key, form in pairs(forms) do
local ru, tr = extract_russian_tr(form)
if tr then
error("Explicit manual translit not yet supported")
end
-- check for empty string, dashes and nil's
if ru and ru ~= "" and ru ~= "-" then
if stressed_prefix then
ru = com.make_unstressed(ru)
end
if rfind(ru, "^[" .. com.cons .. "][" .. com.cons .. "]") then
forms[key] = pre_two_cons_prefix .. ru
else
forms[key] = prefix .. ru
end
end
end
end
-- Apply regex substitution FROM -> TO to all forms. FIXME: Should support
-- explicit manual translit.
local function rsub_forms(forms, from, to)
for key, form in pairs(forms) do
local ru, tr = extract_russian_tr(form)
if tr then
error("Explicit manual translit not yet supported")
end
-- check for empty string, dashes and nil's
if ru and ru ~= "" and ru ~= "-" then
forms[key] = rsub(ru, from, to)
end
end
end
local variant_to_title = {
["[(2)]"] = "[②]",
["(2)"] = "②",
["[(3)]"] = "[③]",
["(3)"] = "③",
["[(4)]"] = "[④]",
["(4)"] = "④",
["[(5)]"] = "[⑤]",
["(5)"] = "⑤",
["[(6)]"] = "[⑥]",
["(6)"] = "⑥",
["[(7)]"] = "[⑦]",
["(7)"] = "⑦",
["[(8)]"] = "[⑧]",
["(8)"] = "⑧",
["(9)"] = "⑨",
["щ"] = "(-щ-)",
["ё"] = "(-ё-)",
["о"] = "(-о-)",
["жд"] = "(-жд-)",
}
local function prepare_past_stress_indicator(past_stress)
if not past_stress or past_stress == "a" then
return ""
end
past_stress = rsub(past_stress, "%(1%)", "①")
past_stress = rsub(past_stress, "(.),%1①", "%1[①]")
past_stress = rsub(past_stress, "(.)①,%1", "%1[①]")
past_stress = rsub(past_stress, "''", "''")
past_stress = rsub(past_stress, "-nd", "")
past_stress = rsub(past_stress, "-bd", "")
return "/" .. past_stress
end
local function parse_variants(data, variants, allowed)
-- Need to set these to nil in case of multiple arg sets
data.imper_variant = nil
data.var4 = nil
data.var5 = nil
data.var6 = nil
data.ppp = nil
data.var9 = nil
data.shch = nil
data.yo = nil
data.o = nil
data.zhd = nil
data.star = nil
variants = variants or ""
local variant_title = ""
if variants ~= "" then -- short-circuit the most common case
-- Only recognize * variant for long-variant prefix at the beginning
-- of the variant code block (where it gets moved if it's in the
-- middle of the conjugation type, as it normally is) because a *
-- also occurs in b*, a past stress variant code.
if rfind(variants, "^%*") then
-- Specify that the present/future tense has extra -о in the prefix:
-- types 9*b (e.g. растере́ть, futr_1sg разотру́) and 11*b (e.g. изли́ть,
-- futr_1sg изолью́). It can also occur with type 7*b (in -че́сть,
-- e.g. счесть, сочту́; расче́сть, разочту́) and type 8*b (in -же́чь, e.g.
-- сжечь, сожгу́) but these are always irregular and require the
-- present tense to be specified explicitly. It can also occur
-- with type 14*b (e.g. размя́ть, разомну́; сжать, сожну́; подожа́ть, подожму́),
-- but for these verbs the present tense is unpredictable and
-- must be specified explicitly.
--
-- This can also occur where the extra -о occurs in the infinitive
-- and past, but not the present tense: type 5*c (in -гна́ть, e.g.
-- согна́ть, сгоню́; разогна́ться, разгоню́сь), type 6*c (in -стла́ть, e.g.
-- подостла́ть, подстелю́; разостла́ть, расстелю́), type 6°*c
-- (in -зва́ть, -бра́ть, -дра́ть, e.g. подозва́ть, подзову́; разобра́ться, разберу́сь);
-- but these are always irregular and require the present tense
-- to be specified explicitly.
if not m_table.contains(allowed, "*") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.star = true
variants = rsub(variants, "^*", "")
end
-- Allow brackets around both 5 and 6, e.g. [(5)(6)]
variants = rsub(variants, "%[(%([56]%))(%([56]%))%]", "[%1][%2]")
-- Handle all remaining variants. We do this using an rsub() function,
-- where we pull out, parse and remove each variant in turn.
variants = rsub(variants, "(%[?%(?[23456789ёощийьж+][дp]?%)?%]?)", function(var)
if m_table.contains({"(2)", "[(2)]", "(3)", "[(3)]", "и", "й", "ь"}, var) then
if data.imper_variant then
error("Saw two imperative variants " .. data.imper_variant ..
" and " .. var)
end
local is_23 = m_table.contains({"(2)", "[(2)]", "(3)", "[(3)]"}, var)
if is_23 and not m_table.contains(allowed, "23") or
not is_23 and not m_table.contains(allowed, "и") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.imper_variant = var
elseif m_table.contains({"(4)", "[(4)]"}, var) then
if data.var4 then
error("Saw two variant-4 specs " .. data.var4 .. " and " .. var)
end
if not m_table.contains(allowed, "4") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.var4 = var == "(4)" and "req" or "opt"
elseif m_table.contains({"(5)", "[(5)]"}, var) then
if data.var5 then
error("Saw two variant-5 specs " .. data.var5 .. " and " .. var)
end
if not m_table.contains(allowed, "5") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.var5 = var == "(5)" and "req" or "opt"
elseif m_table.contains({"(6)", "[(6)]"}, var) then
if data.var6 then
error("Saw two variant-6 specs " .. data.var6 .. " and " .. var)
end
if not m_table.contains(allowed, "6") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.var6 = var == "(6)" and "req" or "opt"
elseif m_table.contains({"(7)", "[(7)]", "(8)", "[(8)]", "+p"}, var) then
if data.shouldnt_have_ppp then
error("Shouldn't specify past passive participle with reflexive or intransitive verbs, if it's needed use has_ppp=y")
end
if data.ppp then
error("Saw two past passive participle specs " .. data.ppp .. " and " .. var)
end
if m_table.contains({"(7)", "[(7)]"}, var) and not m_table.contains(allowed, "7") or
m_table.contains({"(8)", "[(8)]"}, var) and not m_table.contains(allowed, "8") or
var == "+p" and not m_table.contains(allowed, "+p") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.ppp = var
elseif var == "(9)" then
if data.var9 then
error("Saw (9) twice")
end
if not m_table.contains(allowed, "9") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.var9 = true
elseif var == "щ" then
-- specify that the 1sg pres/futr and past passive participle
-- of class 4/5/6 verbs iotate -т to -щ instead of -ч; cf.
-- похи́тить (похи́щу) (4a), защити́ть (защищу́) (4b),
-- поглоти́ть (поглощу́) (4c), клевета́ть (клевещу́) (6c)
if data.shch then
error("Saw щ twice")
end
if not m_table.contains(allowed, "щ") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.shch = "щ"
elseif var == "ё" then
-- specify that the past passive participle has ё instead of е
if data.yo then
error("Saw ё twice")
end
if not m_table.contains(allowed, "ё") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.yo = true
elseif var == "о" then
-- specify that the past passive participle has о instead of е
-- NOTE: Not currently allowed as a user-specifiable variant
if data.o then
error("Saw о twice")
end
if not m_table.contains(allowed, "о") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.o = true
elseif var == "жд" then
-- specify that the past passive participle of class 4/5/6 verbs
-- iotates -д to -жд instead of -ж
if data.zhd then
error("Saw жд twice")
end
if not m_table.contains(allowed, "жд") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.zhd = true
else
error("Unrecognized variant spec: " .. var)
end
variant_title = variant_title .. (variant_to_title[var] or "")
return ""
end)
variant_title = rsub(variant_title, "%[⑤%]%[⑥%]", "[⑤⑥]")
end
if variants ~= "" and not m_table.contains(allowed, "past") then
error("Past stress " .. variants .. " not allowed for this verb class")
end
if data.yo and not data.ppp then
error("Variant ё specified without calling for past passive participle")
end
if data.o and not data.ppp then
error("Variant о specified without calling for past passive participle")
end
if data.zhd and not data.ppp then
error("Variant жд specified without calling for past passive participle")
end
if data.perf and not data.ppp and not data.ppp_override and not data.shouldnt_have_ppp and not data.impers then
error("For perfective transitive verbs, need to specify past passive participle by variant or override; use |ppp=- if no such participle")
end
data.past_stress = variants == "" and "a" or rsub(variants, "/", "")
data.title = data.title ..
prepare_past_stress_indicator(data.past_stress) ..
variant_title
if data.star then
data.title = rsub(data.title, "^([0-9]+°?)", "%1*")
end
-- If there's an override of past_pasv_part, generate the normal participle
-- so we can determine whether the override is irregular. But set a flag
-- so we erase any automatically generated past passive participles that
-- aren't overridden. This happens for example in обнять, where there are
-- two automatically generated past passive participles but a single
-- ppp=о́внятый override.
if not data.ppp and data.main_ppp_override then
data.ppp = "+p"
data.ppp_auto_generated = true
end
end
local function set_past_by_stress(forms, past_stresses, prefix, prefixtr, base,
basetr, args, data, no_pastml, note)
-- If there isn't manual translit for the prefix, we need to supply it
-- if there's manual translit for the base, because we often concatenate
-- prefix to the base.
local prefixtr = prefixtr or basetr and com.translit(prefix)
for _, past_stress in ipairs(rsplit(past_stresses, ",")) do
local pastml = no_pastml and "" or "л"
local stressed_prefix, stressed_prefixtr
if prefix == "пере" then
stressed_prefix = "пе́ре"
stressed_prefixtr = "pe" .. AC .. "re"
elseif prefix == "раз" then
stressed_prefix = "ро́з"
stressed_prefixtr = "ro" .. AC .. "z"
elseif prefix == "рас" then
-- Does this ever occur?
stressed_prefix = "ро́с"
stressed_prefixtr = "ro" .. AC .. "s"
elseif prefix == "ра" and rfind(base, "^[сз]") then
-- Type 9/11/14/16 with automatically split prefix; may never happen.
stressed_prefix = "ро́"
stressed_prefixtr = "ro" .. AC
else
stressed_prefix, stressed_prefixtr =
com.make_ending_stressed(prefix, prefixtr)
end
-- Normally the base is stressed and the prefix isn't, but it could
-- be the other way around, e.g. in запереть and запереться, where
-- the stress on the prefix is used to get prefix-stressed participles.
-- To deal with this, we usually combine base and prefix unchanged,
-- but in combination with stressed_prefix we always want an unstressed
-- base, and when a stressed -ся́ is called for, we want both of them
-- unstressed.
local ubase, ubasetr = com.make_unstressed(base, basetr)
local uprefix, uprefixtr = com.make_unstressed(prefix, prefixtr)
-- If the prefix is stressed (вы́-), we need to use the unstressed base to avoid getting double stress.
local prefixbase = com.is_stressed(prefix) and prefix .. ubase or prefix .. base
local prefixbasetr = basetr and (com.is_stressed(prefix) and prefixtr .. ubasetr or prefixtr .. basetr)
local stressed_prefix_ubase = stressed_prefix .. ubase
local stressed_prefix_ubasetr = ubasetr and stressed_prefixtr .. ubasetr
local uprefixubase = uprefix .. ubase
local uprefixubasetr = ubasetr and uprefixtr .. ubasetr
if past_stress == "a" then
-- (/под/пере/при/по)забы́ть, раздобы́ть, (/пере/по)забы́ться
append_past(forms, prefixbase, prefixbasetr, pastml,
"ла", "ло", "ли", note)
elseif past_stress == "a(1)" then
-- вы́дать, вы́быть, etc.; also проби́ть with the meaning
-- "to strike (of a clock)" (which is a(1),a or similar)
append_past(forms, stressed_prefix_ubase,
stressed_prefix_ubasetr, pastml, {}, "ло", "ли", note)
-- Retraction to prefix doesn't happen in feminine singular, see the
-- bottom of page 81 of Zaliznyak's 1980 grammar.
append_past(forms, prefixbase, prefixbasetr, {}, "ла", {}, {}, note)
elseif past_stress == "b" then
append_past(forms, prefixbase, prefixbasetr, pastml,
"ла́", "ло́", "ли́", note)
elseif past_stress == "b*" then
if not data.refl then
error("Only reflexive verbs can take past stress variant " .. past_stress)
end
-- See comment in type c''. We want to see whether we actually
-- added an argument, and if so, where.
local argset = append_to_arg_chain(forms, "past_m", "past_m",
combine(uprefixubase, uprefixubasetr, pastml .. (note or "")))
if argset and not args[argset] and not data.impers then
data.default_reflex_stress = "ся́"
end
append_past(forms, prefixbase, prefixbasetr, {}, "ла́", "ло́", "ли́", note)
elseif past_stress == "c" then
-- изда́ть, возда́ть, сдать, пересозда́ть, воссозда́ть, надда́ть, наподда́ть, etc.
-- быть, избы́ть, сбыть
-- клясть, закля́сть
append_past(forms, prefixbase, prefixbasetr, pastml, "ла́", "ло", "ли", note)
elseif past_stress == "c(1)" then
-- прибы́ть, убы́ть
-- прокля́сть
-- also, c(1),c:
-- зада́ть, обда́ть, отда́ть, подда́ть, переда́ть (пе́редал), преда́ть, прода́ть, разда́ть (ро́здал), созда́ть, etc.
-- отбы́ть, побы́ть, пробы́ть
-- also, c,c(1):
-- добы́ть
-- Because the prefix may vary depending on stress (esp. for
-- раздать [ро́здал/раздала́]), we need to separate the endings that
-- take the stressed prefix and those that take the unstressed
-- prefix with stressed ending.
append_past(forms, stressed_prefix_ubase, stressed_prefix_ubasetr,
pastml, {}, "ло", "ли", note)
append_past(forms, prefixbase, prefixbasetr, {}, "ла́", {}, {}, note)
elseif past_stress == "c'" then
-- дать
--same with "взять"
append_past(forms, prefixbase, prefixbasetr,
pastml, "ла́", {"ло", "ло́"}, "ли", note)
elseif past_stress == "c''" or past_stress == "c''-nd" or past_stress == "c''-bd" then
if not data.refl then
error("Only reflexive verbs can take past stress variant " .. past_stress)
end
-- c'' (-ся́ dated): all verbs in -да́ться; избы́ться, сбы́ться; all verbs in -кля́сться
-- c''-nd (-ся́ not dated): various verbs in -ня́ться per Zaliznyak
-- c''-bd (-ся́ becoming dated): various verbs in -ня́ться per ruwikt
local note_symbol = past_stress == "c''-nd" and "" or
next_note_symbol(data)
append_past(forms, prefixbase, prefixbasetr,
pastml, "ла́", {"ло́", "ло"}, {"ли́", "ли"})
-- We want to see whether we actually added an argument, and if
-- so, where.
local argset = append_to_arg_chain(forms, "past_m", "past_m",
combine(uprefixubase, uprefixubasetr, pastml .. note_symbol .. (note or "")))
-- Only display the internal note and set the default reflex
-- stress if the form with the note will be displayed (i.e. not
-- impersonal, and no override of this form). FIXME: We should
-- have a more general mechanism to check for this.
if not args[argset] and not data.impers then
local note = past_stress == "c''" and note_symbol .. " Dated." or
past_stress == "c''-bd" and note_symbol .. " Becoming dated." or
nil
if note then
m_table.insertIfNot(data.internal_notes, note)
end
data.default_reflex_stress = "ся́"
end
elseif past_stress == "c''(1)" then
-- запере́ться
-- See comment in type c''. We want to see whether we actually
-- added an argument, and if so, where.
local argset = append_to_arg_chain(forms, "past_m", "past_m",
combine(uprefixubase, uprefixubasetr, pastml .. (note or "")))
if argset and not args[argset] and not data.impers then
data.default_reflex_stress = "ся́"
end
append_past(forms, prefixbase, prefixbasetr, {}, "ла́", "ло́", "ли́", note)
append_past(forms, stressed_prefix_ubase, stressed_prefix_ubasetr,
pastml, {}, "ло", "ли", note)
else
error("Unrecognized past-stress value " .. past_stress .. ", should be a, a(1), b, b*, c, c(1), c', c'', c''-nd, c''-bd, c''(1) or comma-separated list")
end
end
end
-- Split a verb stem into a possibly multisyllabic prefix (пере-, переиз-,
-- воссоз-, повы́-, etc.) and a single-syllable main verb (-тер-, -ли́-, -гре́-,
-- etc.). Normally the splitting is done simply by looking for alternating
-- vowel/consonant sequences, meaning that e.g. разгре́ will be split as
-- ра + згре́ and растер will be split as ра + стер. For most purposes, this
-- doesn't matter, but for the * variant it does; in that case, if it is
-- known that the main verb base always begins with a single consonant,
-- specify SINGLE_CONS_BASE and then e.g. растер will be split as рас + тер.
local function split_monosyllabic_main_verb(ru, tr, single_cons_base)
local rusyl, trsyl = com.split_syllables(ru, tr)
local last_ru = rusyl[#rusyl]
local last_tr = trsyl and trsyl[#trsyl]
table.remove(rusyl, #rusyl)
local prefix_ru = table.concat(rusyl, "")
local prefix_tr
if trsyl then
table.remove(trsyl, #trsyl)
prefix_tr = table.concat(trsyl, "")
end
if single_cons_base then
local cons_to_move, rest = rmatch(last_ru, "^([" .. com.cons .. "]+)([" .. com.cons .. "].*)$")
if cons_to_move then
prefix_ru = prefix_ru .. cons_to_move
last_ru = rest
end
if last_tr then
cons_to_move, rest = rmatch(last_tr, "^([" .. com.tr_cons .. "]+)([" .. com.tr_cons .. "].*)$")
if cons_to_move then
prefix_tr = prefix_tr .. cons_to_move
last_tr = rest
end
end
end
return prefix_ru, prefix_tr, last_ru, last_tr
end
local function split_known_main_verb(arg, mains)
-- Given an argument (which may be RUSSIAN//TR), split the prefix from
-- the main verb, which should be one of the verbs in MAINS (which can be
-- a -- single verb or a list of verbs, but in either case all verbs
-- need to be stressed). This correctly handles stressed and unstressed
-- prefixes.
local stem, tr = com.split_russian_tr(arg)
if type(mains) ~= "table" then
mains = {mains}
end
for _, main in ipairs(mains) do
assert(com.is_stressed(main))
if rfind(stem, main .. "$") then
stem, tr = com.strip_ending(stem, tr, main)
if com.is_stressed(stem) then
error("Two stresses in " .. arg)
end
return stem, tr, main, nil
end
main = com.make_unstressed_once(main)
if rfind(stem, main .. "$") then
stem, tr = com.strip_ending(stem, tr, main)
if com.is_unstressed(stem) then
error("No stresses in " .. arg)
end
return stem, tr, main, nil
end
end
if #mains == 1 then
error("Argument " .. arg .. " doesn't end in " .. mains[1])
else
error("Argument " .. arg .. " doesn't end in any of " .. table.concat(mains, ","))
end
end
local function construct_long_prefix_variant(prefix)
if rfind(prefix, "рас$") then
return rsub(prefix, "рас$", "разо")
end
if rfind(prefix, "ис$") then
return rsub(prefix, "ис$", "изо")
end
if rfind(prefix, "вс$") then
return rsub(prefix, "вс$", "взо")
end
return prefix .. "о"
end
local function append_imper_by_variant(forms, stem, tr, variant, verbclass, note)
local vowel_stem = is_vowel_stem(stem)
local stress = rmatch(verbclass, "([abc])$")
if not stress then
error("Unrecognized verb class '" .. verbclass .. "', should end with a, b or c")
end
local longend = stress == "a" and "и" or "и́"
local shortend = vowel_stem and (com.is_unstressed(stem) and "́й" -- accent on previous vowel
or "й") or "ь"
local function append_short_imper()
append_imper(forms, stem, tr, shortend, shortend .. "те", note)
end
local function append_long_imper()
append_imper(forms, stem, tr, longend, longend .. "те", note)
end
if variant and variant ~= "" then
track("explicit-imper")
track("explicit-imper/" .. verbclass)
end
if variant == "(2)" then
-- use short variants with вы́- (for these verbs, long is expected)
if not rfind(stem, "^вы́-") then
error("Should only specify imperative variant (2) with verbs in вы́-, not " .. stem)
end
append_short_imper()
elseif variant == "[(2)]" then
-- use both long and short variants
append_long_imper()
append_short_imper()
elseif variant == "(3)" then
-- long in singular, short in plural
append_imper(forms, stem, tr, longend, shortend .. "те", note)
elseif variant == "[(3)]" then
-- long and short in singular, short in plural
append_imper(forms, stem, tr, {longend, shortend}, shortend .. "те", note)
elseif variant == "ь" or variant == "й" then
-- short variants wanted
append_short_imper()
elseif variant == "и" then
-- long variants wanted
append_long_imper()
else
assert(not variant or variant == "")
if vowel_stem then
if verbclass == "4b" or verbclass == "4c" or (
verbclass == "4a" and rfind(stem, "^вы́-")) then
append_long_imper()
else
append_short_imper()
end
else -- consonant stem
if stress == "b" or stress == "c" then
append_long_imper()
else
assert(stress == "a")
-- "и" after вы́-, e.g. вы́садить
-- "и" after final щ, e.g. тара́щиться (although this particular
-- verb has a [(3)] spec attached to it)
if rfind(stem, "^вы́-") or rfind(stem, "щ$") or
-- "и" after two consonants in a row (мо́рщить, зафре́ндить)
rfind(stem, "[бвгджзклмнпрстфхцчшщь][бвгджзклмнпрстфхцчшщ]$") then
append_long_imper()
else
-- "ь" after a single consonant (бре́дить)
append_short_imper()
end
end
end
end
end
-- Compute the past passive participle stem for verbs that require it to be
-- iotated (class 4, and class 5 in -еть).
local function iotated_ppp(data, stem, tr)
local iotated_stem, iotated_tr
if data.zhd then
local subbed
iotated_stem, subbed = rsubb(stem, "з?д$", "жд")
if not subbed then
error("Variant -жд- specified but stem " .. stem .. " doesn't end in -д")
end
if tr then
iotated_tr, subbed = rsubb(tr, "z?d$", "žd")
if not subbed then
error("Variant -жд- specified but translit " .. tr .. " doesn't end in -d")
end
end
else
iotated_stem, iotated_tr = com.iotation(stem, tr, data.shch)
end
return iotated_stem, iotated_tr
end
-- Set the past passive participle of verbs where the stress is moved left
-- from the ending by one syllable (if possible) if the ending is stressed,
-- otherwise left as-is (except class 1a in -е́ть, which has ending-stressed
-- -ённый). This applies to classes 1, 2, 3, 5, 6, 10 and 13. The stem comes
-- from the infinitive, iotated in class 5 -еть/-ѣть verbs. The participle
-- ending is -анный/-янный for verbs in -ать/-ять, -енный/-ённый for verbs in -еть,
-- -ѣнный/-ѣ̈нный for verbs in -ѣть, otherwise -тый.
local function set_moving_ppp(forms, data)
if not data.ppp then
return
end
-- NOTE: No need to check for multiple infinitives because no verbs have
-- them normally, and we probably don't want to check for overrides here
-- (e.g. it would break достичь and related verbs, which have participles
-- based on the infinitive достигнуть).
local infinitive, infinitivetr = extract_russian_tr(forms["infinitive"])
local stem, ending = rmatch(infinitive, "^(.*)([аеѣоуя]́?ть)$")
if not stem then
error("Strange infinitive " .. infinitive .. " when trying to create participle")
end
local tr, endingtr
if infinitivetr then
if ending == "ять" or ending == "я́ть" then
tr, endingtr = rmatch(infinitivetr, "^(.*)(ja" .. AC .. "?tʹ)$")
else
tr, endingtr = rmatch(infinitivetr, "^(.*)([aeěou]" .. AC .. "?tʹ)$")
end
if not tr then
error("Translit " .. infinitivetr .. " doesn't match Cyrillic " ..
infinitive)
end
end
local ending_vowel = usub(ending, 1, 1)
local ppptype = data.ppp
if com.is_nonsyllabic(stem) then
-- e.g. 3b гну́ть (гну́тый); but not -нуть (type 3a, as a suffix)
ppptype = "(7)"
end
if m_table.contains({"5a", "5b", "5c"}, data.conj_type) and
(ending_vowel == "е" or ending_vowel == "ѣ") then
stem, tr = iotated_ppp(data, stem, tr)
end
if not com.is_stressed(stem) then
stem, tr = com.make_ending_stressed(stem, tr)
end
if data.o then
-- цев -> цо́в, e.g. (об)лицева́ть -> (об)лицо́ванный
stem = rsub(stem, "е́", "о́") -- Cyrillic
if tr then
tr = rsub(tr, "e" .. AC, "o" .. AC) -- Latin
end
elseif data.yo then
-- ё occurs with e.g. 1a наверста́ть (навёрстанный)
-- ё occurs with e.g. 3b поверну́ть (повёрнутый)
-- ё occurs with e.g. 5b лежа́ть (лёжанный) but not with 5c держа́ть
-- (де́ржанный)
-- ё occurs always with class 2 in -ева́ть, e.g.
-- (за)тушева́ть ((за)тушёванный) and (за)клева́ть ((за)клёванный)
local subbed
stem, subbed = rsubb(stem, "е́", "ё") -- Cyrillic
if not subbed and data.old then
stem, subbed = rsub(stem, "ѣ́", "ѣ̈")
end
if not subbed then
error("No stressed е" .. (data.old and " or ѣ" or "") ..
" in stem " .. stem ..
" to replace with ё" .. (data.old and " or ѣ̈" or "") ..
" when trying to create participle")
end
if tr then
tr, subbed = rsub(tr, "j[eě]" .. AC, "jo" .. AC) -- Latin
if not subbed then
tr, subbed = rsub(tr, "[eě]" .. AC, "jo" .. AC) -- Latin
end
if not subbed then
error("No stressed е in translit " .. tr .. " to replace with jo when trying to create participle")
end
end
end
if data.conj_type == "1a" and ending_vowel == "е" then
-- 1a, only одоле́ть, преодоле́ть, verbs in -печатле́ть
set_ppp(forms, stem, tr, "ённый")
elseif data.conj_type == "1a" and ending_vowel == "ѣ" then
set_ppp(forms, stem, tr, "ѣ̈нный")
else
local stressed_ending, unstressed_ending
if ending_vowel == "е" then
stressed_ending = "ённый"
unstressed_ending = "енный"
elseif ending_vowel == "ѣ" then
stressed_ending = "ѣ̈нный"
unstressed_ending = "ѣнный"
else
local ppp_ending =
(ending_vowel == "а" or ending_vowel == "я") and "нный" or "тый"
stressed_ending = ending_vowel .. AC .. ppp_ending
unstressed_ending = ending_vowel .. ppp_ending
end
set_ppp(forms, stem, tr,
-- (7) occurs with 1a обуя́ть (обуя́нный)
ppptype == "(7)" and stressed_ending or
-- [(7)] -- when does it occur? may only occur in class 4
ppptype == "[(7)]" and {unstressed_ending, stressed_ending} or
unstressed_ending)
end
end
-- Iterate over the values of a property (e.g. past_m, past_f), handling
-- overrides properly. Call FN on each one, passing in RU, TR, NOTE.
local function iterate_over_prop(forms, args, prop, fn)
for _, form in ipairs(main_to_all_verb_forms[prop]) do
local ru, tr
if args[form] then
local orig_forms = {}
for _, form2 in ipairs(main_to_all_verb_forms[prop]) do
if forms[form2] then
table.insert(orig_forms, forms[form2])
end
end
local override = parse_and_stress_override(form, args[form], forms[form], orig_forms)
ru, tr = extract_russian_tr(override)
end
if (not ru or ru == "" or ru == "-") and forms[form] then
ru, tr = extract_russian_tr(forms[form])
end
-- skip unstressed forms (may occur in the past_m when a stressed
-- reflexive -ся́ should occur; these occur only in запереться and
-- опереться, where they're used to generate the past active part
-- and past adverbial part, and end-stressed forms shouldn't be
-- generated)
if ru and ru ~= "" and ru ~= "-" and not com.is_unstressed(ru) then
local ruentry, runotes = m_table_tools.separate_notes(ru)
local trentry, trnotes
if tr then
trentry, trnotes = m_table_tools.separate_notes(tr)
end
fn(ruentry, trentry, {runotes, trnotes})
end
end
end
-- Set the past passive participle for those classes where it is derived
-- from the past tense masculine singular (9, 11, 12, 14, 15, 16). We need
-- to apply any relevant overrides.
local function set_ppp_from_past_m(forms, args, data)
if not data.ppp then
return
end
iterate_over_prop(forms, args, "past_m", function(ru, tr, note)
if rfind(ru, "л$") then
ru = rsub(ru, "л$", "")
if tr then
tr = rsub(tr, "l$", "")
end
end
append_ppp(forms, ru, tr, "тый", note)
end)
end
-- Set the past passive participle for class-4 verbs.
local function set_class_4_ppp(forms, data, stem, tr, vclass)
if not data.ppp then
return
end
local iotated_stem, iotated_tr = iotated_ppp(data, stem, tr)
vclass = vclass or data.conj_type
if vclass == "4b" then
local stressed_iotated_stem, stressed_iotated_tr =
com.make_ending_stressed(iotated_stem, iotated_tr)
set_ppp(forms, stressed_iotated_stem, stressed_iotated_tr,
-- (8) occurs with 4b скрои́ть (скро́енный)
data.ppp == "(8)" and "енный" or
-- [(8)] occurs with 4b разгроми́ть (разгромлённый, разгро́мленный)
data.ppp == "[(8)]" and {"ённый", "енный"} or "ённый")
else
set_ppp(forms, iotated_stem, iotated_tr,
-- (7) occurs with 4c раздели́ть (разделённый)
data.ppp == "(7)" and "ённый" or
-- [(7)] occurs with 4a осве́домить (осве́домленный, осведомлённый)
-- [(7)] occurs with 4c иссуши́ть (иссу́шенный, иссушённый)
data.ppp == "[(7)]" and {"енный", "ённый"} or "енный")
end
end
-- Set the past passive participle for class-7 and class-8 verbs. These
-- form the PPP by adding to the base of the 3sg pres/futr (i.e. minus
-- -ет/-ёт). The stress follows the stress of the past singular feminine.
-- Only types a, a(1) and b exist, meaning that if the past singular feminine
-- is ending-stressed then the PPP ending is -ённый, otherwise it is -енный
-- with the stress of the 3sg pres/futr base preserved (and added to the
-- last syllable if the base has no stress, as in 7b укра́сть, 3sg украдёт,
-- fem sg past укра́ла, PPP укра́денный).
local function set_class_7_8_ppp(forms, args, data)
if not data.ppp then
return
end
local sg3_bases = {}
-- Extract 3sg bases. There may be more than one possible form, e.g. in
-- обокра́сть, so support this.
-- FIXME: We don't support checking for overrides here; doing so isn't
-- overly hard but is a bit tricky because the overrides will be either
-- pres_3sg or futr_3sg, depending on the aspect of the verb.
-- FIXME: We don't support manual translit here, because neither 7 nor 8
-- support it elsewhere.
for _, form in ipairs(main_to_all_verb_forms["pres_futr_3sg"]) do
local ru, tr
if forms[form] then
ru, tr = extract_russian_tr(forms[form])
end
if ru and ru ~= "" and ru ~= "-" then
local ruentry, runotes = m_table_tools.separate_notes(ru)
ruentry = rsub(ruentry, "[её]т$", "")
if com.is_unstressed(ruentry) then
ruentry = com.make_ending_stressed(ruentry)
end
m_table.insertIfNot(sg3_bases, {ruentry, runotes})
end
end
-- Here we do the same rigmarole as in set_ppp_from_past_m(), to respect
-- any past_f overrides that might have been set. It's unlikely that
-- there is more than one possible form but we support it.
iterate_over_prop(forms, args, "past_f", function(ru, tr, note)
for _, base_and_notes in ipairs(sg3_bases) do
local base, notes = base_and_notes[1], base_and_notes[2]
append_ppp(forms, base, nil,
-- check if past_f is ending-stressed
rfind(ru, AC .. "$") and "ённый" or "енный", notes)
end
end)
end
--[=[
Conjugation functions
]=]
conjugations["1a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"+p", "7", "ё"})
local stem, tr = com.split_russian_tr(get_stressed_arg(args, 2))
if stem == "-" and not tr then
-- Template space; leave it
else
stem, tr = com.strip_ending(stem, tr, "ть")
end
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "ть")
append_participles(forms, stem, tr, "ющий", "емый", "я", "вший", "вши", "в")
set_moving_ppp(forms, data)
present_je(forms, stem, tr, "a")
append_imper(forms, stem, tr, "й", "йте")
set_past(forms, stem, tr, "л", "ла", "ло", "ли")
return forms
end
local function guts_of_2(args, data)
local forms = {}
local inf_stem, inf_tr = com.split_russian_tr(get_stressed_arg(args, 2))
inf_stem, inf_tr = com.strip_ending(inf_stem, inf_tr, "ть")
no_stray_args(args, 2)
local pres_stem, pres_tr = inf_stem, inf_tr
local variants = args[1] or ""
parse_variants(data, variants, {"+p", "7"})
-- If stem ends in -ева́ть and a past passive participle is called for
-- with stress on the -е-, automatically set -о- or -ё- as required.
if data.ppp and data.ppp ~= "(7)" then
if rfind(inf_stem, "цева́") then
if data.ppp == "[(7)]" then
-- FIXME. Theoretically we should support this but there
-- aren't any verbs requiring it. It won't work properly
-- currently because we need the о to appear only when
-- stressed.
error("Variant [(7)] not supported for class 2")
end
-- цев -> цо́в, e.g. (об)лицева́ть -> (об)лицо́ванный
data.o = true
data.title = data.title .. "(-о-)"
elseif rfind(inf_stem, "ева́") then
data.yo = true
data.title = data.title .. "(-ё-)"
end
end
-- all -ова- change to -у-
pres_stem = rsub(pres_stem, "о(́?)ва(́?)$", "у%1%2")
pres_tr = pres_tr and rsub(pres_tr, "o(́?)va(́?)$", "u%1%2")
-- -ева- change to -ю- after most consonants and vowels, to -у- after hissing sounds and ц
if rfind(pres_stem, "[бвгдзклмнпрстфхь" .. com.vowel .. AC .. "]е(́?)ва(́?)$") then
pres_stem = rsub(pres_stem, "е(́?)ва(́?)$", "ю%1%2")
pres_tr = pres_tr and rsub(pres_tr, "e(́?)va(́?)$", "ju%1%2")
elseif rfind(pres_stem, "[жцчшщ]е(́?)ва(́?)$") then
pres_stem = rsub(pres_stem, "е(́?)ва(́?)$", "у%1%2")
pres_tr = pres_tr and rsub(pres_tr, "e(́?)va(́?)$", "u%1%2")
end
forms["infinitive"] = combine(inf_stem, inf_tr, "ть")
if data.conj_type == "2a" then
append_participles_2stem(forms, pres_stem, pres_tr, inf_stem, inf_tr,
"ющий", "емый", "я", "вший", "вши", "в")
present_je(forms, pres_stem, pres_tr, "a")
else
append_participles_2stem(forms, pres_stem, pres_tr, inf_stem, inf_tr,
"ю́щий", "-", "я́", "вший", "вши", "в")
present_je(forms, pres_stem, pres_tr, "b")
end
set_moving_ppp(forms, data)
append_imper(forms, pres_stem, pres_tr, "й", "йте")
set_past(forms, inf_stem, inf_tr, "л", "ла", "ло", "ли")
return forms
end
conjugations["2a"] = function(args, data)
return guts_of_2(args, data)
end
conjugations["2b"] = function(args, data)
return guts_of_2(args, data)
end
conjugations["3°a"] = function(args, data)
local forms = {}
-- (5), [(6)] or similar; imperative indicators
parse_variants(data, args[1], {"5", "6", "23", "и", "+p", "7", "ё"})
local stem, tr = com.split_russian_tr(get_stressed_arg(args, 2))
stem, tr = com.strip_ending(stem, tr, "нуть")
local vowel_stem = is_vowel_stem(stem)
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "нуть")
append_participles(forms, stem, tr,
-- default is blank for pres passive and adverbial
"нущий", "-", "-",
data.var6 == "req" and "нувший" or
data.var6 == "opt" and (vowel_stem and {"вший", "нувший"} or {"ший", "нувший"}) or
vowel_stem and "вший" or "ший",
data.var6 == "req" and "нувши" or
data.var6 == "opt" and (vowel_stem and {"вши", "нувши"} or {"ши", "нувши"}) or
vowel_stem and "вши" or "ши",
data.var6 == "req" and "нув" or
data.var6 == "opt" and (vowel_stem and {"в", "нув"} or "нув") or
vowel_stem and "в" or "-")
set_moving_ppp(forms, data)
present_e_a(forms, stem .. "н", tr and tr .. "n")
append_imper_by_variant(forms, stem .. "н", tr and tr .. "n", data.imper_variant, "3°a")
forms["past_m"] = data.var5 and combine(stem, tr, "нул") or "-"
forms["past_m_short"] = data.var5 ~= "req" and combine(stem, tr, (vowel_stem and "л" or "")) or nil
forms["past_f_short"] = combine(stem, tr, "ла")
forms["past_n_short"] = combine(stem, tr, "ло")
forms["past_pl_short"] = combine(stem, tr, "ли")
return forms
end
conjugations["3a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"23", "и", "+p", "7", "ё"})
local stem, tr = com.split_russian_tr(get_stressed_arg(args, 2))
-- make sure we can strip нуть from the stem and any translit;
com.strip_ending(stem, tr, "нуть")
-- but then just strip the -уть and leave the н
stem, tr = com.strip_ending(stem, tr, "уть")
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "уть")
append_participles(forms, stem, tr,
-- default is blank for pres passive and adverbial
"ущий", "-", "-", "увший", "увши", "ув")
set_moving_ppp(forms, data)
present_e_a(forms, stem, tr)
append_imper_by_variant(forms, stem, tr, data.imper_variant, "3a")
set_past(forms, stem .. "ул", tr and tr .. "ul", "", "а", "о", "и")
return forms
end
local function guts_of_3b_3c(args, data, vclass)
local forms = {}
parse_variants(data, args[1], {"+p", "7", "ё"})
local stem, tr = com.split_russian_tr(get_stressed_arg(args, 2))
-- make sure we can strip нуть from the stem and any translit;
com.strip_ending(stem, tr, "ну́ть")
-- but then just strip the -у́ть and leave the н
stem, tr = com.strip_ending(stem, tr, "у́ть")
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "у́ть")
append_participles(forms, stem, tr,
-- default is blank for pres passive and adverbial
"у́щий", "-", "-", "у́вший", "у́вши", "у́в")
set_moving_ppp(forms, data)
append_imper(forms, stem, tr, "и́", "и́те")
set_past(forms, stem, tr, "у́л", "у́ла", "у́ло", "у́ли")
if data.conj_type == "3b" then
present_e_b(forms, stem, tr)
else
stem, tr = com.make_ending_stressed(stem, tr)
present_e_c(forms, stem, tr)
end
return forms
end
conjugations["3b"] = function(args, data)
return guts_of_3b_3c(args, data)
end
conjugations["3c"] = function(args, data)
return guts_of_3b_3c(args, data)
end
conjugations["4a"] = function(args, data)
local forms = {}
-- imperative variants, also щ, used for verbs like похитить (похи́щу) (4a),
-- защитить (защищу́) (4b), поглотить (поглощу́) (4c) with a different
-- iotation (т -> щ, not ч)
parse_variants(data, args[1], {"23", "и", "щ", "past", "+p", "7", "жд"})
local stem, tr = com.split_russian_tr(get_stressed_arg(args, 2))
stem, tr = com.strip_ending(stem, tr, "ить")
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "ить")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(stem, "[шщжч]$")
append_participles(forms, stem, tr, hushing and "ащий" or "ящий",
"awkward-имый", hushing and "а" or "я", "ивший", "ивши", "ив")
set_class_4_ppp(forms, data, stem, tr)
present_i(forms, stem, tr, "a", data.shch)
append_imper_by_variant(forms, stem, tr, data.imper_variant, "4a")
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, stem .. "и",
tr and tr .. "i", args, data)
return forms
end
conjugations["4a1a"] = function(args, data)
local forms = {}
data.title = "4a // 1a"
data.cat_conj_types = {"1a", "4a"}
-- imperative variants, also щ, used for verbs like похитить (похи́щу) (4a),
-- защитить (защищу́) (4b), поглотить (поглощу́) (4c) with a different
-- iotation (т -> щ, not ч)
parse_variants(data, args[1], {"23", "и", "щ", "past", "+p", "7", "жд"})
local stem4, tr4 = com.split_russian_tr(get_stressed_arg(args, 2))
stem4, tr4 = com.strip_ending(stem4, tr4, "ить")
local hushing = rfind(stem4, "[шщжч]$")
local stem1, tr1
if hushing then
stem1 = stem4 .. "а"
tr1 = tr4 and tr4 .. "a"
else
stem1 = stem4 .. "я"
tr1 = tr4 and tr4 .. "ja"
end
no_stray_args(args, 2)
forms["infinitive"] = combine(stem4, tr4, "ить")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
append_participles(forms, stem4, tr4, hushing and "ащий" or "ящий",
"awkward-имый", hushing and "а" or "я", "ивший", "ивши", "ив")
append_participles(forms, stem1, tr1, "ющий", "емый", "я", {}, {}, {})
set_class_4_ppp(forms, data, stem4, tr4)
present_i(forms, stem4, tr4, "a", data.shch)
present_je(forms, stem1, tr1, "a", data.shch)
append_imper_by_variant(forms, stem4, tr4, data.imper_variant, "4a")
append_imper(forms, stem1, tr1, "й", "йте")
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, stem4 .. "и",
tr4 and tr4 .. "i", args, data)
return forms
end
conjugations["4b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"щ", "past", "+p", "8", "жд"})
local stem, tr = com.split_russian_tr(get_stressed_arg(args, 2))
stem, tr = com.strip_ending(stem, tr, "и́ть")
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "и́ть")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(stem, "[шщжч]$")
append_participles(forms, stem, tr, hushing and "а́щий" or "я́щий",
"awkward-и́мый", hushing and "а́" or "я́", "и́вший", "и́вши", "и́в")
set_class_4_ppp(forms, data, stem, tr)
present_i(forms, stem, tr, "b", data.shch)
append_imper(forms, stem, tr, "и́", "и́те")
-- set prefix to "" as past stem may vary in length and no (1) variants
local stem_noa, tr_noa = com.make_unstressed_once(stem, tr)
set_past_by_stress(forms, data.past_stress, "", nil, stem_noa .. "и́",
tr_noa and tr_noa .. "i" .. AC, args, data)
return forms
end
conjugations["4c"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"щ", "4", "past", "+p", "7", "жд"})
local stem, tr = com.split_russian_tr(get_stressed_arg(args, 2))
stem, tr = com.strip_ending(stem, tr, "и́ть")
stem, tr = com.make_ending_stressed(stem, tr)
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "и́ть")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(stem, "[шщжч]$")
local prap_end_stressed = hushing and "а́щий" or "я́щий"
local prap_stem_stressed = hushing and "ащий" or "ящий"
append_participles(forms, stem, tr, data.var4 == "req" and prap_stem_stressed
or data.var4 == "opt" and {prap_end_stressed, prap_stem_stressed}
or prap_end_stressed,
"awkward-и́мый", hushing and "а́" or "я́", "и́вший", "и́вши", "и́в")
set_class_4_ppp(forms, data, stem, tr)
present_i(forms, stem, tr, "c", data.shch)
append_imper(forms, stem, tr, "и́", "и́те")
local stem_noa, tr_noa = com.make_unstressed_once(stem, tr)
set_past_by_stress(forms, data.past_stress, "", nil, stem_noa .. "и́",
tr_noa and tr_noa .. "i" .. AC, args, data)
return forms
end
-- Combined class 5. But there's enough conditional code that it might make
-- more sense to separate them again.
local function guts_of_5(args, data)
local forms = {}
local is5a = data.conj_type == "5a"
local is5b = data.conj_type == "5b"
-- imperative ending (выгнать - выгони) and past stress; imperative is
-- "й" after any vowel (e.g. выстоять), with or without an acute accent,
-- otherwise ь or и
if is5a or is5b then
parse_variants(data, args[1], {"23", "и", "past", "+p", "7", "ё"})
else
parse_variants(data, args[1], {"23", "и", "past", "+p", "7", "ё", "4"})
end
local inf = get_stressed_arg(args, 2)
local past_stem = com.strip_ending(inf, nil, "ть")
local stem = is5b and get_opt_unstressed_arg(args, 3) or get_opt_stressed_arg(args, 3)
local default_stem = rmatch(past_stem, "^(.*)[еѣая]́?$")
if not default_stem then
error("Argument " .. inf .. " doesn't end in еть, ѣть, ать or ять")
end
if not is5a and not is5b then
default_stem = com.make_ending_stressed(default_stem)
end
stem = stem or default_stem
local pres_note = stem ~= default_stem and IRREG
no_stray_args(args, 3)
forms["infinitive"] = past_stem .. "ть"
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(stem, "[шщжч]$")
if is5a then
append_participles_2stem(forms, stem, nil, past_stem, nil,
hushing and "ащий" or "ящий", "имый", hushing and "а" or "я",
"вший", "вши", "в", pres_note)
elseif is5b then
append_participles_2stem(forms, stem, nil, past_stem, nil,
hushing and "а́щий" or "я́щий", "и́мый", hushing and "а́" or "я́",
"вший", "вши", "в", pres_note)
else
-- var4 occurs with at least терпре́ть and дыша́ть
local prap_end_stressed = hushing and "а́щий" or "я́щий"
local prap_stem_stressed = hushing and "ащий" or "ящий"
append_participles_2stem(forms, stem, nil, past_stem, nil,
data.var4 == "req" and prap_stem_stressed
or data.var4 == "opt" and {prap_end_stressed, prap_stem_stressed}
or prap_end_stressed,
"и́мый", hushing and "а́" or "я́", "вший", "вши", "в", pres_note)
end
set_moving_ppp(forms, data)
present_i(forms, stem, nil, is5a and "a" or is5b and "b" or "c", nil, pres_note)
append_imper_by_variant(forms, stem, nil, data.imper_variant, data.conj_type, pres_note)
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, past_stem, nil,
args, data)
return forms
end
conjugations["5a"] = function(args, data)
return guts_of_5(args, data)
end
conjugations["5b"] = function(args, data)
return guts_of_5(args, data)
end
conjugations["5c"] = function(args, data)
return guts_of_5(args, data)
end
-- Implement 6a, 6°a, 6a1as13, 6a1as14, and 1a6a.
local function guts_of_6a(args, data, vclass)
local forms = {}
-- Type 6a1a, section 13:
-- Forms of both 6a and 1a can occur. They are the same in the infinitive
-- and past. In the present active participle and the present/future, the
-- type 6 forms are preferred and the type 1a forms are colloquial. In the
-- remaining present forms and the imperative, both are equally preferred
-- (we put the type-6 forms first because Zaliznyak lists them first).
-- Type 6a1a section 14, type 1a6a:
-- Forms of both 6a and 1a can occur. They are the same in the infinitive
-- and past. In the present adverbial participle and the imperative, the
-- type 1a forms are preferred and the type 6a forms are dated. In the
-- remaining present forms, one or the other is slightly preferred (type
-- 6a for 6a1a, type 1a for 1a6a).
if vclass == "6a1as13" or vclass == "6a1as14" then
data.title = "6a // 1a"
data.cat_conj_types = {"1a", "6a"}
elseif vclass == "1a6a" then
data.title = "1a // 6a"
data.cat_conj_types = {"1a", "6a"}
end
parse_variants(data, args[1], {"23", "и", "past", "+p", "7", "ё"})
local inf = get_stressed_arg(args, 2)
local inf_past_stem = com.strip_ending(inf, nil, "ть")
local stem = rmatch(inf_past_stem, "^(.*)[ая]́?$")
if not stem then
error("Argument " .. inf .. " doesn't end in ать or ять")
end
if com.is_unstressed(stem) then
-- колыха́ть, колеба́ть, etc.
stem = com.make_ending_stressed(stem)
end
-- вызвать - вы́зову (в́ызов)
local pres_stem = get_opt_stressed_arg(args, 3) or stem
no_stray_args(args, 3)
local pres_note = pres_stem ~= stem and IRREG
-- no iotation, e.g. вырвать - вы́рву
local no_iotation = vclass == "6°a"
-- replace consonants for 1st person singular present/future
local iotated_stem = no_iotation and pres_stem or com.iotation(pres_stem)
forms["infinitive"] = inf_past_stem .. "ть"
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(iotated_stem, "[шщжч]$") or no_iotation
-- Participles
-- pres_pasv_part is normal if infinitive ends in -ять, nonexistent except
-- with certain lexical exceptions (колеба́ть, колыха́ть, глаго́лать,
-- дви́гать with exceptional form дви́жимый) if infinitive ends in -ать
local prpp_status = rfind(inf_past_stem, "я́?$") and "" or "none-"
if vclass == "6a" or vclass == "6°a" or vclass == "6a1as13" then
append_participles_2stem(forms, iotated_stem, nil, inf_past_stem, nil,
hushing and "ущий" or "ющий", prpp_status .. "емый", hushing and "а" or "я",
"вший", "вши", "в", pres_note)
if vclass == "6a1as13" then
-- then all the type 1a forms (both are the same in the past)
append_participles(forms, inf_past_stem, nil, "ющий*", prpp_status .. "емый", "я")
end
elseif vclass == "6a1as14" then
-- first the preferred type 6a present active/passive participles
append_participles(forms, iotated_stem, nil,
hushing and "ущий" or "ющий", prpp_status .. "емый", {}, {}, {}, {}, pres_note)
-- then all the type 1a forms (both are the same in the past)
append_participles(forms, inf_past_stem, nil, "ющий", "емый", "я",
"вший", "вши", "в")
-- then the dated type 6a present adverbial participle
append_participles(forms, iotated_stem, nil,
{}, {}, hushing and "а*" or "я*", {}, {}, {}, pres_note)
else -- type 1a6a
-- first the preferred type 1a forms (both are the same in the past)
append_participles(forms, inf_past_stem, nil, "ющий", "емый", "я",
"вший", "вши", "в")
-- then the type 6a forms (dated in present adverbial participle)
append_participles(forms, iotated_stem, nil,
hushing and "ущий" or "ющий", prpp_status .. "емый", hushing and "а*" or "я*",
{}, {}, {}, pres_note)
end
set_moving_ppp(forms, data)
-- Present/future tense
local function class_6_present()
if no_iotation then
present_e_a(forms, pres_stem, nil, pres_note)
else
present_je(forms, pres_stem, nil, "a", nil, pres_note)
end
end
if vclass == "6a" or vclass == "6°a" then
class_6_present()
elseif vclass == "1a6a" then
-- Do type 1a forms
present_je(forms, inf_past_stem, nil, "a")
class_6_present()
elseif vclass == "6a1as14" then
class_6_present()
-- Do type 1a forms
present_je(forms, inf_past_stem, nil, "a")
else
-- 6a1as13
class_6_present()
-- Do type 1a forms
present_je(forms, inf_past_stem, nil, "a", nil, "*")
end
-- Imperative forms; if 1a6a or 6a1as14, type 6a forms are dated;
-- if 6a1as13, type 6a forms go first.
local function class_1_impr()
append_imper(forms, inf_past_stem, nil, "й", "йте")
end
local function class_6_impr()
local dated_note = ((vclass == "6a1as14" or vclass == "1a6a") and "*" or "") ..
(pres_note or "")
append_imper_by_variant(forms, iotated_stem, nil, data.imper_variant,
"6a", dated_note)
end
if vclass == "6a1as14" or vclass == "1a6a" then
class_1_impr()
class_6_impr()
elseif vclass == "6a1as13" then
class_6_impr()
class_1_impr()
else
class_6_impr()
end
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, inf_past_stem, nil,
args, data)
if vclass == "6a1as14" or vclass == "1a6a" then
m_table.insertIfNot(data.internal_notes, "* Dated.")
elseif vclass == "6a1as13" then
m_table.insertIfNot(data.internal_notes, "* Colloquial; type-6 forms preferred.")
end
return forms
end
conjugations["6a"] = function(args, data)
return guts_of_6a(args, data, "6a")
end
conjugations["6°a"] = function(args, data)
return guts_of_6a(args, data, "6°a")
end
conjugations["6a1as13"] = function(args, data)
return guts_of_6a(args, data, "6a1as13")
end
conjugations["6a1as14"] = function(args, data)
return guts_of_6a(args, data, "6a1as14")
end
conjugations["1a6a"] = function(args, data)
return guts_of_6a(args, data, "1a6a")
end
-- implement 6b, 6°b
local function guts_of_6b(args, data, vclass)
local forms = {}
parse_variants(data, args[1], {"past", "+p", "7", "ё"})
local inf = get_stressed_arg(args, 2)
local stem = rmatch(inf, "^(.*)[ая]́ть$")
if not stem then
error("Argument " .. inf .. " doesn't end in ать or ять")
end
-- звать - зов, драть - дер
local pres_stem = get_opt_unstressed_arg(args, 3) or stem
no_stray_args(args, 3)
-- no iotation, e.g. рвать - рву
local no_iotation = vclass == "6°b"
local vowel_end_stem = is_vowel_stem(stem)
local pres_note = pres_stem ~= stem and IRREG
if no_iotation then
present_e_b(forms, pres_stem, nil, pres_note)
else
present_je(forms, pres_stem, nil, "b", nil, pres_note)
end
local impr_end = vowel_end_stem and "́й" -- accent on the preceding vowel
or "и́"
append_imper(forms, pres_stem, nil, impr_end, impr_end .. "те", pres_note)
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(pres_stem, "[шщжч]$")
-- no pres_pasv_part
local past_stem_with_vowel = stem .. (vowel_end_stem and "я́" or "а́")
append_participles_2stem(
forms, pres_stem, nil, past_stem_with_vowel, nil,
((hushing or no_iotation) and "у́щий" or "ю́щий"), {}, (hushing and "а́" or "я́"),
"вший", "вши", "в", pres_note)
forms["infinitive"] = combine(past_stem_with_vowel, nil, "ть")
set_moving_ppp(forms, data)
-- past_f for ждала́, подождала́ now handled through general mechanism
--for разобрало́сь, past_n2 разобрало́ now handled through general mechanism
--for разобрали́сь, past_pl2 разобрали́ now handled through general mechanism
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil,
stem .. (vowel_end_stem and "я́" or "а́"), nil, args, data)
return forms
end
conjugations["6b"] = function(args, data)
return guts_of_6b(args, data, "6b")
end
conjugations["6°b"] = function(args, data)
return guts_of_6b(args, data, "6°b")
end
-- Implement 6c, 6°c and 6c1a.
local function guts_of_6c(args, data, vclass)
local forms = {}
-- In type 6c1a, forms of both 6c and 1a can occur. They are
-- the same in the infinitive and past. In the present active participle
-- and the present/future, the type 6c forms are preferred and the type 1a
-- forms are colloquial. In the remaining present forms and the imperative,
-- both are equally preferred (we put the 6c forms first because Zaliznyak
-- lists 6c first).
if vclass == "6c1a" then
data.title = "6c // 1a"
data.cat_conj_types = {"1a", "6c"}
end
-- optional щ parameter for verbs like клеветать (клевещу́), past stress
parse_variants(data, args[1], {"щ", "past", "+p", "7", "ё"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "а́ть")
stem = com.make_ending_stressed(stem)
-- разостла́ть - расстелю́, рассте́лешь
local pres_stem = get_opt_stressed_arg(args, 3) or stem
no_stray_args(args, 3)
local pres_note = pres_stem ~= stem and IRREG
-- remove accent for some forms
local stem_noa = com.make_unstressed(stem)
-- applies only to стона́ть, застона́ть, простона́ть
local no_iotation = vclass == "6°c"
-- iotate the stem
local iotated_stem =
no_iotation and pres_stem or com.iotation(pres_stem, nil, data.shch)
local stem1a = stem_noa .. "а́"
forms["infinitive"] = stem_noa .. "а́ть"
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(iotated_stem, "[шщжч]$")
-- Participles
append_participles_2stem(forms, iotated_stem, nil, stem_noa, nil,
(hushing or no_iotation) and "ущий" or "ющий", {},
hushing and "а́" or "я́", "а́вший", "а́вши", "а́в", pres_note)
if vclass == "6c1a" then
-- then all the type 1a forms (both are the same in the past)
append_participles(forms, stem1a, nil, "ющий*", "емый", "я")
end
set_moving_ppp(forms, data)
if no_iotation then
present_e_c(forms, pres_stem, nil, pres_note)
else
present_je(forms, pres_stem, nil, "c", data.shch, pres_note)
end
append_imper(forms, iotated_stem, nil, "и́", "и́те", pres_note)
if vclass == "6c1a" then
present_je(forms, stem1a, nil, "a", nil, "*")
append_imper(forms, stem1a, nil, "й", "йте")
end
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, stem_noa .. "а́", nil,
args, data)
if vclass == "6c1a" then
m_table.insertIfNot(data.internal_notes, "* Colloquial; type-6 forms preferred.")
end
return forms
end
conjugations["6c"] = function(args, data)
return guts_of_6c(args, data, "6c")
end
conjugations["6°c"] = function(args, data)
return guts_of_6c(args, data, "6°c")
end
conjugations["6c1a"] = function(args, data)
return guts_of_6c(args, data, "6c1a")
end
local function convert_last_e_to_yo(form)
return rsub(form,
"([еѣ])[́̀̈]*([^" .. com.vowel .. "]*)$",
function(e, nonvowels)
return (e == "е" and "ё" or "ѣ̈") .. nonvowels
end)
end
local function guts_of_7(args, data, forms)
local is7b = data.conj_type == "7b"
local full_inf = get_stressed_arg(args, 2)
local pres_stems = is7b and get_unstressed_arg(args, 3) or get_stressed_arg(args, 3)
pres_stems = rsplit(pres_stems, ",")
local past_stem
if past_stem ~= "ёе" then
past_stem = get_opt_stressed_arg(args, 4)
end
local past_stem_vowel_alt = past_stem == "ёе"
if past_stem_vowel_alt then
past_stem = nil
end
no_stray_args(args, 4)
forms["infinitive"] = full_inf
-- Construct the default past and present stem by a combination of
-- infinitive and present final consonant.
-- (1) Deduce the final consonant.
local final_cons
for _, pres_stem in ipairs(pres_stems) do
-- Final cons is -ст if pres stem ends in vowel + ст, else
-- single final cons [дтсзбп] (no actual examples of final п).
-- Note that final -з can occur after a consonant (e.g. ползти́).
local this_final_cons = rmatch(pres_stem,
"[" .. com.vowel .. "]" .. AC .. "?(ст)$")
if not this_final_cons then
this_final_cons = rmatch(pres_stem, "([дтсзбп])$")
end
if not this_final_cons then
error("Unable to determine final consonant from present stem " .. pres_stem)
end
if final_cons and this_final_cons ~= final_cons then
error("Present stems with conflicting final consonants specified: " ..
table.concat(pres_stems, ","))
end
final_cons = this_final_cons
end
-- (2) Find the infinitive minus the termination.
local prefix = rmatch(full_inf, "^(.*)[сз]т[иь]" .. AC .."?$")
if not prefix then
error("Strange infinitive " .. full_inf .. "in class 7")
end
-- (3) Combine infinitive with final consonant.
local default_pres_stem = prefix .. final_cons
if is7b then
default_pres_stem = com.make_unstressed(default_pres_stem)
end
local default_past_stem = default_pres_stem
if com.is_unstressed(default_past_stem) then
default_past_stem = com.make_ending_stressed(default_past_stem)
end
-- (4) Past stems ending in -д and -т when the infinitive ends in -сть (but not -сти or -сти́)
-- lose this consonant (page 85 of Zaliznyak, see also footnote 2 on that page).
if rfind(full_inf, "сть$") then
default_past_stem = rsub(default_past_stem, "[дт]$", "")
end
-- (5) If 7b and the past stem wasn't originally specified as ёе, the past stem gets
-- ё in place of е.
if is7b and not past_stem_vowel_alt then
default_past_stem = convert_last_e_to_yo(default_past_stem)
end
for _, pres_stem in ipairs(pres_stems) do
local pres_note = pres_stem ~= default_pres_stem and IRREG
if is7b then
present_e_b(forms, pres_stem, nil, pres_note)
append_imper(forms, pres_stem, nil, "и́", "и́те", pres_note)
else
present_e_a(forms, pres_stem, nil, pres_note)
append_imper_by_variant(forms, pres_stem, nil, data.imper_variant,
"7a", pres_note)
end
end
-- Construct the past stem if not specified. Note that we then derive a separate
-- past-tense stem from this stem, and this stem as such ends up applying only
-- to the past active and adverbial participles.
if not past_stem then
past_stem = default_past_stem
end
local past_note = past_stem ~= default_past_stem and IRREG
-- Derive the past tense stem from the past stem derived above. This has ё instead of е
-- in 7b verbs; it also loses д and т in all cases, when the past stem derived above only loses
-- these consonants in some cases.
local past_tense_stem = past_stem
if is7b then
past_tense_stem = convert_last_e_to_yo(past_tense_stem)
end
past_tense_stem = rsub(past_tense_stem, "[дт]$", "")
local vowel_pp = is_vowel_stem(past_stem)
local pap = vowel_pp and "вши" or "ши"
local var9_note_symbol = next_note_symbol(data)
for _, pres_stem in ipairs(pres_stems) do
local pres_note = pres_stem ~= default_pres_stem and IRREG
append_participles_2stem(forms, pres_stem, nil, past_stem, nil,
is7b and "у́щий" or "ущий", "-", is7b and "я́" or "я",
vowel_pp and "вший" or "ший",
data.var9 and {is7b and "я́" or "я", pap .. var9_note_symbol} or pap,
vowel_pp and not data.var9 and "в" or "-", pres_note, past_note)
end
if data.var9 then
m_table.insertIfNot(data.internal_notes, var9_note_symbol .. " Dated.")
end
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, past_tense_stem, nil,
args, data,
-- 0 ending if the past stem ends in a consonant
not is_vowel_stem(past_tense_stem) and "no-pastml", past_note)
-- set PPP; must be done after both present 3sg and past fem have been set
set_class_7_8_ppp(forms, args, data)
end
conjugations["7a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"23", "и", "9","past", "+p"})
-- лезть - ле́зши - non-existent past_actv_part handled through general mechanism
guts_of_7(args, data, forms)
return forms
end
conjugations["7b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"9", "past", "+p"})
guts_of_7(args, data, forms)
return forms
end
local function class_8a_stem_to_infinitive(stem)
-- map e.g. вы́сек back to высе́чь
return rsub(stem, "[гк]$", "чь")
end
local function class_8b_stem_to_infinitive(stem)
-- map e.g. отвлёк back to отвле́чь
-- map e.g. зажёг back to заже́чь
return com.make_ending_stressed(rsub(rsub(rsub(stem, "ё", "е"), "ѣ̈", "ѣ"), "[гк]$", "чь"))
end
conjugations["8a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local full_inf = get_stressed_arg(args, 2)
local stem = get_stressed_arg(args, 3)
local stressed_past_stem = get_opt_stressed_arg(args, 4) or stem
no_stray_args(args, 4)
forms["infinitive"] = full_inf
local pres_note = class_8a_stem_to_infinitive(stem) ~= full_inf and IRREG
local stressed_past_note =
class_8a_stem_to_infinitive(stressed_past_stem) ~= full_inf and IRREG
-- default for pres_pasv_part is blank
append_participles_2stem(forms, stem, nil, stressed_past_stem, nil,
"ущий", "-", "-", "ший", "ши", "-", pres_note, stressed_past_note)
local iotated_stem = com.iotation(stem)
append_pres_futr(forms, iotated_stem, nil, {}, "ешь", "ет", "ем", "ете", {}, pres_note)
append_pres_futr(forms, stem, nil, "у", {}, {}, {}, {}, "ут", pres_note)
append_imper(forms, stem, nil, "и", "ите", pres_note)
-- set prefix to "" as stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, stem, nil, args, data,
"no-pastml", pres_note)
forms["past_m"] = stressed_past_stem .. (stressed_past_note or "")
-- set PPP; must be done after both present 3sg and past fem have been set
set_class_7_8_ppp(forms, args, data)
return forms
end
conjugations["8b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local full_inf = get_stressed_arg(args, 2)
local stem = get_unstressed_arg(args, 3)
local stressed_past_stems = rsplit(args[4] or "ё", ",")
for _, stressed_past_stem in ipairs(stressed_past_stems) do
if stressed_past_stem ~= "е" then
check_stressed_arg(stressed_past_stem, 4)
end
end
no_stray_args(args, 4)
forms["infinitive"] = full_inf
local pres_note = class_8b_stem_to_infinitive(stem) ~= full_inf and IRREG
local iotated_stem = com.iotation(stem)
append_pres_futr(forms, iotated_stem, nil, {}, "ёшь", "ёт", "ём", "ёте", {}, pres_note)
append_pres_futr(forms, stem, nil, "у́", {}, {}, {}, {}, "у́т", pres_note)
append_imper(forms, stem, nil, "и́", "и́те", pres_note)
-- set prefix to "" as stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil,
com.make_ending_stressed(stem), nil, args, data, "no-pastml", pres_note)
forms["past_m"] = nil
for _, stressed_past_stem in ipairs(stressed_past_stems) do
local pastm_stem, past_part_stem
if stressed_past_stem == "е" then
past_part_stem = com.make_ending_stressed(stem)
pastm_stem = past_part_stem
elseif stressed_past_stem == "ё" then
past_part_stem = convert_last_e_to_yo(com.make_ending_stressed(stem))
pastm_stem = past_part_stem
elseif stressed_past_stem == "ёе" then
past_part_stem = com.make_ending_stressed(stem)
pastm_stem = convert_last_e_to_yo(past_part_stem)
else
pastm_stem = stressed_past_stem
past_part_stem = stressed_past_stem
end
local past_note =
class_8b_stem_to_infinitive(pastm_stem) ~= full_inf and IRREG
-- default for pres_pasv_part is blank; влечь -> влеко́мый handled through
-- general override mechanism
append_participles_2stem(forms, stem, nil, past_part_stem, nil,
"у́щий", "-", "-", "ший", "ши", "-", pres_note, past_note)
append_form(forms, "past_m", pastm_stem, nil, "", past_note)
end
-- set PPP; must be done after both present 3sg and past fem have been set
set_class_7_8_ppp(forms, args, data)
return forms
end
conjugations["9a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "еть")
local pres_stem = get_opt_stressed_arg(args, 3)
no_stray_args(args, 3)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
local default_pres_stem = prefix .. rsub(base, "е", "")
pres_stem = pres_stem or default_pres_stem
local pres_note = pres_stem ~= default_pres_stem and IRREG
forms["infinitive"] = stem .. "еть"
-- perfective only
append_participles(forms, stem, nil, "-", "-", "-", "ший", "ши", "ев")
present_e_a(forms, pres_stem, nil, pres_note)
append_imper(forms, pres_stem, nil, "и", "ите", pres_note)
-- past_m doesn't end in л
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data, "no-pastml")
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["9b"] = function(args, data)
local forms = {}
--for this type, it's important to distinguish impf and pf
local impf = rfind(data.verb_type, "^impf")
parse_variants(data, args[1], {"past", "+p", "*"})
local stem_noa = com.strip_ending(get_stressed_arg(args, 2), nil, "е́ть")
local stem = rsub(stem_noa, "(.*)е", "%1ё")
local pres_stem = get_opt_unstressed_arg(args, 3)
-- stem used for past active and adverbial participles; defaults to past_m
local past_part_stem = get_opt_stressed_arg(args, 4)
no_stray_args(args, 4)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem, nil, "single_cons_base")
local default_pres_stem =
data.star and construct_long_prefix_variant(prefix) .. rsub(base, "[её]", "") or
prefix .. rsub(base, "[её]", "")
pres_stem = pres_stem or default_pres_stem
local pres_note = pres_stem ~= default_pres_stem and IRREG
forms["infinitive"] = stem_noa .. "е́ть"
present_e_b(forms, pres_stem, nil, pres_note)
append_imper(forms, pres_stem, nil, "и́", "и́те", pres_note)
-- past_m doesn't end in л
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data, "no-pastml")
set_ppp_from_past_m(forms, args, data)
append_participles_2stem(forms, pres_stem, nil, stem, nil, "у́щий", {}, {},
-- impf: тереть -> тёрши
-- pf: растереть -> растёрши, растере́в
-- we handle (рас)тёрши down below because the stress depends on the
-- past_m: запереть -> за́пер, за́перши(й)
{}, {}, impf and {} or "е́в", pres_note)
if past_part_stem then
for _, ppstem in ipairs(rsplit(past_part_stem, ",")) do
append_participles(forms, ppstem, nil, {}, {}, {}, "ший", "ши", {})
end
else
iterate_over_prop(forms, args, "past_m", function(ru, tr, note)
append_participles(forms, ru, tr, {}, {}, {}, "ший", "ши", {}, note)
end)
end
return forms
end
conjugations["10a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"+p", "7"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "оть")
no_stray_args(args, 2)
forms["infinitive"] = stem .. "оть"
-- These verbs are perfective-only, no present participles
append_participles(forms, stem, nil, "-", "-", "-", "овший", "овши", "ов")
set_moving_ppp(forms, data)
present_je(forms, stem, nil, "a")
append_imper(forms, stem, nil, "и", "ите")
set_past(forms, stem .. "ол", nil, "", "а", "о", "и")
return forms
end
conjugations["10c"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"+p", "7"})
local inf_stem = com.strip_ending(get_stressed_arg(args, 2), nil, "ть")
-- present tense stressed stem "моло́ть" - ме́лет
local pres_stem = get_opt_stressed_arg(args, 3)
no_stray_args(args, 3)
local default_pres_stem =
com.make_ending_stressed(com.strip_ending(inf_stem, nil, "о́"))
pres_stem = pres_stem or default_pres_stem
-- remove accent for some forms
local pres_stem_noa = com.remove_accents(pres_stem)
local pres_note = pres_stem ~= default_pres_stem and IRREG
forms["infinitive"] = inf_stem .. "ть"
-- default for pres_pasv_part is blank
append_participles_2stem(forms, pres_stem, nil, inf_stem, nil,
"ющий", "-", "я́", "вший", "вши", "в", pres_note)
set_moving_ppp(forms, data)
present_je(forms, pres_stem, nil, "c", nil, pres_note)
append_imper(forms, pres_stem_noa, nil, "и́", "и́те", pres_note)
set_past(forms, inf_stem .. "л", nil, "", "а", "о", "и")
return forms
end
conjugations["11a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "ить")
no_stray_args(args, 2)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem .. "и")
forms["infinitive"] = stem .. "ить"
-- perfective only
append_participles(forms, stem, nil, "-", "-", "-", "ивший", "ивши", "ив")
present_je(forms, stem .. "ь", nil, "a")
append_imper(forms, stem .. "ей", nil, "", "те")
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["11b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p", "*"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "и́ть")
local pres_stem = get_opt_unstressed_arg(args, 3)
no_stray_args(args, 3)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem .. "и́", nil, "single_cons_base")
local default_pres_stem =
data.star and construct_long_prefix_variant(prefix) .. rsub(base, "и́$", "") or
stem
pres_stem = pres_stem or default_pres_stem
local pres_note = pres_stem ~= default_pres_stem and IRREG
forms["infinitive"] = stem .. "и́ть"
append_participles_2stem(forms, pres_stem, nil, stem, nil,
"ью́щий", "-", "ья́", "и́вший", "и́вши", "и́в", pres_note)
present_je(forms, pres_stem .. "ь", nil, "b", nil, pres_note)
append_imper(forms, stem .. "е́й", nil, "", "те")
-- e.g. пила́, лила́
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["12a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = get_opt_stressed_arg(args, 3)
no_stray_args(args, 3)
local default_pres_stem = stem
pres_stem = pres_stem or default_pres_stem
local pres_note = pres_stem ~= default_pres_stem and IRREG
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
append_participles_2stem(forms, pres_stem, nil, stem, nil,
"ющий", "емый", "я", "вший", "вши", "в", pres_note)
present_je(forms, pres_stem, nil, "a", nil, pres_note)
append_imper(forms, pres_stem .. "й", nil, "", "те", pres_note)
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["12b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = get_opt_unstressed_arg(args, 3)
no_stray_args(args, 3)
local default_pres_stem = com.make_unstressed_once(stem)
pres_stem = pres_stem or default_pres_stem
local pres_note = pres_stem ~= default_pres_stem and IRREG
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
append_participles_2stem(forms, pres_stem, nil, stem, nil,
"ю́щий", "-", "я́", "вший", "вши", "в", pres_note)
present_je(forms, pres_stem, nil, "b", nil, pres_note)
-- the preceding vowel is stressed
append_imper(forms, pres_stem .. "́й", nil, "", "те", pres_note)
-- e.g. гнила́ but пе́ла
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["13b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"+p"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = com.strip_ending(stem, nil, "ва́")
no_stray_args(args, 2)
forms["infinitive"] = stem .. "ть"
-- tricky to use append_participles_2stem() because only pres_actv_part
-- uses pres_stem, not all present participles
forms["pres_actv_part"] = pres_stem .. "ю́щий"
forms["pres_pasv_part"] = stem .. "емый"
forms["pres_adv_part"] = stem .. "я"
forms["past_actv_part"] = stem .. "вший"
forms["past_adv_part"] = stem .. "вши"
forms["past_adv_part_short"] = stem .. "в"
set_moving_ppp(forms, data)
present_je(forms, pres_stem, nil, "b")
forms["impr_sg"] = stem .. "й"
forms["impr_pl"] = stem .. "йте"
set_past(forms, stem .. "л", nil, "", "а", "о", "и")
return forms
end
conjugations["14a"] = function(args, data)
-- only one verb: вы́жать
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = get_stressed_arg(args, 3)
no_stray_args(args, 3)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- perfective only
append_participles(forms, stem, nil, "-", "-", "-", "вший", "вши", "в")
present_e_a(forms, pres_stem)
forms["impr_sg"] = pres_stem .. "и"
forms["impr_pl"] = pres_stem .. "ите"
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["14b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = get_unstressed_arg(args, 3)
no_stray_args(args, 3)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
append_participles_2stem(forms, pres_stem, nil, stem, nil,
"у́щий", "-", "я́", "вший", "вши", "в")
present_e_b(forms, pres_stem)
forms["impr_sg"] = pres_stem .. "и́"
forms["impr_pl"] = pres_stem .. "и́те"
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["14c"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = get_stressed_arg(args, 3)
local pres_stem_noa = com.make_unstressed(pres_stem)
no_stray_args(args, 3)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
append_participles_2stem(forms, pres_stem, nil, stem, nil,
"у́щий", "-", "я́", "вший", "вши", "в")
present_e_c(forms, pres_stem)
forms["impr_sg"] = pres_stem_noa .. "и́"
forms["impr_pl"] = pres_stem_noa .. "и́те"
--two forms for past_m: при́нялся, приня́лся
--изъя́ла but приняла́
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["15a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"+p"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "ть")
no_stray_args(args, 2)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, stem, nil, "нущий", "-", "-", "вший", "вши", "в")
present_e_a(forms, stem .. "н")
forms["impr_sg"] = stem .. "нь"
forms["impr_pl"] = stem .. "ньте"
set_past(forms, stem .. "л", nil, "", "а", "о", "и")
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["16a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "ть")
no_stray_args(args, 2)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, stem, nil, "ву́щий", "-", "-", "вший", "вши", "в")
present_e_a(forms, stem .. "в")
forms["impr_sg"] = stem .. "ви"
forms["impr_pl"] = stem .. "вите"
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["16b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = com.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local stem_noa = com.make_unstressed(stem)
no_stray_args(args, 2)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
append_participles(forms, stem, nil, "ву́щий", "-", "вя́", "вший", "вши", "в")
present_e_b(forms, stem_noa .. "в")
forms["impr_sg"] = stem_noa .. "ви́"
forms["impr_pl"] = stem_noa .. "ви́те"
-- e.g. прижило́сь, прижи́лось
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["irreg"] = function(args, data)
local main = select(3, split_known_main_verb(get_stressed_arg(args, 2),
-- честь must go before есть
{"бежа́ть", "бѣжа́ть", "хоте́ть", "хотѣ́ть", "да́ть", "че́сть",
"е́сть", "ѣ́сть", "сы́пать", "лга́ть", "мо́чь", "идти́", "йти́",
"е́хать", "ѣ́хать", "мину́ть", "живописа́ть", "ле́чь",
"зи́ждить", "зы́бить", "кля́сть", "стели́ть", "бы́ть", "сса́ть", "сца́ть",
"чти́ть", "шиби́ть", "реве́ть", "има́ть", "вня́ть", "обя́зывать"}))
main = com.make_unstressed_once(main)
if not conjugations["irreg-" .. main] then
error("Strange, can't find conjugation for main verb " .. main)
end
return conjugations["irreg-" .. main](args, data)
end
conjugations["irreg-бежать"] = function(args, data)
-- irregular, only for verbs derived from бежать with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2),
{"бежа́ть", "бѣжа́ть"})
data.title = com.is_stressed(prefix) and "5a" or "5b"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "бежа́ть"
append_participles_2stem(forms, "бег", nil, "бежа́", nil,
"у́щий", "-", "-", "вший", "вши", "в", IRREG)
append_imper(forms, "беги́", nil, "", "те", IRREG)
append_pres_futr(forms, "бе", nil,
"гу́" .. IRREG, "жи́шь", "жи́т", "жи́м", "жи́те", "гу́т" .. IRREG)
set_past(forms, "бежа́л", nil, "", "а", "о", "и")
if data.old then
rsub_forms(forms, "^бе", "бѣ")
end
prepend_prefix(forms, prefix)
-- no PPP's for any derivatives of бежать
return forms
end
conjugations["irreg-бѣжать"] = conjugations["irreg-бежать"]
conjugations["irreg-хотеть"] = function(args, data)
-- irregular, only for verbs derived from хотеть with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2),
{"хоте́ть", "хотѣ́ть"})
data.title = "5c'"
data.cat_conj_types = {"5c"} -- no class for 5c', no point in creating for just this verb
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "хоте́ть"
append_participles_2stem(forms, "хот", nil, "хоте́", nil,
"я́щий", "-", "я́", "вший", "вши", "в")
append_imper(forms, "хоти́", nil, "", "те")
append_pres_futr(forms, "", nil,
"хочу́", "хо́чешь" .. IRREG, "хо́чет" .. IRREG, "хоти́м", "хоти́те", "хотя́т")
set_past(forms, "хоте́л", nil, "", "а", "о", "и")
if data.old then
rsub_forms(forms, "^хоте", "хотѣ")
end
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-хотѣть"] = conjugations["irreg-хотеть"]
conjugations["irreg-дать"] = function(args, data)
-- irregular, only for verbs derived from дать with the same stress pattern and вы́дать
local forms = {}
--for this type, it's important to distinguish if it's reflexive to set some stress patterns
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "да́ть")
data.title = com.is_stressed(prefix) and "irreg-a" or "irreg-b"
parse_variants(data, args[1], {"past", "+p"})
no_stray_args(args, 2)
forms["infinitive"] = "да́ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, "", nil, "даю́щий", "-", "-",
"да́вший", "да́вши", "да́в")
append_imper(forms, "да́й", nil, "", "те")
append_pres_futr(forms, "", nil,
"да́м", "да́шь", "да́ст", "дади́м", "дади́те", "даду́т")
prepend_prefix(forms, prefix)
set_past_by_stress(forms, data.past_stress, prefix, nil, "да́", nil,
args, data)
if data.ppp then
if prefix == "пере" then
set_ppp(forms, "", nil, "пе́реданный")
elseif prefix == "раз" then
set_ppp(forms, "", nil, "ро́зданный")
else
set_moving_ppp(forms, data)
end
end
return forms
end
conjugations["irreg-есть"] = function(args, data)
-- irregular, only for verbs derived from есть
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2),
{"е́сть", "ѣ́сть"})
data.title = com.is_stressed(prefix) and "irreg-a" or "irreg-b"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "е́сть"
append_participles_2stem(forms, "ед", nil, "е́", nil,
"я́щий", "о́мый", "я́", "вший", "вши", "в")
if data.ppp then
set_ppp(forms, "е́д", nil, "енный")
end
append_imper(forms, "е́шь", nil, "", "те")
append_pres_futr(forms, "е́", nil,
"м", "шь", "ст", "ди́м", "ди́те", "дя́т")
set_past(forms, "е́л", nil, "", "а", "о", "и")
if data.old then
rsub_forms(forms, "^е", "ѣ")
end
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-ѣсть"] = conjugations["irreg-есть"]
conjugations["irreg-сыпать"] = function(args, data)
-- irregular, only for verbs derived from сыпать
local forms = {}
--for this type, it's important to distinguish if it's reflexive for вы́сыпаться vs. вы́сыпать imperative
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "сы́пать")
data.title = "6a"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "сы́пать"
append_participles(forms, "сы́п", nil,
"лющий", "лемый", {"ля", "я" .. IRREG}, "авший", "авши", "ав")
append_imper(forms, "сы́п", nil,
-- вы́сыпать (but not вы́сыпаться) has two imperative singulars
com.is_stressed(prefix) and not data.refl and {"и", "ь"} or "ь", "ьте", IRREG)
present_je(forms, "сы́пл", nil, "a")
append_pres_futr(forms, "сы́п", nil,
{}, "ешь", "ет", "ем", "ете", {}, IRREG)
set_past(forms, "сы́пал", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
set_moving_ppp(forms, data)
return forms
end
conjugations["irreg-лгать"] = function(args, data)
-- irregular, only for verbs derived from лгать with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "лга́ть")
data.title = "6°b/c"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "лга́ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, "лг", nil,
"у́щий", "-", "-", "а́вший", "а́вши", "а́в")
append_imper(forms, "лги́", nil, "", "те")
append_pres_futr(forms, "", nil,
"лгу́", "лжёшь" .. IRREG, "лжёт" .. IRREG, "лжём" .. IRREG, "лжёте" .. IRREG, "лгу́т")
set_past(forms, "лга́л", nil, "", "а́", "о", "и")
prepend_prefix(forms, prefix)
set_moving_ppp(forms, data)
return forms
end
conjugations["irreg-мочь"] = function(args, data)
-- irregular, only for verbs derived from мочь with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "мо́чь")
data.title = "8c/b"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "мо́чь"
-- no passive or adverbial participles
append_participles(forms, "мо́г", nil,
"у́щий", "-", "-", "ший", "-", "-")
append_imper(forms, "моги́", nil, "", "те")
append_pres_futr(forms, "", nil,
"могу́", "мо́жешь", "мо́жет", "мо́жем", "мо́жете", "мо́гут")
set_past(forms, "мо́г", nil, "", "ла́", "ло́", "ли́")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-идти"] = function(args, data)
-- irregular, only for verbs derived from идти, including прийти́ and в́ыйти
local forms = {}
local prefix = args[2] == "идти́" and "" or
split_known_main_verb(get_stressed_arg(args, 2), "йти́")
data.title = com.is_stressed(prefix) and "irreg-a" or "irreg-b/b"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
-- no pres_pasv_part
if prefix == "" then
-- only идти, present imperfective
forms["infinitive"] = "идти́"
append_imper(forms, "иди́", nil, "", "те")
present_e_b(forms, "ид")
-- no past_adv_part_short
append_participles(forms, "", nil,
"иду́щий", "-", "идя́", "ше́дший", "ше́дши", "-")
elseif rfind(prefix, "и$") then -- при
forms["infinitive"] = "йти́"
append_imper(forms, "ди́", nil, "", "те")
present_e_b(forms, "д")
append_participles(forms, "", nil,
"-", "-", "-", "ше́дший", "ше́дши", "дя́")
else
forms["infinitive"] = "йти́"
append_imper(forms, "йди́", nil, "", "те")
present_e_b(forms, "йд")
append_participles(forms, "", nil,
"-", "-", "-", "ше́дший", "ше́дши", "йдя́")
end
set_past(forms, "", nil, "шёл", "шла́", "шло́", "шли́")
prepend_prefix(forms, prefix)
if data.ppp then
if prefix == "на" or prefix == "про" then
-- найти́ and пройти́ exceptionally have the stress on the prefix
set_ppp(forms, prefix, nil, "́йденный")
else
-- вы́йти and прийти́ are intransitive so we don't have to worry about them
set_ppp(forms, prefix, nil, "йдённый")
end
end
return forms
end
conjugations["irreg-йти"] = conjugations["irreg-идти"]
conjugations["irreg-ехать"] = function(args, data)
-- irregular, only for verbs derived from ехать
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2),
{"е́хать", "ѣ́хать"})
data.title = "irreg-a"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "е́хать"
-- no pres_pasv_part
-- no pres_adv_part
append_participles_2stem(forms, "е́д", nil, "е́х", nil,
"ущий", "-", "-", "авший", "авши", "ав")
present_e_a(forms, "е́д")
set_past(forms, "е́хал", nil, "", "а", "о", "и")
if data.old then
rsub_forms(forms, "^е", "ѣ")
end
prepend_prefix(forms, prefix)
--special-case the imperative
--literary (special) imperative forms for ехать are поезжа́й, поезжа́йте
local impstem = data.old and "ѣзжа́й" or "езжа́й"
if prefix == "" then
append_imper(forms, "по" .. impstem, nil, "", "те")
append_imper(forms, impstem, nil, "", "те")
elseif com.is_stressed(prefix) then
append_imper(forms, com.make_unstressed_once(prefix) .. impstem, nil, "", "те")
else
append_imper(forms, prefix .. impstem, nil, "", "те")
end
return forms
end
conjugations["irreg-ѣхать"] = conjugations["irreg-ехать"]
conjugations["irreg-минуть"] = function(args, data)
-- for the irregular verb "мину́ть"
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "мину́ть")
data.title = "3c"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "мину́ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, "ми́н", nil,
"у́щий", "-", "-", "у́вший", "у́вши", "у́в")
present_e_c(forms, "ми́н")
forms["pres_futr_1sg"] = "-" -- no futr 1sg
-- no imperative
-- two possible variants, one with root-only stress, the other with
-- either root or suffix stress.
if not args["root_past_stress"] then
append_past(forms, "мину́л", nil, "", "а", "о", "и")
end
append_past(forms, "ми́нул", nil, "", "а", "о", "и", IRREG)
prepend_prefix(forms, prefix)
set_moving_ppp(forms, data)
return forms
end
conjugations["irreg-живописать"] = function(args, data)
-- for irregular verb "живописа́ть", mixture of types 1 and 2
local forms = {}
local inf = get_stressed_arg(args, 2)
data.title = "1a"
parse_variants(data, args[1], {"+p"})
local inf_stem = com.strip_ending(inf, nil, "ть")
local pres_stem = rfind(inf_stem, "а́$") and rsub(inf_stem, "а́$", "у́")
or error("Unexpected infinitive " .. inf)
no_stray_args(args, 2)
forms["infinitive"] = inf_stem .. "ть"
-- no pres_pasv_part
append_participles_2stem(forms, pres_stem, nil, inf_stem, nil,
"ющий", "-", "я", "вший", "вши", "в", IRREG)
set_moving_ppp(forms, data)
present_je(forms, pres_stem, nil, "a", nil, IRREG)
append_imper(forms, pres_stem .. "й", nil, "", "те", IRREG)
set_past(forms, inf_stem .. "л", nil, "", "а", "о", "и")
return forms
end
conjugations["irreg-лечь"] = function(args, data)
-- irregular, only for verbs derived from лечь with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "ле́чь")
data.title = "8a/b"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "ле́чь"
-- no pres parts because always perfective
-- no past_adv_part_short
append_participles(forms, "лёг", nil,
"-", "-", "-", "ший", "ши", "-")
append_imper(forms, "ля́г", nil, "", "те", IRREG)
append_pres_futr(forms, "ля́", nil,
"гу", "жешь", "жет", "жем", "жете", "гут", IRREG)
set_past(forms, "", nil, "лёг", "легла́", "легло́", "легли́")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-честь"] = function(args, data)
-- irregular, only for verbs derived from идти, including прийти́ and в́ыйти
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "че́сть")
local pre_two_cons_prefix =
prefix == "об" and "обо" or
prefix == "с" and "со" or
prefix == "рас" and "разо" or
prefix
data.title = prefix == "" and "7b/b" or com.is_stressed(prefix) and "7a⑨" or
pre_two_cons_prefix ~= prefix and "7*b/b⑨" or "7b/b⑨"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
-- no pres_pasv_part
forms["infinitive"] = "че́сть"
append_imper(forms, "чти́", nil, "", "те", IRREG)
present_e_b(forms, "чт", nil, IRREG)
if prefix == "" then
append_participles(forms, "", nil,
"чту́щий", "-", "чтя́", "чти́вший", "чти́вши", "чти́в", IRREG)
elseif com.is_stressed(prefix) then
append_participles(forms, "", nil,
"-", "-", "-", "-", "чтя́", "-", IRREG)
else
append_participles(forms, "", nil,
"-", "-", "-", "-", {"чтя́" .. IRREG, "чётши*"}, "-")
m_table.insertIfNot(data.internal_notes, "* Dated.")
end
if data.ppp then
set_ppp(forms, "", nil, "чтённый" .. IRREG)
end
set_past(forms, "", nil, "чёл", "чла́" .. IRREG, "чло́" .. IRREG, "чли́" .. IRREG)
prepend_prefix(forms, prefix, pre_two_cons_prefix)
return forms
end
conjugations["irreg-зиждить"] = function(args, data)
-- irregular, only for verbs derived from зиждить(ся) with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "зи́ждить")
data.title = "irreg-a"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "зи́ждить"
append_participles(forms, "зи́жд", nil,
"ущий", "емый", "я", "ивший", "ивши", "ив")
if data.ppp then
set_ppp(forms, "зи́жд", nil, "енный")
end
append_imper(forms, "зи́жди", nil, "", "те")
present_e_a(forms, "зи́жд")
set_past(forms, "зи́ждил", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-зыбить"] = function(args, data)
-- irregular, only for verbs derived from зыбить
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "зы́бить")
data.title = "irreg-a"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "зы́бить"
append_participles(forms, "зы́б", nil,
"лющий", "лемый", "ля", "ивший", "ивши", "ив")
append_imper(forms, "зы́бли", nil, "", "те")
present_je(forms, "зы́б", nil, "a")
set_past(forms, "зы́бил", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-клясть"] = function(args, data)
-- irregular, only for verbs derived from клясть with the same stress pattern
local forms = {}
--for this type, it's important to distinguish if it's reflexive to set some stress patterns
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "кля́сть")
data.title = "irreg-b"
parse_variants(data, args[1], {"past", "+p"})
no_stray_args(args, 2)
forms["infinitive"] = "кля́сть"
append_participles_2stem(forms, "клян", nil, "кля́", nil,
"у́щий", "и́мый", "я́", "вший", "вши", "в")
append_imper(forms, "кляни́", nil, "", "те")
present_e_b(forms, "клян")
prepend_prefix(forms, prefix)
set_past_by_stress(forms, data.past_stress, prefix, nil, "кля́", nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["irreg-стелить"] = function(args, data)
-- irregular, only for verbs derived from стелить
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "стели́ть")
data.title = com.is_stressed(prefix) and "4a" or "4c"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "стели́ть"
append_participles(forms, "сте́л", nil,
"ющий" .. IRREG, "и́мый", "я́", "и́вший", "и́вши", "и́в")
set_class_4_ppp(forms, data, "сте́л", nil, data.title)
append_imper(forms, "стели́", nil, "", "те")
append_pres_futr(forms, "сте́л", nil, "ю́", {}, {}, {}, {}, {})
append_pres_futr(forms, "сте́л", nil, {}, "ешь", "ет", "ем", "ете", "ют", IRREG)
set_past(forms, "стели́л", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-быть"] = function(args, data)
-- irregular, only for verbs derived from быть with various stress patterns, the actual verb быть different from its derivatives
local forms = {}
--for this type, it's important to distinguish if it's reflexive to set some stress patterns
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "бы́ть")
data.title = "irreg-a"
parse_variants(data, args[1], {"past", "+p"})
no_stray_args(args, 2)
forms["infinitive"] = "бы́ть"
-- no pres_pasv_part
append_participles(forms, "", nil, "су́щий", "-", "бу́дучи",
"бы́вший", "бы́вши", "бы́в")
append_imper(forms, "бу́дь", nil, "", "те")
prepend_prefix(forms, prefix)
-- only for "бы́ть", some forms are archaic
if forms["infinitive"] == "бы́ть" then
append_pres_futr(forms, "", nil, "есть", "есть", "есть", "есть", "есть", "есть")
elseif com.is_stressed(prefix) then
-- if the prefix is stressed, e.g. "вы́быть"
present_e_a(forms, prefix .. "буд")
else
present_e_a(forms, prefix .. "бу́д")
end
set_past_by_stress(forms, data.past_stress, prefix, nil, "бы́", nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["irreg-ссать-сцать"] = function(args, data)
-- irregular, only for verbs derived from ссать and сцать (both vulgar!)
local forms = {}
local prefix, _, stem = split_known_main_verb(get_stressed_arg(args, 2),
{"сса́ть", "сца́ть"})
data.title = com.is_stressed(prefix) and "irreg-a" or "irreg-b"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
stem = com.strip_ending(stem, nil, "ть")
local pres_stem = rsub(stem, "а́?$", "")
no_stray_args(args, 2)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, pres_stem, nil, "у́щий", "-", "-",
"а́вший", "а́вши", "а́в")
append_imper(forms, pres_stem, nil, "ы́", "ы́те")
append_pres_futr(forms, pres_stem, nil,
"у́", "ы́шь", "ы́т", "ы́м", "ы́те", "у́т")
set_past(forms, stem .. "л", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-ссать"] = conjugations["irreg-ссать-сцать"]
conjugations["irreg-сцать"] = conjugations["irreg-ссать-сцать"]
conjugations["irreg-чтить"] = function(args, data)
-- irregular, only for verbs derived from чтить
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "чти́ть")
data.title = "4b"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "чти́ть"
append_participles_2stem(forms, "чт", nil, "чти́", nil,
{"я́щий", "у́щий" .. IRREG}, "и́мый", "я́", "вший", "вши", "в")
if data.ppp then
set_ppp(forms, "чт", nil, "ённый")
end
append_imper(forms, "чти́", nil, "", "те")
append_pres_futr(forms, "чт", nil,
"у́" .. IRREG, "и́шь", "и́т", "и́м", "и́те", {"я́т", "у́т" .. IRREG})
set_past(forms, "чти́л", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-шибить"] = function(args, data)
-- irregular, only for verbs in -шибить(ся)
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "шиби́ть")
data.title = com.is_stressed(prefix) and "irreg-a" or "irreg-b"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
-- no present participles
forms["infinitive"] = "шиби́ть"
append_participles(forms, "шиби́", nil,
"-", "-", "-", "вший", "вши", "в")
if data.ppp then
set_ppp(forms, "ши́бл", nil, "енный")
end
append_imper(forms, "шиби́", nil, "", "те")
present_e_b(forms, "шиб")
set_past(forms, "ши́б", nil, "", "ла", "ло", "ли")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-реветь"] = function(args, data)
-- irregular, only for verbs derived from "реветь"
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "реве́ть")
data.title = "irreg-b"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "реве́ть"
-- no pres_pasv_part
append_participles_2stem(forms, "рев", nil, "реве́", nil,
"у́щий", "-", "я́", "вший", "вши", "в")
present_e_b(forms, "рев")
append_imper(forms, "реви́", nil, "", "те")
set_past(forms, "реве́л", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-имать"] = function(args, data)
-- irregular, only for внимать and certain archaic verbs (e.g. имать as
-- conjugated in the 18th century, отъимать)
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "има́ть")
data.title = "1a // 6a"
data.cat_conj_types = {"1a", "6a"}
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "има́ть"
-- handle внемл- forms
append_participles(forms, "е́мл", nil,
"ющий", "емый", {"я", "я́"}, {}, {}, {})
-- handle внима́- forms
append_participles(forms, "има́", nil,
"ющий", "емый", "я", "вший", "вши", "в")
if data.ppp then
-- FIXME, do class-1a-type ppp's (e.g. вни́манный) exist?
-- ruwikt marks them with a *
set_ppp(forms, "е́мл", nil, "енный")
end
append_imper(forms, "", nil, {"е́мли", "емли́", "има́й"},
{"е́млите", "емли́те", "има́йте"})
present_je(forms, "е́мл", nil, "a")
-- Both вне́млю and внемлю́ are possible
append_pres_futr(forms, "емл", nil, "ю́", {}, {}, {}, {}, {})
present_je(forms, "има́", nil, "a")
set_past(forms, "има́л", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-внять"] = function(args, data)
-- irregular, only for внять
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "вня́ть")
data.title = "14c/c"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "вня́ть"
-- perfective only; no present participles
append_participles(forms, "вня́", nil,
"-", "-", "-", "вший", "вши", "в")
append_imper(forms, "вними́", nil, "", "те")
append_imper(forms, "вонми́", nil, "", "те")
present_e_c(forms, "вни́м")
present_e_c(forms, "во́нм")
set_past(forms, "вня́л", nil, "", "а́", "о", "и")
set_ppp_from_past_m(forms, args, data)
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-обязывать"] = function(args, data)
-- irregular, only for обязывать and обязываться
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "обя́зывать")
data.title = "1a"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "обя́зывать"
append_participles_2stem(forms, "обя́з", nil, "обя́зыва", nil,
{"ывающий", "у́ющий"}, {"ываемый", "у́емый"}, {"ывая", "у́я"}, "вший", "вши", "в")
append_imper(forms, "обя́зывай", nil, "", "те")
append_imper(forms, "обязу́й", nil, "", "те")
present_je(forms, "обя́зыва", nil, "a")
present_je(forms, "обязу́", nil, "a")
set_past(forms, "обя́зывал", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
--[=[
Partial conjugation functions
]=]
-- Present forms with -e-, no j-vowels.
present_e_a = function(forms, stem, tr, note)
append_pres_futr(forms, stem, tr, "у", "ешь", "ет", "ем", "ете", "ут", note)
end
present_e_b = function(forms, stem, tr, note)
append_pres_futr(forms, stem, tr, "у́", "ёшь", "ёт", "ём", "ёте", "у́т", note)
end
present_e_c = function(forms, stem, tr, note)
append_pres_futr(forms, stem, tr, "у́", "ешь", "ет", "ем", "ете", "ут", note)
end
-- Present forms with -e- and iotated stem. ABC = "a", "b" or "c", indicating
-- the accent pattern. If SHCH is set, iotate final т as щ, not ч. If NOTE
-- is given, add it to each form.
present_je = function(forms, stem, tr, abc, shch, note)
local iotated_stem, iotated_tr = com.iotation(stem, tr, shch)
assert(abc == "a" or abc == "b" or abc == "c")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(iotated_stem, "[шщжч]$") -- or no_iotation
local ending_1sg =
hushing and (abc == "a" and "у" or "у́") or
not hushing and (abc == "a" and "ю" or "ю́")
if abc == "b" then
append_pres_futr(forms, iotated_stem, iotated_tr,
{}, "ёшь", "ёт", "ём", "ёте", (hushing and "у́т" or "ю́т"), note)
else
append_pres_futr(forms, iotated_stem, iotated_tr,
{}, "ешь", "ет", "ем", "ете", (hushing and "ут" or "ют"), note)
end
append_pres_futr(forms, iotated_stem, iotated_tr,
ending_1sg, {}, {}, {}, {}, {}, note)
end
-- Present forms with -i- (and iotated stem in the 1sg). ABC = "a", "b" or "c",
-- indicating the accent pattern. If SHCH is set, iotate final т as щ, not ч.
-- If NOTE is given, add it to each form.
present_i = function(forms, stem, tr, abc, shch, note)
local iotated_stem, iotated_tr = com.iotation(stem, tr, shch)
assert(abc == "a" or abc == "b" or abc == "c")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local iotated_hushing = rfind(iotated_stem, "[шщжч]$")
local hushing = rfind(stem, "[шщжч]$")
local ending_1sg =
iotated_hushing and (abc == "a" and "у" or "у́") or
not iotated_hushing and (abc == "a" and "ю" or "ю́")
if abc == "b" then
append_pres_futr(forms, stem, tr,
{}, "и́шь", "и́т", "и́м", "и́те", hushing and "а́т" or "я́т", note)
else
append_pres_futr(forms, stem, tr,
{}, "ишь", "ит", "им", "ите", hushing and "ат" or "ят", note)
end
append_pres_futr(forms, iotated_stem, iotated_tr,
ending_1sg, {}, {}, {}, {}, {}, note)
end
-- Add the reflexive particle to all verb forms
make_reflexive = function(forms, reflex_stress)
for key, form in pairs(forms) do
local ru, tr = extract_russian_tr(form)
-- check for empty string, dashes and nil's
if ru and ru ~= "" and ru ~= "-" then
local ruentry, runotes = m_table_tools.separate_notes(ru)
local trentry, trnotes
if tr then
trentry, trnotes = m_table_tools.separate_notes(tr)
end
if is_vowel_stem(ruentry) then
forms[key] = {ruentry .. "сь" .. runotes, trentry and trentry .. "sʹ" .. trnotes}
-- if a past_m form doesn't contain a stress, add a stressed
-- particle "ся́" if called for
elseif reflex_stress and com.is_unstressed(ruentry) and rfind(key, "^past_m") then
forms[key] = {ruentry .. "ся́" .. runotes, trentry and trentry .. "sja" .. AC .. trnotes}
else
forms[key] = {ruentry .. "ся" .. runotes, trentry and trentry .. "sja" .. trnotes}
end
end
end
end
-- Convert verb forms to pre-reform style by adding ъ to consonant-final
-- forms (excluding those ending in й and ь) and converting -ий to -ій and
-- -ийся to -ійся
make_pre_reform = function(forms)
for key, form in pairs(forms) do
local ru, tr = extract_russian_tr(form)
-- check for empty string, dashes and nil's
if ru and ru ~= "" and ru ~= "-" then
local ruentry, runotes = m_table_tools.separate_notes(ru)
if rfind(ruentry, "[бцдфгчклмнпрствшхзжщ]$") then
forms[key] = {ruentry .. "ъ" .. runotes, tr}
else
forms[key] = {rsub(rsub(ruentry, "ий$", "ій"), "ийся$", "ійся") .. runotes, tr}
end
end
end
end
local function setup_pres_futr(forms, perf, old)
-- Copy the main form FROMFORM to the main form TOFORM, and copy all
-- associated alternative forms.
local function copy_form(fromform, toform)
local fromforms = main_to_all_verb_forms[fromform]
local toforms = main_to_all_verb_forms[toform]
local numforms = #fromforms
assert(#toforms == numforms)
for i=1,numforms do
forms[toforms[i]] = forms[fromforms[i]]
end
end
-- Copy pres_futr_* to pres_* (imperfective) or futr_* (perfective).
if perf then
copy_form("pres_futr_1sg", "futr_1sg")
copy_form("pres_futr_2sg", "futr_2sg")
copy_form("pres_futr_3sg", "futr_3sg")
copy_form("pres_futr_1pl", "futr_1pl")
copy_form("pres_futr_2pl", "futr_2pl")
copy_form("pres_futr_3pl", "futr_3pl")
else
copy_form("pres_futr_1sg", "pres_1sg")
copy_form("pres_futr_2sg", "pres_2sg")
copy_form("pres_futr_3sg", "pres_3sg")
copy_form("pres_futr_1pl", "pres_1pl")
copy_form("pres_futr_2pl", "pres_2pl")
copy_form("pres_futr_3pl", "pres_3pl")
end
local futr_data = {
{"futr_1sg", "бу́ду", "búdu"},
{"futr_2sg", "бу́дешь", "búdešʹ"},
{"futr_3sg", "бу́дет" .. (old and "ъ" or ""), "búdet"},
{"futr_1pl", "бу́дем" .. (old and "ъ" or ""), "búdem"},
{"futr_2pl", "бу́дете", "búdete"},
{"futr_3pl", "бу́дут" .. (old and "ъ" or ""), "búdut"}
}
local function insert_future(inf, inf_tr)
for _, fut in ipairs(futr_data) do
append_to_arg_chain(forms, fut[1], fut[1],
{fut[2] .. inf, inf_tr and fut[3] .. inf_tr})
end
end
-- Insert future, if required (there may conceivably be multiple infitives).
for _, form in ipairs(main_to_all_verb_forms["infinitive"]) do
local infinitive = forms[form]
if infinitive then
local inf, inf_tr = extract_russian_tr(forms[form])
-- only for "бы́ть" the future forms are бу́ду, бу́дешь, etc.
if inf == "бы́ть" then
insert_future("", nil)
elseif not perf then
insert_future(" " .. inf, inf_tr and " " .. inf_tr)
end
end
end
end
parse_and_stress_override = function(form, val, existing, all_existing)
if rfind(form, "^pres_futr") then
error("Overrides of pres_futr* are illegal, use pres_* or futr_*")
end
local allow_unaccented
val, allow_unaccented = rsubb(val, "^%*", "")
local ru, tr = com.split_russian_tr(val)
-- past_m can be unaccented in connection with reflex_stress=ся́
if not allow_unaccented and not rfind(form, "^past_m") then
if tr and com.is_unstressed(ru) ~= com.is_unstressed(tr) then
error("Override " .. form .. "=" .. ru .. " and translit " .. tr .. " must have same accent pattern")
end
if com.is_monosyllabic(ru) then
ru, tr = com.make_ending_stressed(ru, tr)
elseif com.needs_accents(ru) then
error("Override " .. form .. "=" .. ru .. " requires an accent")
end
end
if rfind(ru, "%+") then
-- If either the existing or override has manual translit, the resulting
-- form should have manual translit. We specify ALWAYS_TRANSLIT if
-- the override has manual translit, so that we can substitute the
-- existing translit into the override translit.
local existing_ru, existing_tr = extract_russian_tr(existing, not not tr)
-- used especially for present participles; substitute existing form,
-- minus any "awkward-" or "none-" prefixes.
ru = rsub(ru, "%+", strip_arg_status_prefix(existing_ru))
-- If there's existing translit but not in the override, make sure it's
-- carried along.
if existing_tr and not tr then
tr = com.translit(ru)
end
tr = tr and rsub(tr, "%+", strip_arg_status_prefix(existing_tr))
end
-- If there's an override and it doesn't match an existing form, it's
-- irregular and indicate it using the IRREG marker. We don't do this if
-- the override simply removes a form. We do do this if there aren't any
-- existing forms, on the theory that the presence of a form when none is
-- normally called for is an irregularity. When comparing against the
-- existing forms, strip any status prefix (e.g. 'awkward-').
if all_existing then
local all_existing_stripped = {}
for _, ae in ipairs(all_existing) do
local existing_ru, existing_tr = extract_russian_tr(ae)
existing_ru = strip_arg_status_prefix(existing_ru)
existing_tr = existing_tr and strip_arg_status_prefix(existing_tr)
table.insert(all_existing_stripped, {existing_ru, existing_tr})
end
if ru ~= "-" and not contains_form(all_existing_stripped, {ru, tr}) then
ru = ru .. IRREG
tr = tr and tr .. IRREG
end
end
return {ru, tr}
end
-- Set up pres_* or futr_*; handle *sym/*tail/*tailall notes and overrides.
handle_forms_and_overrides = function(args, forms, data)
setup_pres_futr(forms, data.perf, data.old)
--handle overrides (formerly we only had past_pasv_part as a
--general override, plus scattered main-form overrides in particular
--conjugation classes)
for _, all_forms in pairs(main_to_all_verb_forms) do
local i = 0
local orig_forms = {}
for _, form in ipairs(all_forms) do
if forms[form] then
table.insert(orig_forms, forms[form])
end
end
for _, form in ipairs(all_forms) do
i = i + 1
-- If we auto-generated the past passive participle in order to
-- check for irregular overrides, make sure to erase any such
-- participles that weren't overridden. This happens for example
-- in обнять, where there are two automatically generated past
-- passive participles but a single ppp=о́внятый override.
local override = args[form] or (
data.ppp_auto_generated and rfind(form, "^past_pasv_part") and "-"
)
if override then
forms[form] = parse_and_stress_override(form, override,
forms[form], orig_forms)
elseif i == 1 then
forms[form] = forms[form] or ""
end
end
end
local function append_value(forms, prop, value)
if forms[prop] and forms[prop] ~= "" and forms[prop] ~= "-" then
value = com.split_russian_tr(value, "dopair")
local curval = forms[prop]
if type(curval) == "string" then
curval = {curval}
end
forms[prop] = com.concat_paired_russian_tr(curval, value)
end
end
local function append_note_all(forms, proplist, value)
for _, prop in ipairs(proplist) do
append_value(forms, prop, value)
end
end
local function append_note_last(forms, proplist, value, gt_one)
local numprops = 0
local lastprop
-- Find the last property in the series with a value
for _, prop in ipairs(proplist) do
if forms[prop] and forms[prop] ~= "" and forms[prop] ~= "-" then
numprops = numprops + 1
lastprop = prop
end
end
if numprops > (gt_one and 1 or 0) then
append_value(forms, lastprop, value)
end
end
for _, proplist in ipairs(all_verb_forms) do
-- Handle PROP_sym, which applies to all overridable properties, including
-- alternative forms, and applies to exactly that property.
for _, prop in ipairs(proplist) do
if args[prop .. "_sym"] then
append_value(forms, prop, args[prop .. "_sym"])
end
end
local propname = proplist[1]
-- Handle PROP_tail, which applies to a series of properties (e.g. past_m,
-- past_m2, ...) and appends to the last one.
if args[propname .. "_tail"] then
append_note_last(forms, proplist, args[propname .. "_tail"])
end
-- Handle PROP_tailall, which applies to a series of properties and
-- appends to all.
if args[propname .. "_tailall"] then
append_note_all(forms, proplist, args[propname .. "_tailall"])
end
end
-- Now handle pasttail, pasttailall, prestail, prestailall, etc.
-- Table listing tail-arg prefix and corresponding verb forms.
local tailargs = {
{"past", past_verb_forms},
{"pres", pres_verb_forms},
{"futr", futr_verb_forms},
{"impr", impr_verb_forms},
{"part", part_verb_forms},
{"prespart", pres_part_verb_forms},
{"pastpart", past_part_verb_forms},
{"", all_main_verb_forms}
}
for _, tailspec in ipairs(tailargs) do
local tailforms = tailspec[2]
-- Handle the ...tail variants.
local tailarg = tailspec[1] .. "tail"
if args[tailarg] then
track(tailarg)
for _, prop in ipairs(tailforms) do
append_note_last(forms, main_to_all_verb_forms[prop], args[tailarg], ">1")
end
end
-- Handle the ...tailall variants.
local tailallarg = tailspec[1] .. "tailall"
if args[tailallarg] then
track(tailallarg)
for _, prop in ipairs(tailforms) do
append_note_all(forms, main_to_all_verb_forms[prop], args[tailallarg])
end
end
end
end
-- Finish generating the forms; primarily, clear out unused forms.
finish_generating_forms = function(forms, data)
-- Convert any main form that's nil (meaning no forms at all corresponding
-- to this main form) to the empty string.
for main_form, _ in pairs(main_to_all_verb_forms) do
if not forms[main_form] then
forms[main_form] = ""
end
end
-- Set the main form FORM to the empty string, and corresponding alt forms
-- to nil.
local function clear_form(form)
local i = 0
for _, altform in ipairs(main_to_all_verb_forms[form]) do
i = i + 1
if i == 1 then
forms[altform] = ""
else
forms[altform] = nil
end
end
end
-- Intransitive and reflexive verbs have no passive participles
-- (unless has_prpp=y and/or has_ppp=y).
if data.intr or data.refl then
if not data.has_prpp then
clear_form("pres_pasv_part")
end
if not data.has_ppp then
clear_form("past_pasv_part")
end
end
if data.refl then
-- no past_adv_part_short for reflexive verbs
clear_form("past_adv_part_short")
end
-- Impersonal verbs normally have no passive participles, but allow them
-- if there's specifically an override. We only do this for the present
-- passive participle because the past passive participle isn't inserted
-- by default, and we still want +p to work, which doesn't currently set
-- data.ppp_override.
if data.impers and not data.prpp_override then
clear_form("pres_pasv_part")
end
if data.impers then
clear_form("pres_1sg")
clear_form("pres_2sg")
clear_form("pres_1pl")
clear_form("pres_2pl")
clear_form("pres_3pl")
clear_form("futr_1sg")
clear_form("futr_2sg")
clear_form("futr_1pl")
clear_form("futr_2pl")
clear_form("futr_3pl")
clear_form("past_m")
clear_form("past_f")
clear_form("past_pl")
clear_form("past_m_short")
clear_form("past_f_short")
clear_form("past_pl_short")
clear_form("pres_actv_part")
clear_form("past_actv_part")
clear_form("pres_adv_part")
clear_form("past_adv_part")
clear_form("past_adv_part_short")
clear_form("impr_sg")
clear_form("impr_pl")
end
-- Perfective and iterative verbs have no present forms, as well as
-- verbs marked nopres=1.
if data.perf or data.iter or data.nopres then
clear_form("pres_actv_part")
clear_form("pres_pasv_part")
clear_form("pres_adv_part")
clear_form("pres_1sg")
clear_form("pres_2sg")
clear_form("pres_3sg")
clear_form("pres_1pl")
clear_form("pres_2pl")
clear_form("pres_3pl")
end
-- Some verbs (e.g. грясти́, густи́) have no past
if data.nopast then
clear_form("past_m")
clear_form("past_f")
clear_form("past_n")
clear_form("past_pl")
clear_form("past_m_short")
clear_form("past_f_short")
clear_form("past_n_short")
clear_form("past_pl_short")
clear_form("past_actv_part")
clear_form("past_pasv_part")
clear_form("past_adv_part")
clear_form("past_adv_part_short")
end
-- Iterative verbs and verbs marked noimpr=1 have no imperative forms.
if data.iter or data.noimpr then
clear_form("impr_sg")
clear_form("impr_pl")
end
-- Iterative verbs and verbs marked nofutr=1 have no future forms.
if data.iter or data.nofutr then
clear_form("futr_1sg")
clear_form("futr_2sg")
clear_form("futr_3sg")
clear_form("futr_1pl")
clear_form("futr_2pl")
clear_form("futr_3pl")
end
--handle "none-" and "awkward-" prefixes (used especially for pres_pasv_part)
local footnote_sym = nil
for _, all_forms in pairs(main_to_all_verb_forms) do
local i = 0
for _, form in ipairs(all_forms) do
i = i + 1
if forms[form] then
local formru, formtr = extract_russian_tr(forms[form])
if rfind(formru, "^none%-") then
if i == 1 then
forms[form] = ""
else
forms[form] = nil
end
elseif rfind(formru, "^awkward%-") then
if not footnote_sym then
footnote_sym = next_note_symbol(data)
m_table.insertIfNot(data.internal_notes, footnote_sym .. " Rare and awkward.")
end
forms[form] = {rsub(formru, "^awkward%-", "") .. footnote_sym,
formtr and rsub(formtr, "^awkward%-", "") .. footnote_sym}
end
end
end
end
--Insert footnote for IRREG symbol if present.
for _, all_forms in pairs(main_to_all_verb_forms) do
for _, form in ipairs(all_forms) do
if forms[form] then
local formru = extract_russian_tr(forms[form])
if rfind(formru, IRREG) then
m_table.insertIfNot(data.internal_notes, IRREG .. " Irregular.")
end
end
end
end
end
local accel_forms = {
-- present tense
pres_1sg = "1|s|pres|ind",
pres_2sg = "2|s|pres|ind",
pres_3sg = "3|s|pres|ind",
pres_1pl = "1|p|pres|ind",
pres_2pl = "2|p|pres|ind",
pres_3pl = "3|p|pres|ind",
-- future tense
futr_1sg = "1|s|fut|ind",
futr_2sg = "2|s|fut|ind",
futr_3sg = "3|s|fut|ind",
futr_1pl = "1|p|fut|ind",
futr_2pl = "2|p|fut|ind",
futr_3pl = "3|p|fut|ind",
-- imperative
impr_sg = "2|s|imp",
impr_pl = "2|p|imp",
-- past
past_m = "m|s|past|ind",
past_f = "f|s|past|ind",
past_n = "n|s|past|ind",
past_pl = "p|past|ind",
past_m_short = "short|m|s|past|ind",
past_f_short = "short|f|s|past|ind",
past_n_short = "short|n|s|past|ind",
past_pl_short = "short|p|past|ind",
-- active participles
pres_actv_part = "pres|act|part",
past_actv_part = "past|act|part",
-- passive participles
pres_pasv_part = "pres|pass|part",
past_pasv_part = "past|pass|part",
-- adverbial participles
pres_adv_part = "pres|adv|part",
past_adv_part = "past|adv|part",
past_adv_part_short = "short|past|adv|part",
-- infinitive
infinitive = "inf",
}
-- Make the table
make_table = function(forms, title, perf, intr, impers, notes, internal_notes, old)
local infinitives = {}
for _, form in ipairs(main_to_all_verb_forms["infinitive"]) do
local infinitive = forms[form]
if infinitive then
local inf = extract_russian_tr(forms[form])
if inf ~= "-" then
m_table.insertIfNot(infinitives, inf)
end
end
end
-- Group forms together for a given key and combine adjacent forms with the same
-- Russian (they should always have different translits). Take care not to introduce
-- manual translit unnecessarily.
local grouped_forms = {}
for dispform, sourceforms in pairs(disp_verb_form_map) do
local entry = {}
for _, form in ipairs(sourceforms) do
local ru, tr = extract_russian_tr(forms[form])
-- check for empty strings, dashes and nil's
if ru and ru ~= "" and ru ~= "-" and ru ~= "—" then
if #entry > 0 then
local lastru, lasttr = extract_russian_tr(entry[#entry])
if lastru == ru then
if not lasttr and not tr or lasttr == tr then
error("Russian form " .. ru .. " is duplicated, probably due to a duplicative override")
end
lasttr = lasttr or com.translit(lastru)
tr = tr or com.translit(ru)
entry[#entry] = {ru, lasttr .. " ''or'' " .. tr}
else
table.insert(entry, {ru, tr})
end
else
table.insert(entry, {ru, tr})
end
end
end
grouped_forms[dispform] = entry
end
local title = (old and "Pre-reform conjugation" or "Conjugation") .. (#infinitives == 0 and "" or
" of <span lang=\"ru\" class=\"Cyrl\">''" .. table.concat(infinitives, ", ") .. "''</span>") ..
(title and " (" .. title .. ")" or "")
local function add_links(ru, rusuf, runotes, tr, trnotes, accel)
local ruspan
ruspan = m_links.full_link({lang = lang, term = ru, accel = accel, tr = "-"})
if rusuf ~= "" then
rusuf = "<span lang=\"ru\" class=\"Cyrl\">" .. rusuf .. "</span>"
end
return ruspan .. rusuf .. runotes .. "<br/>" .. require("Modül:alfabe araçları").tag_translit(tr .. trnotes, lang, "default", 'style="color:var(--wikt-palette-grey-8,#888);"')
end
-- NOTE: No need to check for multiple infinitives because the accel system
-- doesn't support multiple lemmas.
local lemma, lemmatr = extract_russian_tr(forms["infinitive"])
-- check for empty strings, dashes and nil's
if lemma and lemma ~= "" and lemma ~= "-" and lemma ~= "—" then
lemma = m_table_tools.separate_notes(lemma)
if lemmatr then
lemmatr = m_table_tools.separate_notes(lemmatr)
end
else
-- In case the lemma is an empty string or dash, set to nil so we don't
-- set a lemma in the accelerator and fall back to the page name.
lemma = nil
lemmatr = nil
end
-- Convert to displayed form
local disp = {}
for key, entry in pairs(grouped_forms) do
for i, form in ipairs(entry) do
local ru, origtr = extract_russian_tr(form)
local tr = origtr or ru and com.translit(ru)
local ruentry, runotes = m_table_tools.get_notes(ru)
local trentry, trnotes = m_table_tools.get_notes(tr)
local accel_form = accel_forms[key]
if not accel_form then
error("Unrecognized key " .. key .. " when looking up accelerator form")
end
local accel
if origtr and origtr:find(" ''or'' ") then
-- Multiple translits for a given Russian term.
-- FIXME! Support this.
accel = nil
else
accel = { form = accel_form, translit = origtr,
lemma = lemma, lemma_translit = lemmatr}
end
if rfind(key, "^futr") then
-- Add link to first word (form of 'to be')
local tobe, inf = rmatch(ruentry, "^([^ ]*) ([^ ]*)$")
if tobe then
-- No accelerators for imperfective future, as it's just the future of "to be"
-- plus the infinitive.
entry[i] = add_links(tobe, " " .. inf, runotes, trentry, trnotes, nil)
else
entry[i] = add_links(ruentry, "", runotes, trentry, trnotes, accel)
end
else
entry[i] = add_links(ruentry, "", runotes, trentry, trnotes, accel)
end
end
disp[key] = table.concat(entry, ",<br/>")
if disp[key] == "" then
disp[key] = "—"
end
end
local all_notes = {}
for _, note in ipairs(internal_notes) do
local symbol, entry = m_table_tools.get_initial_notes(note)
table.insert(all_notes, symbol .. entry)
end
for _, note in ipairs(notes) do
local symbol, entry = m_table_tools.get_initial_notes(note)
table.insert(all_notes, symbol .. entry)
end
local notes_text
table.insert(all_notes, 1,
"Note: For declension of participles, see their entries. Adverbial participles are indeclinable.")
notes_text = table.concat(all_notes, "<br />") .. "\n"
return [=[<div class="NavFrame" style="max-width:49.6em;">
<div class="NavHead" style="text-align:left; background:var(--wikt-palette-lightindigo, #e9e9ff);">]=] .. title .. [=[</div>
<div class="NavContent">
{| class="inflection inflection-ru inflection-verb inflection-table"
|+ ]=] .. notes_text .. [=[
|- class="rowgroup"
! colspan="3" | ]=] .. (perf and [=[[[совершенный вид|perfective aspect]]]=] or [=[[[несовершенный вид|imperfective aspect]]]=]) .. [=[
|-
! [[неопределённая форма|infinitive]]
| colspan="2" | ]=] .. disp.infinitive .. [=[
|- class="rowgroup"
! style="width:15em" | [[причастие|participles]]
! [[настоящее время|present tense]]
! [[прошедшее время|past tense]]
|-
! [[действительный залог|active]]
| ]=] .. disp.pres_actv_part .. [=[ || ]=] .. disp.past_actv_part .. [=[
|-
! [[страдательный залог|passive]]
| ]=] .. disp.pres_pasv_part .. [=[ || ]=] .. disp.past_pasv_part .. [=[
|-
! [[деепричастие|adverbial]]
| ]=] .. disp.pres_adv_part .. [=[ || ]=] .. disp.past_adv_part .. [=[
|- class="rowgroup"
!
! [[настоящее время|present tense]]
! [[будущее время|future tense]]
|-
! [[первое лицо|1st]] [[единственное число|singular]] (<span lang="ru" class="Cyrl">я</span>)
| ]=] .. disp.pres_1sg .. [=[ || ]=] .. disp.futr_1sg .. [=[
|-
! [[второе лицо|2nd]] [[единственное число|singular]] (<span lang="ru" class="Cyrl">ты</span>)
| ]=] .. disp.pres_2sg .. [=[ || ]=] .. disp.futr_2sg .. [=[
|-
! [[третье лицо|3rd]] [[единственное число|singular]] (<span lang="ru" class="Cyrl">он/она́/оно́</span>)
| ]=] .. disp.pres_3sg .. [=[ || ]=] .. disp.futr_3sg .. [=[
|-
! [[первое лицо|1st]] [[множественное число|plural]] (<span lang="ru" class="Cyrl">мы</span>)
| ]=] .. disp.pres_1pl .. [=[ || ]=] .. disp.futr_1pl .. [=[
|-
! [[второе лицо|2nd]] [[множественное число|plural]] (<span lang="ru" class="Cyrl">вы</span>)
| ]=] .. disp.pres_2pl .. [=[ || ]=] .. disp.futr_2pl .. [=[
|-
! [[третье лицо|3rd]] [[множественное число|plural]] (<span lang="ru" class="Cyrl">они́</span>)
| ]=] .. disp.pres_3pl .. [=[ || ]=] .. disp.futr_3pl .. [=[
|- class="rowgroup"
! [[повелительное наклонение|imperative]]
! [[единственное число|singular]]
! [[множественное число|plural]]
|-
! [[второе лицо|2nd]] (<span lang="ru" class="Cyrl">ты/вы</span>)
| ]=] .. disp.impr_sg .. [=[ || ]=] .. disp.impr_pl .. [=[
|- class="rowgroup"
! [[прошедшее время|past tense]]
! [[единственное число|singular]]
! [[множественное число|plural]]<br/>(<span lang="ru" class="Cyrl">мы/вы/они́</span>)
|-
! [[мужской род|masculine]] (<span lang="ru" class="Cyrl">я/ты/он</span>)
| ]=] .. disp.past_m .. [=[ || rowspan="3" | ]=] .. disp.past_pl .. [=[
|-
! [[женский род|feminine]] (<span lang="ru" class="Cyrl">я/ты/она́</span>)
| ]=] .. disp.past_f .. [=[
|-
! [[средний род|neuter]] (<span lang="ru" class="Cyrl">оно́</span>)
| ]=] .. disp.past_n .. [=[
|}
</div>
</div>]=]
end
return export
bd3o6mk40k4u7jwiwyfznuax009lqb8
Modül:User:Benwing2/ru-verb
828
1591007
5672500
2026-06-29T15:10:53Z
MustafaCavlak
59368
imported from en
5672500
Scribunto
text/plain
--[=[
This module contains functions for creating inflection tables for Russian
verbs.
Author: Benwing, rewritten from early version by Atitarev, earliest version by CodeCat
NOTE: This module is partly converted to support manual translit, in the
form CYRILLIC//LATIN (i.e. with a // separating the Cyrillic and Latin
parts). All the general infrastructure supports manual translit; the
only thing that doesn't is some of the specific verb conjugation functions.
In particular, all of the class 1, 2, 3 and 4 conjugation functions support
manual translit, and the rest don't. To convert another, follow the
model of one of the already-converted functions.
Note that an individual form (an entry in the 'forms' table) can be
either a string (no special manual translit; generally this originates
from the portion of the code that doesn't support manual translit), or
a one-element list {CYRILLIC} (no special manual translit), or a
two-element list {CYRILLIC, LATIN} with manual translit specified.
The code is careful only to generate manual translit when it's needed,
to avoid penalizing the majority of cases where manual transit isn't
needed.
]=]
local m_utilities = require("Module:utilities")
local ut = require("Module:utils")
local m_links = require("Module:links")
local com = require("Module:ru-common")
local nom = require("Module:ru-nominal")
local m_debug = require("Module:debug")
local m_table_tools = require("Module:table tools")
-- If enabled, compare this module with new version of module to make
-- sure all conjugations are the same.
local test_new_ru_verb_module = false
local export = {}
-- Within this module, conjugations are the functions that do the actual
-- conjugating by creating the forms of a basic verb.
-- They are defined further down.
local conjugations = {}
local lang = require("Module:languages").getByCode("ru")
local u = mw.ustring.char
local rfind = mw.ustring.find
local rsubn = mw.ustring.gsub
local rmatch = mw.ustring.match
local rsplit = mw.text.split
local usub = mw.ustring.sub
local AC = u(0x0301) -- acute = ́
local DIA = u(0x0308) -- diaeresis = ̈
local PSEUDOCONS = u(0xFFF2) -- pseudoconsonant placeholder, matching ru-common
local IRREG = "△"
-- version of rsubn() that discards all but the first return value
local function rsub(term, foo, bar)
local retval = rsubn(term, foo, bar)
return retval
end
-- version of rsubn() that returns a 2nd argument boolean indicating whether
-- a substitution was made.
local function rsubb(term, foo, bar)
local retval, nsubs = rsubn(term, foo, bar)
return retval, nsubs > 0
end
-- Fancy version of ine() (if-not-empty). Converts empty string to nil,
-- but also strips leading/trailing space and then single or double quotes,
-- to allow for embedded spaces.
local function ine(arg)
if not arg then return nil end
arg = rsub(arg, "^%s*(.-)%s*$", "%1")
if arg == "" then return nil end
local inside_quotes = rmatch(arg, '^"(.*)"$')
if inside_quotes then
return inside_quotes
end
inside_quotes = rmatch(arg, "^'(.*)'$")
if inside_quotes then
return inside_quotes
end
return arg
end
local function is_vowel_stem(stem)
return rfind(stem, "[" .. com.vowel .. AC .. DIA .. "]$")
end
-- Return the next number to use as an internal note symbol, starting at 1.
-- We look at existing internal notes to see if the symbol is already used.
local function next_note_symbol(data)
local nextsym = 1
while true do
local sym_already_seen = false
for _, note in ipairs(data.internal_notes) do
if rfind(note, "^" .. nextsym .. " ") then
sym_already_seen = true
break
end
end
if sym_already_seen then
nextsym = nextsym + 1
else
break
end
end
return nextsym
end
-- FIXME: Move to utils
-- Iterate over a chain of parameters, FIRST then PREF2, PREF3, ...,
-- inserting into LIST (newly created if omitted). Return LIST.
local function get_arg_chain(args, first, pref, list)
if not list then
list = {}
end
local val = args[first]
local i = 2
while val do
table.insert(list, val)
val = args[pref .. i]
i = i + 1
end
return list
end
-- FIXME: Move to utils
-- Set a chain of parameters, FIRST then PREF2, PREF3, ..., from LIST.
local function set_arg_chain(args, first, pref, list)
local param = first
local i = 2
for _, val in ipairs(list) do
args[param] = val
param = pref .. i
i = i + 1
end
end
-- For a given form in a conjugation table, we allow either strings or
-- two-element lists {RUSSIAN, TRANSLIT}, where TRANSLIT can be nil
-- (equivalent to a one-element list). When comparing them, we have to take
-- this into account.
local function forms_equal(form1, form2)
if type(form1) ~= "table" then
form1 = {form1}
end
if type(form2) ~= "table" then
form2 = {form2}
end
return ut.equals(form1, form2)
end
local function contains_form(forms, form)
for _, f in ipairs(forms) do
if forms_equal(f, form) then
return true
end
end
return false
end
-- FIXME: Move to utils
-- Append to the end of a chain of parameters, FIRST then PREF2, PREF3, ...,
-- if the value isn't already present.
local function append_to_arg_chain(args, first, pref, newval)
local nextarg = first
local i = 2
if newval == "" then
error("Internal error: attempt to insert blank value into arg chain")
end
while true do
if not args[nextarg] then break end
if forms_equal(args[nextarg], newval) then
return nil
end
nextarg = pref .. i
i = i + 1
end
args[nextarg] = newval
return nextarg
end
local function get_true_arg(arg, not_off_by_1)
-- We normally move all params down by one because the first param is the
-- verb type; so reflect this correctly if the arg is numeric and
-- not_off_by_1 isn't given
return (not_off_by_1 or type(arg) ~= "number") and arg or arg + 1
end
local function getarg(args, arg, default, paramdesc, not_off_by_1)
paramdesc = paramdesc or "Parameter " .. get_true_arg(arg, not_off_by_1)
default = default or "-"
--PAGENAME = mw.loadData("Module:headword/data").pagename
local NAMESPACE = mw.title.getCurrentTitle().nsText
return args[arg] or (NAMESPACE == "Template" and default) or error(paramdesc .. " has not been provided")
end
local function check_stressed_arg(val, arg)
-- don't consider suffixes
if not rfind(val, "^%-") and not com.is_nonsyllabic(val) and not com.is_stressed(val) then
error("Argument value " .. val .. " (parameter " .. get_true_arg(arg) .. ") must be stressed")
end
return val
end
local function get_stressed_arg(args, arg, default, paramdesc)
local retval = getarg(args, arg, default, paramdesc)
check_stressed_arg(retval, arg)
return retval
end
local function get_opt_stressed_arg(args, arg)
return args[arg] and get_stressed_arg(args, arg) or nil
end
local function check_unstressed_arg(val, arg)
if com.is_stressed(val) then
error("Argument value " .. val .. " (parameter " .. get_true_arg(arg) .. ") should not be stressed")
end
return val
end
local function get_unstressed_arg(args, arg, default, paramdesc)
local retval = getarg(args, arg, default, paramdesc)
check_unstressed_arg(retval, arg)
return retval
end
local function get_opt_unstressed_arg(args, arg)
return args[arg] and get_unstressed_arg(args, arg) or nil
end
local function no_stray_args(args, maxarg)
for i=(maxarg + 1), 20 do
if args[i] then
error("Value for argument " .. get_true_arg(i) .. " not allowed ("
.. args[i] .. " supplied)")
end
end
end
-- Extract a form spec (either a single string or a two-element table {RU, TR}
-- into the component Russian and transliterated components. Normally, if
-- an explicit manual translit wasn't given, the resulting translit will be
-- nil; but if ALWAYS_TRANSLIT is given, it will be auto-transliterated from
-- the Russian as needed.
local function extract_russian_tr(form, always_translit)
local ru, tr
if type(form) == "table" then
ru, tr = form[1], form[2]
else
ru = form
end
if not tr and always_translit then
tr = ru and com.translit(ru)
end
return ru, tr
end
local function strip_arg_status_prefix(arg)
if not arg then
return arg, ""
end
local subbed
arg, subbed = rsubb(arg, "^awkward%-", "")
if subbed then
return arg, "awkward-"
end
arg, subbed = rsubb(arg, "^none%-", "")
if subbed then
return arg, "none-"
end
return arg, ""
end
local function track(page)
m_debug.track("ru-verb/" .. page)
return true
end
-- Forward functions
local present_e_a
local present_e_b
local present_e_c
local present_je
local present_i
local make_reflexive
local make_pre_reform
local parse_and_stress_override
local handle_forms_and_overrides
local finish_generating_forms
local make_table
local all_verb_types = {
"pf", "pf-intr", "pf-refl",
"pf-impers", "pf-intr-impers", "pf-refl-impers",
"impf", "impf-intr", "impf-refl",
"impf-impers", "impf-intr-impers", "impf-refl-impers"}
-- Examples of alternatives in use:
-- past_m2: со́здал/созда́л, пе́редал/переда́л, о́тдал/отда́л, при́нялся/принялся́
-- past_m3: for verbs with three past masculine sg forms: за́нялся, заня́лся, занялс́я (заня́ться)
-- past_n2: да́ло, дал́о; вз́яло, взяло́
-- past_pl2: разобрали́сь (разобрали́)
-- past_m_short: short forms in 3a (исчез, сох, etc.)
-- past_f_short: short forms in 3a (исчезла, сохла, etc.)
-- past_n_short: short forms in 3a (исчезло, сохло, etc.)
-- past_pl_short: short forms in 3a (исчезли, сохли, etc.)
-- past_adv_parts:
-- тереть: тере́вши, тёрши, short: тере́в
-- умереть: умере́вши, у́мерши, short: умере́в
-- pres_adv_part: сыпля, сыпя, лёжа (лежать)
-- pres_2sg2: сыплешь, сыпешь
-- pres_3sg2: сыплет, сыпет
-- pres_1pl2: сыплем, сыпем
-- pres_2pl2: сыплете, сыпете
-- pres_3pl2: сыплют, сыпют
-- futr_2sg2: насыплешь, насыпешь
-- futr_3sg2: насыплет, насыпет
-- futr_1pl2: насыплем, насыпем
-- futr_2pl2: насыплете, насыпете
-- futr_3pl2: насыплют, насыпют
-- List of all main verb forms. Short forms (those ending in "_short")
-- must be listed after the corresponding non-short forms.
local all_main_verb_forms = {
-- present tense
"pres_1sg", "pres_2sg", "pres_3sg", "pres_1pl", "pres_2pl", "pres_3pl",
-- future tense
"futr_1sg", "futr_2sg", "futr_3sg", "futr_1pl", "futr_2pl", "futr_3pl",
-- present-future tense. The conjugation functions generate the
-- "present-future" tense instead of either the present or future tense,
-- since the same forms are used in the present imperfect and future
-- perfect. These forms are later copied into the present or future in
-- finish_generating_forms().
"pres_futr_1sg", "pres_futr_2sg", "pres_futr_3sg", "pres_futr_1pl", "pres_futr_2pl", "pres_futr_3pl",
-- imperative
"impr_sg", "impr_pl",
-- past
"past_m", "past_f", "past_n", "past_pl",
"past_m_short", "past_f_short", "past_n_short", "past_pl_short",
-- active participles
"pres_actv_part", "past_actv_part",
-- passive participles
"pres_pasv_part", "past_pasv_part",
-- adverbial participles
"pres_adv_part", "past_adv_part", "past_adv_part_short",
-- infinitive
"infinitive"
}
-- List of all verb forms. Each element is a list, where the first element
-- is the "main" form and the remainder are alternatives. The following
-- *MUST* hold:
-- 1. Forms must be given in the order they will appear in the outputted
-- table.
-- 2. Short forms (those ending in "_short") must be listed after the
-- corresponding non-short forms.
-- 3. For each person, e.g. '2sg', there must be the same number of
-- futr_PERSON, pres_PERSON and pres_futr_PERSON forms, and the alternative
-- forms must be listed in the same order.
--
-- FIXME!!! We should fix things so we no longer need to compute this table.
local all_verb_forms = {}
-- Compile all_verb_forms
for _, mainform in ipairs(all_main_verb_forms) do
local entry = {}
table.insert(entry, mainform)
for i=2,9 do
table.insert(entry, mainform .. i)
end
table.insert(all_verb_forms, entry)
end
local prop_aliases = {
pap="past_actv_part",
paptail="past_actv_part_tail",
paptailall="past_actv_part_tailall",
ppp="past_pasv_part",
ppptail="past_pasv_part_tail",
ppptailall="past_pasv_part_tailall",
prap="pres_actv_part",
praptail="pres_actv_part_tail",
praptailall="pres_actv_part_tailall",
prpp="pres_pasv_part",
prpptail="pres_pasv_part_tail",
prpptailall="pres_pasv_part_tailall",
padp="past_adv_part",
padptail="past_adv_part_tail",
padptailall="past_adv_part_tailall",
padp_short="past_adv_part_short",
padp_shorttail="past_adv_part_short_tail",
padp_shorttailall="past_adv_part_short_tailall",
pradp="pres_adv_part",
pradptail="pres_adv_part_tail",
pradptailall="pres_adv_part_tailall",
}
-- Table mapping "main" to the list of all forms in the series (e.g.
-- past_m, past_m2, past_m3, etc.). If a main form (e.g. past_m) is missing,
-- it needs to end up with a value of "", whereas the alternatives
-- (e.g. past_m2, past_m3) need to end up with a value of nil.
local main_to_all_verb_forms = {}
-- List of the main verb forms for the past.
local past_verb_forms = {"past_m", "past_f", "past_n", "past_pl"}
-- List of the main verb forms for the present.
local pres_verb_forms = {"pres_1sg", "pres_2sg", "pres_3sg",
"pres_1pl", "pres_2pl", "pres_3pl"}
-- List of the main verb forms for the future.
local futr_verb_forms = {"futr_1sg", "futr_2sg", "futr_3sg",
"futr_1pl", "futr_2pl", "futr_3pl"}
-- List of the main verb forms for the imperative.
local impr_verb_forms = {"impr_sg", "impr_pl"}
-- List of the main verb forms for participles.
local part_verb_forms = {"pres_actv_part", "past_actv_part",
"pres_pasv_part", "past_pasv_part",
"pres_adv_part", "past_adv_part", "past_adv_part_short"}
-- List of the main verb forms for present participles.
local pres_part_verb_forms = {"pres_actv_part", "pres_pasv_part",
"pres_adv_part"}
-- List of the main verb forms for past participles.
local past_part_verb_forms = {"past_actv_part", "past_pasv_part",
"past_adv_part", "past_adv_part_short"}
-- Compile main_to_all_verb_forms.
for _, proplist in ipairs(all_verb_forms) do
main_to_all_verb_forms[proplist[1]] = proplist
end
-- Map listing the forms to be displayed, and the verb forms used to generate
-- the displayed form, in order. For example, under past_m will be found
-- {"past_m_short", "past_m", "past_m2", "past_m3"} because those forms in
-- that order are displayed in the table under "masculine singular past".
local disp_verb_form_map = {}
for _, proplist in ipairs(all_verb_forms) do
local key = proplist[1]
-- if we find short forms, insert them at the beginning of the list for
-- the corresponding full forms. This requires that short forms are
-- listed in all_verb_forms after the corresponding full forms.
if rfind(key, "_short$") then
local full_key = rsub(key, "_short$", "")
-- short forms should occur in list after full forms
assert(#(disp_verb_form_map[full_key]) > 0)
-- build entry for full form, consisting first of the short forms,
-- in order, then the full forms, in order.
local new_entry = {}
for _, form in ipairs(proplist) do
table.insert(new_entry, form)
end
for _, form in ipairs(disp_verb_form_map[full_key]) do
table.insert(new_entry, form)
end
disp_verb_form_map[full_key] = new_entry
elseif rfind(key, "^pres_futr") then
-- skip these forms, not displayed
else
disp_verb_form_map[key] = mw.clone(proplist)
end
end
local all_verb_props = mw.clone(all_verb_forms)
local non_form_props = {"title", "perf", "intr", "impers", "categories", "notes", "internal_notes"}
for _, prop in ipairs(non_form_props) do
table.insert(all_verb_props, {prop})
end
-- Clone parent's args while also assigning nil to empty strings and splitting
-- arg sets (numeric args separated by "or"), assigning named args to
-- all all sets. Handle aliases in the process. Extract conjugation type
-- from the first arg of the arg set (for the initial arg set, this will be
-- arg 2 because arg 1 is the verb type), assigning to '.conj_type' of the
-- arg set. Return arg sets.
local function split_args_handle_aliases(frame)
local args = frame:getParent().args
local arg_sets = {}
local arg_set = {}
-- Verb type, e.g. impf, pf, impf-intr, pf-intr, impf-refl, pf-refl, etc.
-- Default to impf on the template page so that there is no script error.
local verb_type = getarg(args, 1, "impf", "Verb type (first parameter)")
local offset = 1
-- Find maximum-numbered arg, allowing for holes.
local max_arg = 1 -- needs to be 1 not 0 so template pages display ok
for pname, param in pairs(args) do
if type(pname) == "number" and pname > max_arg then
max_arg = pname
end
end
-- Now gather the numbered arguments.
for i=2,(max_arg + 1) do
local end_arg_set = false
if i == max_arg + 1 or args[i] == "or" then
end_arg_set = true
end
if end_arg_set then
table.insert(arg_sets, arg_set)
arg_set = {}
offset = i
else
arg_set[i - offset] = ine(args[i])
end
end
-- Insert named arguments into all arg sets, mapping aliases appropriately.
for pname, param in pairs(args) do
if type(pname) == "string" then
local argval = ine(param)
local mainprop, num = rmatch(pname, "^([a-z_]+)([0-9]*)$")
for i=1,#arg_sets do
if not mainprop then
arg_sets[i][pname] = argval
else
mainprop = prop_aliases[mainprop] or mainprop
arg_sets[i][mainprop .. num] = argval
end
end
end
end
-- If we're conjugating a suffix, insert a pseudoconsonant at the beginning
-- of all forms, so they get conjugated as if ending in a consonant.
-- We remove the pseudoconsonant later.
for i=1,#arg_sets do
asif_prefix = (arg_sets[i]["asif_prefix"] or
arg_sets[i][2] and rfind(arg_sets[i][2], "^%-") and PSEUDOCONS)
if asif_prefix then
for k, v in pairs(arg_sets[i]) do
arg_sets[i][k] = rsub(v, "^%-", "-" .. asif_prefix)
end
end
end
-- Frob conjugation type.
for i=1,#arg_sets do
local arg1 = arg_sets[i][1]
local conj_type
if arg1 then
local orig_arg1 = arg1
-- This complex spec matches matches 3°a, 3oa, 4a1a, 6c1a,
-- 1a6a, 6a1as13, 6a1as14, 11*b, etc.
conj_type = rmatch(arg1, "^([0-9]+[*°o0-9abc]*[abc]s?1?[34]?)")
arg1 = rsub(arg1, "^[0-9]+[*°o0-9abc]*[abc]s?1?[34]?", "")
if not conj_type then
if rfind(arg1, "^irreg") then
conj_type = "irreg"
arg1 = rsub(arg1, "^irreg", "")
end
if not conj_type then
-- Check for Cyrillic, a common mistake (esp. Cyrillic а)
if rfind(orig_arg1, "[абцдеѣфгчийклмнопярстувшхызёюжэщьъ]") then
error("Unrecognized conjugation type (WARNING, has Cyrillic in it): " .. orig_arg1)
else
error("Unrecognized conjugation type: " .. orig_arg1)
end
end
end
-- The * variant is conventionally written e.g. 11*b; if found in
-- the conj_type, move it to the beginning of the remainder
if rfind(conj_type, "%*") then
conj_type = rsub(conj_type, "%*", "")
arg1 = "*" .. arg1
end
arg_sets[i][1] = arg1
else
local NAMESPACE = mw.title.getCurrentTitle().nsText
if NAMESPACE == "Template" and i == 1 then
conj_type = "1a"
else
error("Must specify argument 2 (conjugation type)")
end
end
arg_sets[i]["conj_type"] = conj_type
end
return arg_sets, verb_type
end
function export.do_generate_forms(arg_sets, verb_type, old)
local set1 = arg_sets[1]
local notes = get_arg_chain(set1, "notes", "notes")
local forms = {}
local categories = {}
if not ut.contains(all_verb_types, verb_type) then
error("Invalid verb type " .. verb_type)
end
local data = {}
data.verb_type = verb_type
--impersonal
data.impers = rfind(verb_type, "impers")
data.intr = rfind(verb_type, "intr")
data.perf = rfind(verb_type, "^pf")
data.iter = set1["iter"]
data.nopres = set1["nopres"]
data.nopast = set1["nopast"]
data.nofutr = set1["nofutr"]
data.noimpr = set1["noimpr"]
if data.iter and data.perf then
error("Iterative verbs must be imperfective")
end
data.old = old
data.has_ppp = set1["has_ppp"]
data.has_prpp = set1["has_prpp"]
data.ppp_override = false
data.prpp_override = false
for _, form in ipairs(main_to_all_verb_forms["past_pasv_part"]) do
if set1[form] then
data.ppp_override = true
break
end
end
data.main_ppp_override = not not set1["past_pasv_part"]
for _, form in ipairs(main_to_all_verb_forms["pres_pasv_part"]) do
if set1[form] then
data.prpp_override = true
break
end
end
data.internal_notes = {}
local titles = {}
for i=1,#arg_sets do
local args = arg_sets[i]
local conj_type = args.conj_type
-- Support e.g. 3oa in place of 3°a
conj_type = rsub(conj_type, "o", "°")
track("conj-" .. conj_type) -- FIXME, convert to regular category
track("conj-" .. conj_type .. "/" .. verb_type) -- FIXME, convert to regular category
data.conj_type = conj_type
data.cat_conj_types = {conj_type}
if conj_type == "irreg" then
data.title = "irregular"
else
data.title = conj_type
end
if not conjugations[conj_type] then
error("Unknown conjugation type '" .. conj_type .. "'")
end
if args[2] then
local inf, tr = nom.split_russian_tr(args[2])
if rfind(inf, "[тч]ься$") then
inf = rsub(inf, "ся$", "")
tr = nom.strip_tr_ending(tr, "ся")
data.refl = true
elseif rfind(inf, "ти́?сь$") then
-- 7a (вы́вестись), 7b (вести́сь) or derivative of -йти́ (разойти́сь)
inf = rsub(inf, "сь$", "")
tr = nom.strip_tr_ending(tr, "сь")
data.refl = true
elseif rfind(inf, "[тч]ь$") then
-- Allow monosyllabic infinitives to be specified without stress
if com.is_monosyllabic(inf) and not rfind(inf, "^%-") then
inf, tr = com.make_ending_stressed(inf, tr)
end
end
if tr then
args[2] = inf .. "//" .. tr
else
args[2] = inf
end
end
if data.refl and data.intr then
error("Can't specify -intr with reflexive verbs")
end
if data.has_ppp or data.has_prpp then
if data.refl then
error("Can't specify has_ppp=y or has_prpp=y with reflexive verbs")
end
if not data.intr then
error("Can only specify has_ppp=y or has_prpp=y with intransitive verbs")
end
end
data.shouldnt_have_ppp = data.refl or not data.has_ppp and data.intr
data.shouldnt_have_prpp = data.refl or not data.has_prpp and data.intr
if data.ppp_override and data.shouldnt_have_ppp then
error("Shouldn't specify past passive participle with reflexive or intransitive verbs, if it's needed use has_ppp=y")
elseif data.perf and not data.shouldnt_have_ppp and not data.ppp_override then
-- possible omissions
track("perfective-no-ppp")
end
if data.prpp_override and data.shouldnt_have_prpp then
error("Shouldn't specify present passive participle with reflexive or intransitive verbs, if it's needed use has_prpp=y")
end
-- Call conjugation function. It will return a table of forms
-- as if it's the first arg set. If it is in fact the first
-- arg set, we just use the table directly (we may destructively
-- modify it if there are later arg sets, but this is OK because
-- no one else but us uses the table). Otherwise we need to
-- append the values from the table to those of the previous
-- arg sets.
local arg_set_forms = conjugations[conj_type](args, data)
if i == 1 then
forms = arg_set_forms
else
for _, all_forms in pairs(main_to_all_verb_forms) do
for _, form in ipairs(all_forms) do
if arg_set_forms[form] then
append_to_arg_chain(forms, all_forms[1], all_forms[1],
arg_set_forms[form])
end
end
end
end
ut.insert_if_not(titles, data.title)
if conj_type == "irreg" then
table.insert(categories, "Russian irregular verbs")
end
-- For irregular verbs, if the verb didn't set a specific cat_conj_type,
-- it will be the same as the conj_type and be "irreg". In that case,
-- replace it with the title, which might be a proper conjugation type
-- like 4a or 8c/b (and remove anything starting with a slash, to
-- account for cases like 8c/b). After doing this, the cat_conj_type
-- might still begin with "irreg" (for sufficiently irregular verbs that
-- they can't be assigned to any of the normal classes), in which case
-- we don't create a class for the verb beyond "Russian irregular verbs"
-- (set above).
if data.cat_conj_types[1] == "irreg" then
data.cat_conj_types = {rsub(rsub(data.title, "/.*", ""), "⑨", "")}
end
for _, cat_conj_type in ipairs(data.cat_conj_types) do
if not rmatch(cat_conj_type, "^irreg") then
local class_num = rmatch(cat_conj_type, "^([0-9]+)")
assert(class_num and class_num ~= "")
table.insert(categories, "Russian class " .. class_num .. " verbs")
table.insert(categories, "Russian class " .. cat_conj_type .. " verbs")
end
end
end
data.title = "class " .. table.concat(titles, " // ") ..
(data.perf and " perfective" or " imperfective") ..
(data.refl and " reflexive" or data.intr and " intransitive" or " transitive") ..
(data.impers and " impersonal" or "") ..
(data.iter and " iterative" or "")
-- Perfective/imperfective
if data.perf then
table.insert(categories, "Russian perfective verbs")
else
table.insert(categories, "Russian imperfective verbs")
end
handle_forms_and_overrides(set1, forms, data)
local function remove_pseudo(str)
toremove = set1["asif_prefix"] or PSEUDOCONS
if str == nil then
return str
end
str = rsub(str, "^%-" .. toremove, "-")
-- also handle prefix after space, e.g. in futures
str = rsub(str, " %-" .. toremove, " -")
return str
end
-- Remove pseudoconsonant we may have inserted; if no ending, insert
-- "(no suffix)".
for k, v in pairs(forms) do
if forms[k] == "-" .. PSEUDOCONS or type(forms[k] == "table") and forms[k][1] == "-" .. PSEUDOCONS then
-- Make the translit empty.
forms[k] = {"(no suffix)", ""}
else
if type(forms[k]) == "table" then
forms[k][1] = remove_pseudo(forms[k][1])
forms[k][2] = remove_pseudo(forms[k][2])
else
forms[k] = remove_pseudo(forms[k])
end
end
end
-- Catch errors in verb arguments that lead to the infinitive not matching
-- page title, but only in the main namespace.
local NAMESPACE = mw.title.getCurrentTitle().nsText
if NAMESPACE == "" then
local PAGENAME = mw.loadData("Module:headword/data").pagename
for _, form in ipairs(main_to_all_verb_forms["infinitive"]) do
local inf, inf_tr = extract_russian_tr(forms[form])
if inf then
inf, _ = m_table_tools.separate_notes(inf) -- remove any footnote symbols (e.g. грясти́)
local inf_noaccent = com.remove_accents(inf)
if inf ~= "-" then
if data.refl then
if rfind(inf_noaccent, "и$") then
inf_noaccent = inf_noaccent .. "сь"
inf = inf .. "сь"
else
inf_noaccent = inf_noaccent .. "ся"
inf = inf .. "ся"
end
end
if inf_noaccent ~= PAGENAME then
error("Infinitive " .. inf .. " doesn't match pagename " ..
PAGENAME)
end
end
end
end
end
-- Reflexive/intransitive/transitive
if set1["reflex_stress"] then
track("reflex-stress")
end
if data.refl then
local reflex_stress = set1["reflex_stress"] or data.default_reflex_stress -- "ся́"
make_reflexive(forms, reflex_stress and reflex_stress ~= "n" and
reflex_stress ~= "no")
table.insert(categories, "Russian reflexive verbs")
elseif data.intr then
table.insert(categories, "Russian intransitive verbs")
else
table.insert(categories, "Russian transitive verbs")
end
-- Impersonal
if data.impers then
table.insert(categories, "Russian impersonal verbs")
end
-- Iterative
if data.iter then
table.insert(categories, "Russian iterative verbs")
end
if data.old then
make_pre_reform(forms)
end
finish_generating_forms(forms, data)
return forms, data.title, data.perf, data.intr or data.refl, data.impers, categories, notes, data.internal_notes
end
local function fetch_forms(forms)
local function fetch_one_form(form)
local val = forms[form]
local ru, tr
if type(val) == "table" then
ru, tr = val[1], val[2]
elseif type(val) == "string" and val ~= "" and val ~= "-" then
ru = val
end
if not ru then
return nil
end
local ruentry, runotes = m_table_tools.get_notes(ru)
local trentry, trnotes
if tr then
trentry, trnotes = m_table_tools.get_notes(tr)
end
-- There shouldn't be any links.
-- ruentry = m_links.remove_links(ruentry)
-- There shouldn't be any vertical bars.
-- ruentry = rsub(ruentry, "|", "<!>")
-- if trentry then
-- trentry = rsub(trentry, "|", "<!>")
-- end
return trentry and ruentry .. "//" .. trentry or ruentry
end
local vals = {}
for _, proplist in ipairs(all_verb_forms) do
local vallist = {}
local propname = proplist[1]
if not rfind(propname, "^pres_futr") then
for _, prop in ipairs(proplist) do
local val = fetch_one_form(prop)
if val then
table.insert(vallist, val)
end
end
if #vallist > 0 then
table.insert(vals, propname .. "=" .. table.concat(vallist, ","))
end
end
end
return table.concat(vals, "|")
end
function export.generate_forms(frame)
local arg_sets, verb_type = split_args_handle_aliases(frame)
local old = frame.args["old"] or arg_sets[1]["old"]
local forms, title, perf, intr, impers, categories, notes, internal_notes = export.do_generate_forms(arg_sets, verb_type, old)
return fetch_forms(forms)
end
local function concat_vals(val)
if type(val) == "table" then
return table.concat(val, ",")
else
return val
end
end
-- The main entry point.
-- This is the only function that can be invoked from a template.
function export.show(frame)
local arg_sets, verb_type = split_args_handle_aliases(frame)
local old = frame.args["old"] or arg_sets[1]["old"]
local arg_sets_clone
if test_new_ru_verb_module then
-- arg_sets may be modified by do_generate_forms()
arg_sets_clone = mw.clone(arg_sets)
end
local forms, title, perf, intr, impers, categories, notes, internal_notes =
export.do_generate_forms(arg_sets, verb_type, old)
-- Test code to compare existing module to new one.
if test_new_ru_verb_module then
local m_new_ru_verb = require("Module:User:Benwing2/ru-verb")
local newforms, newtitle, newperf, newintr, newimpers, newcategories, newnotes, newinternal_notes =
m_new_ru_verb.do_generate_forms(arg_sets_clone, verb_type, old)
local vals = mw.clone(forms)
vals.title = title
vals.perf = perf
vals.intr = intr
vals.impers = impers
vals.categories = categories
vals.notes = notes
vals.internal_notes = internal_notes
local newvals = mw.clone(newforms)
newvals.title = newtitle
newvals.perf = newperf
newvals.intr = newintr
newvals.impers = newimpers
newvals.categories = newcategories
newvals.notes = newnotes
newvals.internal_notes = newinternal_notes
local difconj = false
for _, proplist in ipairs(all_verb_props) do
for _, prop in ipairs(proplist) do
local val = vals[prop]
local newval = newvals[prop]
-- deal with impedance mismatch between old style (plain string)
-- and new style (Russian/translit array), and empty string vs. nil
if not ut.contains(non_form_props, prop) then
if type(val) == "string" then val = {val} end
if val and val[1] == "" then val = nil end
if type(newval) == "string" then newval = {newval} end
if newval and newval[1] == "" then newval = nil end
end
-- Ignore changes in pres_futr_*, which aren't displayed
if not forms_equal(val, newval) and not rfind(prop, "^pres_futr") then
-- Uncomment this to display the particular case and
-- differing forms.
--error(prop .. " " .. (val and concat_vals(val) or "nil") .. " || " .. (newval and concat_vals(newval) or "nil"))
difconj = true
break
end
end
end
track(difconj and "different-conj" or "same-conj")
end
return make_table(forms, title, perf, intr, impers, notes, internal_notes, old) .. m_utilities.format_categories(categories, lang)
end
-- Implementation of template 'ru-verb cat'.
function export.catboiler(frame)
local SUBPAGENAME = mw.loadData("Module:headword/data").pagename
local cats = {}
local cls, variant, pattern = rmatch(SUBPAGENAME, "^Russian class ([0-9]*)(°?)([abc]?) verbs")
local text = nil
if not cls then
error("Invalid category name, should be e.g. \"Russian class 3a verbs\"")
end
if pattern == "" then
table.insert(cats, "Russian verbs by class|" .. cls .. variant)
text = "This category contains Russian class " .. cls .. " verbs."
else
table.insert(cats, "Russian verbs by class and accent pattern|" .. cls .. pattern)
table.insert(cats, "Russian class " .. cls .. " verbs|" .. pattern)
text = "This category contains Russian class " .. cls .. " verbs of " ..
"accent pattern " .. pattern .. (
variant == "" and "" or " and variant " .. variant) .. ". " .. (
pattern == "a" and "With this pattern, all forms are stem-stressed."
or pattern == "b" and "With this pattern, all forms are ending-stressed."
or "With this pattern, the first singular present indicative and all forms " ..
"outside of the present indicative are ending-stressed, while the remaining " ..
"forms of the present indicative are stem-stressed.").. (
variant == "" and "" or
cls == "3" and " The variant code indicates that the -н of the stem " ..
"is missing in most non-present-tense forms." or
" The variant code indicates that the present tense is not " ..
"[[Appendix:Glossary#iotation|iotated]]. (In most verbs of this class, " ..
"the present tense is iotated, e.g. иска́ть with present tense " ..
"ищу́, и́щешь, и́щет, etc.)")
end
return text .. "\n" ..
mw.getCurrentFrame():expandTemplate{title="ru-categoryTOC", args={}}
.. m_utilities.format_categories(cats, lang, nil, nil, "force")
end
-- Implementation of poscatboiler handler for Russian verb cats. Loaded from
-- [[Module:category tree/poscatboiler/data/lang-specific]].
function export.poscatboiler_verb_class_handler(cls, variant, pattern)
if pattern == "" then
return {
description = "Russian class " .. cls .. " verbs.",
breadcrumb = cls,
parents = {{name = "verbs by class", sort = cls .. variant}},
}
else
return {
description = "Russian class " .. cls .. " verbs of " ..
"accent pattern " .. pattern .. (
variant == "" and "" or " and variant " .. variant) .. ". " .. (
pattern == "a" and "With this pattern, all forms are stem-stressed."
or pattern == "b" and "With this pattern, all forms are ending-stressed."
or "With this pattern, the first singular present indicative and all forms " ..
"outside of the present indicative are ending-stressed, while the remaining " ..
"forms of the present indicative are stem-stressed.") .. (
variant == "" and "" or
cls == "3" and " The variant code indicates that the -н of the stem " ..
"is missing in most non-present-tense forms." or
" The variant code indicates that the present tense is not " ..
"[[Appendix:Glossary#iotation|iotated]]. (In most verbs of this class, " ..
"the present tense is iotated, e.g. иска́ть with present tense " ..
"ищу́, и́щешь, и́щет, etc.)"),
breadcrumb = cls .. variant .. pattern,
parents = {
{name = "class " .. cls .. " verbs", sort = pattern},
{name = "verbs by class and accent pattern", sort = cls .. pattern},
},
}
end
end
--[=[
Functions for working with stems, paradigms, Russian/translit
]=]
-- Combine a stem with optional translit with an ending and possibly a foonote
-- symbol (which may be a tuple {RUNOTES, TRNOTES}), returning a tuple
-- {RUSSIAN, TR}.
local function combine(stem, tr, ending, note)
if not ending or ending == "-" then
return nil
end
local arg_status
ending, arg_status = strip_arg_status_prefix(ending)
if stem ~= "" and com.is_stressed(ending) then
stem, tr = com.make_unstressed_once(stem, tr)
end
stem = arg_status .. stem
if not note then
return nom.concat_russian_tr(stem, tr, ending, nil, "dopair")
else
local runotes, trnotes = extract_russian_tr(note)
local ruending, trending = nom.concat_russian_tr(ending, nil, runotes, trnotes)
return nom.concat_russian_tr(stem, tr, ruending, trending, "dopair")
end
end
-- Set an individual form PARAM in FORMS with value based on stem STEM (with
-- optional translit TR), ENDINGS (either a single string or a list of strings)
-- and NOTE (nil, a string, or a tuple {RUSSIAN, TR}). If there are multiple
-- endings listed, they will go successively into PARAM, PARAM2, etc.
-- (e.g. past_m, past_m2, etc.).
local function set_form(forms, param, stem, tr, endings, note)
if type(endings) ~= "table" then
endings = {endings}
end
local entries = {}
for _, val in ipairs(endings) do
ut.insert_if_not(entries, combine(stem, tr, val, note))
end
set_arg_chain(forms, param, param, entries)
end
-- Append to an individual form PARAM in FORMS with value based on stem STEM
-- (with optional translit TR), ENDINGS (either a single string or a list of
-- strings) and NOTE (nil, a string, or a tuple {RUSSIAN, TR}). If there are
-- multiple endings listed, they will go successively into PARAM, PARAM2, etc.
-- (e.g. past_m, past_m2, etc.), provided there are no existing forms already
-- present. Duplicate forms aren't inserted.
local function append_form(forms, param, stem, tr, endings, note)
if type(endings) ~= "table" then
endings = {endings}
end
for _, val in ipairs(endings) do
append_to_arg_chain(forms, param, param, combine(stem, tr, val, note))
end
end
local function append_pres_futr(forms, stem, tr,
sg1, sg2, sg3, pl1, pl2, pl3, note)
append_form(forms, "pres_futr_1sg", stem, tr, sg1, note)
append_form(forms, "pres_futr_2sg", stem, tr, sg2, note)
append_form(forms, "pres_futr_3sg", stem, tr, sg3, note)
append_form(forms, "pres_futr_1pl", stem, tr, pl1, note)
append_form(forms, "pres_futr_2pl", stem, tr, pl2, note)
append_form(forms, "pres_futr_3pl", stem, tr, pl3, note)
end
local function append_participles_2stem(forms,
pres_stem, pres_tr, past_stem, past_tr,
pres_actv, pres_pasv, pres_adv, past_actv, past_adv, past_adv_short,
pres_note, past_note)
append_form(forms, "pres_actv_part", pres_stem, pres_tr, pres_actv, pres_note)
append_form(forms, "pres_pasv_part", pres_stem, pres_tr, pres_pasv, pres_note)
append_form(forms, "pres_adv_part", pres_stem, pres_tr, pres_adv, pres_note)
append_form(forms, "past_actv_part", past_stem, past_tr, past_actv, past_note)
append_form(forms, "past_adv_part", past_stem, past_tr, past_adv, past_note)
append_form(forms, "past_adv_part_short", past_stem, past_tr, past_adv_short, past_note)
end
local function append_participles(forms, stem, tr,
pres_actv, pres_pasv, pres_adv, past_actv, past_adv, past_adv_short, note)
append_participles_2stem(forms, stem, tr, stem, tr,
pres_actv, pres_pasv, pres_adv, past_actv, past_adv, past_adv_short, note, note)
end
local function set_ppp(forms, stem, tr, ending, note)
set_form(forms, "past_pasv_part", stem, tr, ending, note)
end
local function append_ppp(forms, stem, tr, ending, note)
append_form(forms, "past_pasv_part", stem, tr, ending, note)
end
local function append_imper(forms, stem, tr, sg, pl, note)
append_form(forms, "impr_sg", stem, tr, sg, note)
append_form(forms, "impr_pl", stem, tr, pl, note)
end
local function set_past(forms, stem, tr, m, f, n, pl, note)
set_form(forms, "past_m", stem, tr, m, note)
set_form(forms, "past_f", stem, tr, f, note)
set_form(forms, "past_n", stem, tr, n, note)
set_form(forms, "past_pl", stem, tr, pl, note)
end
local function append_past(forms, stem, tr, m, f, n, pl, note)
append_form(forms, "past_m", stem, tr, m, note)
append_form(forms, "past_f", stem, tr, f, note)
append_form(forms, "past_n", stem, tr, n, note)
append_form(forms, "past_pl", stem, tr, pl, note)
end
-- Prepend a possibly-stressed prefix to all forms; if prefix is stressed,
-- destress the forms before prepending. FIXME: Should support explicit
-- manual translit.
local function prepend_prefix(forms, prefix, pre_two_cons_prefix)
pre_two_cons_prefix = pre_two_cons_prefix or prefix
local stressed_prefix = com.is_stressed(prefix)
for key, form in pairs(forms) do
local ru, tr = extract_russian_tr(form)
if tr then
error("Explicit manual translit not yet supported")
end
-- check for empty string, dashes and nil's
if ru and ru ~= "" and ru ~= "-" then
if stressed_prefix then
ru = com.make_unstressed(ru)
end
if rfind(ru, "^[" .. com.cons .. "][" .. com.cons .. "]") then
forms[key] = pre_two_cons_prefix .. ru
else
forms[key] = prefix .. ru
end
end
end
end
-- Apply regex substitution FROM -> TO to all forms. FIXME: Should support
-- explicit manual translit.
local function rsub_forms(forms, from, to)
for key, form in pairs(forms) do
local ru, tr = extract_russian_tr(form)
if tr then
error("Explicit manual translit not yet supported")
end
-- check for empty string, dashes and nil's
if ru and ru ~= "" and ru ~= "-" then
forms[key] = rsub(ru, from, to)
end
end
end
local variant_to_title = {
["[(2)]"] = "[②]",
["(2)"] = "②",
["[(3)]"] = "[③]",
["(3)"] = "③",
["[(4)]"] = "[④]",
["(4)"] = "④",
["[(5)]"] = "[⑤]",
["(5)"] = "⑤",
["[(6)]"] = "[⑥]",
["(6)"] = "⑥",
["[(7)]"] = "[⑦]",
["(7)"] = "⑦",
["[(8)]"] = "[⑧]",
["(8)"] = "⑧",
["(9)"] = "⑨",
["щ"] = "(-щ-)",
["ё"] = "(-ё-)",
["о"] = "(-о-)",
["жд"] = "(-жд-)",
}
local function prepare_past_stress_indicator(past_stress)
if not past_stress or past_stress == "a" then
return ""
end
past_stress = rsub(past_stress, "%(1%)", "①")
past_stress = rsub(past_stress, "(.),%1①", "%1[①]")
past_stress = rsub(past_stress, "(.)①,%1", "%1[①]")
past_stress = rsub(past_stress, "''", "''")
past_stress = rsub(past_stress, "-nd", "")
past_stress = rsub(past_stress, "-bd", "")
return "/" .. past_stress
end
local function parse_variants(data, variants, allowed)
-- Need to set these to nil in case of multiple arg sets
data.imper_variant = nil
data.var4 = nil
data.var5 = nil
data.var6 = nil
data.ppp = nil
data.var9 = nil
data.shch = nil
data.yo = nil
data.o = nil
data.zhd = nil
data.star = nil
variants = variants or ""
local variant_title = ""
if variants ~= "" then -- short-circuit the most common case
-- Only recognize * variant for long-variant prefix at the beginning
-- of the variant code block (where it gets moved if it's in the
-- middle of the conjugation type, as it normally is) because a *
-- also occurs in b*, a past stress variant code.
if rfind(variants, "^%*") then
-- Specify that the present/future tense has extra -о in the prefix:
-- types 9*b (e.g. растере́ть, futr_1sg разотру́) and 11*b (e.g. изли́ть,
-- futr_1sg изолью́). It can also occur with type 7*b (in -че́сть,
-- e.g. счесть, сочту́; расче́сть, разочту́) and type 8*b (in -же́чь, e.g.
-- сжечь, сожгу́) but these are always irregular and require the
-- present tense to be specified explicitly. It can also occur
-- with type 14*b (e.g. размя́ть, разомну́; сжать, сожну́; подожа́ть, подожму́),
-- but for these verbs the present tense is unpredictable and
-- must be specified explicitly.
--
-- This can also occur where the extra -о occurs in the infinitive
-- and past, but not the present tense: type 5*c (in -гна́ть, e.g.
-- согна́ть, сгоню́; разогна́ться, разгоню́сь), type 6*c (in -стла́ть, e.g.
-- подостла́ть, подстелю́; разостла́ть, расстелю́), type 6°*c
-- (in -зва́ть, -бра́ть, -дра́ть, e.g. подозва́ть, подзову́; разобра́ться, разберу́сь);
-- but these are always irregular and require the present tense
-- to be specified explicitly.
if not ut.contains(allowed, "*") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.star = true
variants = rsub(variants, "^*", "")
end
-- Allow brackets around both 5 and 6, e.g. [(5)(6)]
variants = rsub(variants, "%[(%([56]%))(%([56]%))%]", "[%1][%2]")
-- Handle all remaining variants. We do this using an rsub() function,
-- where we pull out, parse and remove each variant in turn.
variants = rsub(variants, "(%[?%(?[23456789ёощийьж+][дp]?%)?%]?)", function(var)
if ut.contains({"(2)", "[(2)]", "(3)", "[(3)]", "и", "й", "ь"}, var) then
if data.imper_variant then
error("Saw two imperative variants " .. data.imper_variant ..
" and " .. var)
end
local is_23 = ut.contains({"(2)", "[(2)]", "(3)", "[(3)]"}, var)
if is_23 and not ut.contains(allowed, "23") or
not is_23 and not ut.contains(allowed, "и") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.imper_variant = var
elseif ut.contains({"(4)", "[(4)]"}, var) then
if data.var4 then
error("Saw two variant-4 specs " .. data.var4 .. " and " .. var)
end
if not ut.contains(allowed, "4") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.var4 = var == "(4)" and "req" or "opt"
elseif ut.contains({"(5)", "[(5)]"}, var) then
if data.var5 then
error("Saw two variant-5 specs " .. data.var5 .. " and " .. var)
end
if not ut.contains(allowed, "5") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.var5 = var == "(5)" and "req" or "opt"
elseif ut.contains({"(6)", "[(6)]"}, var) then
if data.var6 then
error("Saw two variant-6 specs " .. data.var6 .. " and " .. var)
end
if not ut.contains(allowed, "6") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.var6 = var == "(6)" and "req" or "opt"
elseif ut.contains({"(7)", "[(7)]", "(8)", "[(8)]", "+p"}, var) then
if data.shouldnt_have_ppp then
error("Shouldn't specify past passive participle with reflexive or intransitive verbs, if it's needed use has_ppp=y")
end
if data.ppp then
error("Saw two past passive participle specs " .. data.ppp .. " and " .. var)
end
if ut.contains({"(7)", "[(7)]"}, var) and not ut.contains(allowed, "7") or
ut.contains({"(8)", "[(8)]"}, var) and not ut.contains(allowed, "8") or
var == "+p" and not ut.contains(allowed, "+p") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.ppp = var
elseif var == "(9)" then
if data.var9 then
error("Saw (9) twice")
end
if not ut.contains(allowed, "9") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.var9 = true
elseif var == "щ" then
-- specify that the 1sg pres/futr and past passive participle
-- of class 4/5/6 verbs iotate -т to -щ instead of -ч; cf.
-- похи́тить (похи́щу) (4a), защити́ть (защищу́) (4b),
-- поглоти́ть (поглощу́) (4c), клевета́ть (клевещу́) (6c)
if data.shch then
error("Saw щ twice")
end
if not ut.contains(allowed, "щ") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.shch = "щ"
elseif var == "ё" then
-- specify that the past passive participle has ё instead of е
if data.yo then
error("Saw ё twice")
end
if not ut.contains(allowed, "ё") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.yo = true
elseif var == "о" then
-- specify that the past passive participle has о instead of е
-- NOTE: Not currently allowed as a user-specifiable variant
if data.o then
error("Saw о twice")
end
if not ut.contains(allowed, "о") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.o = true
elseif var == "жд" then
-- specify that the past passive participle of class 4/5/6 verbs
-- iotates -д to -жд instead of -ж
if data.zhd then
error("Saw жд twice")
end
if not ut.contains(allowed, "жд") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.zhd = true
else
error("Unrecognized variant spec: " .. var)
end
variant_title = variant_title .. (variant_to_title[var] or "")
return ""
end)
variant_title = rsub(variant_title, "%[⑤%]%[⑥%]", "[⑤⑥]")
end
if variants ~= "" and not ut.contains(allowed, "past") then
error("Past stress " .. variants .. " not allowed for this verb class")
end
if data.yo and not data.ppp then
error("Variant ё specified without calling for past passive participle")
end
if data.o and not data.ppp then
error("Variant о specified without calling for past passive participle")
end
if data.zhd and not data.ppp then
error("Variant жд specified without calling for past passive participle")
end
if data.perf and not data.ppp and not data.ppp_override and not data.shouldnt_have_ppp and not data.impers then
error("For perfective transitive verbs, need to specify past passive participle by variant or override; use |ppp=- if no such participle")
end
data.past_stress = variants == "" and "a" or rsub(variants, "/", "")
data.title = data.title ..
prepare_past_stress_indicator(data.past_stress) ..
variant_title
if data.star then
data.title = rsub(data.title, "^([0-9]+°?)", "%1*")
end
-- If there's an override of past_pasv_part, generate the normal participle
-- so we can determine whether the override is irregular. But set a flag
-- so we erase any automatically generated past passive participles that
-- aren't overridden. This happens for example in обнять, where there are
-- two automatically generated past passive participles but a single
-- ppp=о́внятый override.
if not data.ppp and data.main_ppp_override then
data.ppp = "+p"
data.ppp_auto_generated = true
end
end
local function set_past_by_stress(forms, past_stresses, prefix, prefixtr, base,
basetr, args, data, no_pastml, note)
-- If there isn't manual translit for the prefix, we need to supply it
-- if there's manual translit for the base, because we often concatenate
-- prefix to the base.
local prefixtr = prefixtr or basetr and com.translit(prefix)
for _, past_stress in ipairs(rsplit(past_stresses, ",")) do
local pastml = no_pastml and "" or "л"
local stressed_prefixtr
if prefix == "пере" then
stressed_prefix = "пе́ре"
stressed_prefixtr = "pe" .. AC .. "re"
elseif prefix == "раз" then
stressed_prefix = "ро́з"
stressed_prefixtr = "ro" .. AC .. "z"
elseif prefix == "рас" then
-- Does this ever occur?
stressed_prefix = "ро́с"
stressed_prefixtr = "ro" .. AC .. "s"
elseif prefix == "ра" and rfind(base, "^[сз]") then
-- Type 9/11/14/16 with automatically split prefix; may never happen.
stressed_prefix = "ро́"
stressed_prefixtr = "ro" .. AC
else
stressed_prefix, stressed_prefixtr =
com.make_ending_stressed(prefix, prefixtr)
end
-- Normally the base is stressed and the prefix isn't, but it could
-- be the other way around, e.g. in запереть and запереться, where
-- the stress on the prefix is used to get prefix-stressed participles.
-- To deal with this, we usually combine base and prefix unchanged,
-- but in combination with stressed_prefix we always want an unstressed
-- base, and when a stressed -ся́ is called for, we want both of them
-- unstressed.
local ubase, ubasetr = com.make_unstressed(base, basetr)
local uprefix, uprefixtr = com.make_unstressed(prefix, prefixtr)
local prefixbase = prefix .. base
local prefixbasetr = basetr and prefixtr .. basetr
local stressed_prefix_ubase = stressed_prefix .. ubase
local stressed_prefix_ubasetr = ubasetr and stressed_prefixtr .. ubasetr
local uprefixubase = uprefix .. ubase
local uprefixubasetr = ubasetr and uprefixtr .. ubasetr
if past_stress == "a" then
-- (/под/пере/при/по)забы́ть, раздобы́ть, (/пере/по)забы́ться
append_past(forms, prefixbase, prefixbasetr, pastml,
"ла", "ло", "ли", note)
elseif past_stress == "a(1)" then
-- вы́дать, вы́быть, etc.; also проби́ть with the meaning
-- "to strike (of a clock)" (which is a(1),a or similar)
append_past(forms, stressed_prefix_ubase,
stressed_prefix_ubasetr, pastml, "ла", "ло", "ли", note)
elseif past_stress == "b" then
append_past(forms, prefixbase, prefixbasetr, pastml,
"ла́", "ло́", "ли́", note)
elseif past_stress == "b*" then
if not data.refl then
error("Only reflexive verbs can take past stress variant " .. past_stress)
end
-- See comment in type c''. We want to see whether we actually
-- added an argument, and if so, where.
local argset = append_to_arg_chain(forms, "past_m", "past_m",
combine(uprefixubase, uprefixubasetr, pastml .. (note or "")))
if argset and not args[argset] and not data.impers then
data.default_reflex_stress = "ся́"
end
append_past(forms, prefixbase, prefixbasetr, {}, "ла́", "ло́", "ли́", note)
elseif past_stress == "c" then
-- изда́ть, возда́ть, сдать, пересозда́ть, воссозда́ть, надда́ть, наподда́ть, etc.
-- быть, избы́ть, сбыть
-- клясть, закля́сть
append_past(forms, prefixbase, prefixbasetr, pastml, "ла́", "ло", "ли", note)
elseif past_stress == "c(1)" then
-- прибы́ть, убы́ть
-- прокля́сть
-- also, c(1),c:
-- зада́ть, обда́ть, отда́ть, подда́ть, переда́ть (пе́редал), преда́ть, прода́ть, разда́ть (ро́здал), созда́ть, etc.
-- отбы́ть, побы́ть, пробы́ть
-- also, c,c(1):
-- добы́ть
-- Because the prefix may vary depending on stress (esp. for
-- раздать [ро́здал/раздала́]), we need to separate the endings that
-- take the stressed prefix and those that take the unstressed
-- prefix with stressed ending.
append_past(forms, stressed_prefix_ubase, stressed_prefix_ubasetr,
pastml, {}, "ло", "ли", note)
append_past(forms, prefixbase, prefixbasetr, {}, "ла́", {}, {}, note)
elseif past_stress == "c'" then
-- дать
--same with "взять"
append_past(forms, prefixbase, prefixbasetr,
pastml, "ла́", {"ло", "ло́"}, "ли", note)
elseif past_stress == "c''" or past_stress == "c''-nd" or past_stress == "c''-bd" then
if not data.refl then
error("Only reflexive verbs can take past stress variant " .. past_stress)
end
-- c'' (-ся́ dated): all verbs in -да́ться; избы́ться, сбы́ться; all verbs in -кля́сться
-- c''-nd (-ся́ not dated): various verbs in -ня́ться per Zaliznyak
-- c''-bd (-ся́ becoming dated): various verbs in -ня́ться per ruwikt
local note_symbol = past_stress == "c''-nd" and "" or
next_note_symbol(data)
append_past(forms, prefixbase, prefixbasetr,
pastml, "ла́", {"ло́", "ло"}, {"ли́", "ли"})
-- We want to see whether we actually added an argument, and if
-- so, where.
local argset = append_to_arg_chain(forms, "past_m", "past_m",
combine(uprefixubase, uprefixubasetr, pastml .. note_symbol .. (note or "")))
-- Only display the internal note and set the default reflex
-- stress if the form with the note will be displayed (i.e. not
-- impersonal, and no override of this form). FIXME: We should
-- have a more general mechanism to check for this.
if not args[argset] and not data.impers then
ut.insert_if_not(data.internal_notes,
past_stress == "c''" and note_symbol .. " Dated." or
past_stress == "c''-bd" and note_symbol .. " Becoming dated." or nil)
data.default_reflex_stress = "ся́"
end
elseif past_stress == "c''(1)" then
-- запере́ться
-- See comment in type c''. We want to see whether we actually
-- added an argument, and if so, where.
local argset = append_to_arg_chain(forms, "past_m", "past_m",
combine(uprefixubase, uprefixubasetr, pastml .. (note or "")))
if argset and not args[argset] and not data.impers then
data.default_reflex_stress = "ся́"
end
append_past(forms, prefixbase, prefixbasetr, {}, "ла́", "ло́", "ли́", note)
append_past(forms, stressed_prefix_ubase, stressed_prefix_ubasetr,
pastml, {}, "ло", "ли", note)
else
error("Unrecognized past-stress value " .. past_stress .. ", should be a, a(1), b, b*, c, c(1), c', c'', c''-nd, c''-bd, c''(1) or comma-separated list")
end
end
end
-- Split a verb stem into a possibly multisyllabic prefix (пере-, переиз-,
-- воссоз-, повы́-, etc.) and a single-syllable main verb (-тер-, -ли́-, -гре́-,
-- etc.). Normally the splitting is done simply by looking for alternating
-- vowel/consonant sequences, meaning that e.g. разгре́ will be split as
-- ра + згре́ and растер will be split as ра + стер. For most purposes, this
-- doesn't matter, but for the * variant it does; in that case, if it is
-- known that the main verb base always begins with a single consonant,
-- specify SINGLE_CONS_BASE and then e.g. растер will be split as рас + тер.
local function split_monosyllabic_main_verb(ru, tr, single_cons_base)
local rusyl, trsyl = com.split_syllables(ru, tr)
local last_ru = rusyl[#rusyl]
local last_tr = trsyl and trsyl[#trsyl]
table.remove(rusyl, #rusyl)
local prefix_ru = table.concat(rusyl, "")
local prefix_tr
if trsyl then
table.remove(trsyl, #trsyl)
prefix_tr = table.concat(trsyl, "")
end
if single_cons_base then
local cons_to_move, rest = rmatch(last_ru, "^([" .. com.cons .. "]+)([" .. com.cons .. "].*)$")
if cons_to_move then
prefix_ru = prefix_ru .. cons_to_move
last_ru = rest
end
if last_tr then
cons_to_move, rest = rmatch(last_tr, "^([" .. com.tr_cons .. "]+)([" .. com.tr_cons .. "].*)$")
if cons_to_move then
prefix_tr = prefix_tr .. cons_to_move
last_tr = rest
end
end
end
return prefix_ru, prefix_tr, last_ru, last_tr
end
local function split_known_main_verb(arg, mains)
-- Given an argument (which may be RUSSIAN//TR), split the prefix from
-- the main verb, which should be one of the verbs in MAINS (which can be
-- a -- single verb or a list of verbs, but in either case all verbs
-- need to be stressed). This correctly handles stressed and unstressed
-- prefixes.
local stem, tr = nom.split_russian_tr(arg)
if type(mains) ~= "table" then
mains = {mains}
end
for _, main in ipairs(mains) do
assert(com.is_stressed(main))
if rfind(stem, main .. "$") then
stem, tr = nom.strip_ending(stem, tr, main)
if com.is_stressed(stem) then
error("Two stresses in " .. arg)
end
return stem, tr, main, nil
end
main = com.make_unstressed_once(main)
if rfind(stem, main .. "$") then
stem, tr = nom.strip_ending(stem, tr, main)
if com.is_unstressed(stem) then
error("No stresses in " .. arg)
end
return stem, tr, main, nil
end
end
if #mains == 1 then
error("Argument " .. arg .. " doesn't end in " .. mains[1])
else
error("Argument " .. arg .. " doesn't end in any of " .. table.concat(mains, ","))
end
end
local function construct_long_prefix_variant(prefix)
if rfind(prefix, "рас$") then
return rsub(prefix, "рас$", "разо")
end
if rfind(prefix, "ис$") then
return rsub(prefix, "ис$", "изо")
end
if rfind(prefix, "вс$") then
return rsub(prefix, "вс$", "взо")
end
return prefix .. "о"
end
local function append_imper_by_variant(forms, stem, tr, variant, verbclass, note)
local vowel_stem = is_vowel_stem(stem)
local stress = rmatch(verbclass, "([abc])$")
if not stress then
error("Unrecognized verb class '" .. verbclass .. "', should end with a, b or c")
end
local longend = stress == "a" and "и" or "и́"
local shortend = vowel_stem and (com.is_unstressed(stem) and "́й" -- accent on previous vowel
or "й") or "ь"
local function append_short_imper()
append_imper(forms, stem, tr, shortend, shortend .. "те", note)
end
local function append_long_imper()
append_imper(forms, stem, tr, longend, longend .. "те", note)
end
if variant and variant ~= "" then
track("explicit-imper")
track("explicit-imper/" .. verbclass)
end
if variant == "(2)" then
-- use short variants with вы́- (for these verbs, long is expected)
if not rfind(stem, "^вы́-") then
error("Should only specify imperative variant (2) with verbs in вы́-, not " .. stem)
end
append_short_imper()
elseif variant == "[(2)]" then
-- use both long and short variants
append_long_imper()
append_short_imper()
elseif variant == "(3)" then
-- long in singular, short in plural
append_imper(forms, stem, tr, longend, shortend .. "те", note)
elseif variant == "[(3)]" then
-- long and short in singular, short in plural
append_imper(forms, stem, tr, {longend, shortend}, shortend .. "те", note)
elseif variant == "ь" or variant == "й" then
-- short variants wanted
append_short_imper()
elseif variant == "и" then
-- long variants wanted
append_long_imper()
else
assert(not variant or variant == "")
if vowel_stem then
if verbclass == "4b" or verbclass == "4c" or (
verbclass == "4a" and rfind(stem, "^вы́-")) then
append_long_imper()
else
append_short_imper()
end
else -- consonant stem
if stress == "b" or stress == "c" then
append_long_imper()
else
assert(stress == "a")
-- "и" after вы́-, e.g. вы́садить
-- "и" after final щ, e.g. тара́щиться (although this particular
-- verb has a [(3)] spec attached to it)
if rfind(stem, "^вы́-") or rfind(stem, "щ$") or
-- "и" after two consonants in a row (мо́рщить, зафре́ндить)
rfind(stem, "[бвгджзклмнпрстфхцчшщь][бвгджзклмнпрстфхцчшщ]$") then
append_long_imper()
else
-- "ь" after a single consonant (бре́дить)
append_short_imper()
end
end
end
end
end
-- Compute the past passive participle stem for verbs that require it to be
-- iotated (class 4, and class 5 in -еть).
local function iotated_ppp(data, stem, tr)
local iotated_stem, iotated_tr
if data.zhd then
local subbed
iotated_stem, subbed = rsubb(stem, "з?д$", "жд")
if not subbed then
error("Variant -жд- specified but stem " .. stem .. " doesn't end in -д")
end
if tr then
iotated_tr, subbed = rsubb(tr, "z?d$", "žd")
if not subbed then
error("Variant -жд- specified but translit " .. tr .. " doesn't end in -d")
end
end
else
iotated_stem, iotated_tr = com.iotation(stem, tr, data.shch)
end
return iotated_stem, iotated_tr
end
-- Set the past passive participle of verbs where the stress is moved left
-- from the ending by one syllable (if possible) if the ending is stressed,
-- otherwise left as-is (except class 1a in -е́ть, which has ending-stressed
-- -ённый). This applies to classes 1, 2, 3, 5, 6, 10 and 13. The stem comes
-- from the infinitive, iotated in class 5 -еть/-ѣть verbs. The participle
-- ending is -анный/-янный for verbs in -ать/-ять, -енный/-ённый for verbs in -еть,
-- -ѣнный/-ѣ̈нный for verbs in -ѣть, otherwise -тый.
local function set_moving_ppp(forms, data)
if not data.ppp then
return
end
-- NOTE: No need to check for multiple infinitives because no verbs have
-- them normally, and we probably don't want to check for overrides here
-- (e.g. it would break достичь and related verbs, which have participles
-- based on the infinitive достигнуть).
local infinitive, infinitivetr = extract_russian_tr(forms["infinitive"])
local stem, ending = rmatch(infinitive, "^(.*)([аеѣоуя]́?ть)$")
if not stem then
error("Strange infinitive " .. infinitive .. " when trying to create participle")
end
local tr, endingtr
if infinitivetr then
if ending == "ять" or ending == "я́ть" then
tr, endingtr = rmatch(infinitivetr, "^(.*)(ja" .. AC .. "?tʹ)$")
else
tr, endingtr = rmatch(infinitivetr, "^(.*)([aeěou]" .. AC .. "?tʹ)$")
end
if not tr then
error("Translit " .. infinitivetr .. " doesn't match Cyrillic " ..
infinitive)
end
end
local ending_vowel = usub(ending, 1, 1)
local ppptype = data.ppp
if com.is_nonsyllabic(stem) then
-- e.g. 3b гну́ть (гну́тый); but not -нуть (type 3a, as a suffix)
ppptype = "(7)"
end
if ut.contains({"5a", "5b", "5c"}, data.conj_type) and
(ending_vowel == "е" or ending_vowel == "ѣ") then
stem, tr = iotated_ppp(data, stem, tr)
end
if not com.is_stressed(stem) then
stem, tr = com.make_ending_stressed(stem, tr)
end
if data.o then
-- цев -> цо́в, e.g. (об)лицева́ть -> (об)лицо́ванный
stem = rsub(stem, "е́", "о́") -- Cyrillic
if tr then
tr = rsub(tr, "e" .. AC, "o" .. AC) -- Latin
end
elseif data.yo then
-- ё occurs with e.g. 1a наверста́ть (навёрстанный)
-- ё occurs with e.g. 3b поверну́ть (повёрнутый)
-- ё occurs with e.g. 5b лежа́ть (лёжанный) but not with 5c держа́ть
-- (де́ржанный)
-- ё occurs always with class 2 in -ева́ть, e.g.
-- (за)тушева́ть ((за)тушёванный) and (за)клева́ть ((за)клёванный)
local subbed
stem, subbed = rsubb(stem, "е́", "ё") -- Cyrillic
if not subbed and data.old then
stem, subbed = rsub(stem, "ѣ́", "ѣ̈")
end
if not subbed then
error("No stressed е" .. (data.old and " or ѣ" or "") ..
" in stem " .. stem ..
" to replace with ё" .. (data.old and " or ѣ̈" or "") ..
" when trying to create participle")
end
if tr then
tr, subbed = rsub(tr, "j[eě]" .. AC, "jo" .. AC) -- Latin
if not subbed then
tr, subbed = rsub(tr, "[eě]" .. AC, "jo" .. AC) -- Latin
end
if not subbed then
error("No stressed е in translit " .. tr .. " to replace with jo when trying to create participle")
end
end
end
if data.conj_type == "1a" and ending_vowel == "е" then
-- 1a, only одоле́ть, преодоле́ть, verbs in -печатле́ть
set_ppp(forms, stem, tr, "ённый")
elseif data.conj_type == "1a" and ending_vowel == "ѣ" then
set_ppp(forms, stem, tr, "ѣ̈нный")
else
local stressed_ending, unstressed_ending
if ending_vowel == "е" then
stressed_ending = "ённый"
unstressed_ending = "енный"
elseif ending_vowel == "ѣ" then
stressed_ending = "ѣ̈нный"
unstressed_ending = "ѣнный"
else
local ppp_ending =
(ending_vowel == "а" or ending_vowel == "я") and "нный" or "тый"
stressed_ending = ending_vowel .. AC .. ppp_ending
unstressed_ending = ending_vowel .. ppp_ending
end
set_ppp(forms, stem, tr,
-- (7) occurs with 1a обуя́ть (обуя́нный)
ppptype == "(7)" and stressed_ending or
-- [(7)] -- when does it occur? may only occur in class 4
ppptype == "[(7)]" and {unstressed_ending, stressed_ending} or
unstressed_ending)
end
end
-- Iterate over the values of a property (e.g. past_m, past_f), handling
-- overrides properly. Call FN on each one, passing in RU, TR, NOTE.
local function iterate_over_prop(forms, args, prop, fn)
for _, form in ipairs(main_to_all_verb_forms[prop]) do
local ru, tr
if args[form] then
local orig_forms = {}
for _, form2 in ipairs(main_to_all_verb_forms[prop]) do
if forms[form2] then
table.insert(orig_forms, forms[form2])
end
end
local override = parse_and_stress_override(form, args[form], forms[form], orig_forms)
ru, tr = extract_russian_tr(override)
end
if (not ru or ru == "" or ru == "-") and forms[form] then
ru, tr = extract_russian_tr(forms[form])
end
-- skip unstressed forms (may occur in the past_m when a stressed
-- reflexive -ся́ should occur; these occur only in запереться and
-- опереться, where they're used to generate the past active part
-- and past adverbial part, and end-stressed forms shouldn't be
-- generated)
if ru and ru ~= "" and ru ~= "-" and not com.is_unstressed(ru) then
local ruentry, runotes = m_table_tools.separate_notes(ru)
local trentry, trnotes
if tr then
trentry, trnotes = m_table_tools.separate_notes(tr)
end
fn(ruentry, trentry, {runotes, trnotes})
end
end
end
-- Set the past passive participle for those classes where it is derived
-- from the past tense masculine singular (9, 11, 12, 14, 15, 16). We need
-- to apply any relevant overrides.
local function set_ppp_from_past_m(forms, args, data)
if not data.ppp then
return
end
iterate_over_prop(forms, args, "past_m", function(ru, tr, note)
if rfind(ru, "л$") then
ru = rsub(ru, "л$", "")
if tr then
tr = rsub(tr, "l$", "")
end
end
append_ppp(forms, ru, tr, "тый", note)
end)
end
-- Set the past passive participle for class-4 verbs.
local function set_class_4_ppp(forms, data, stem, tr, vclass)
if not data.ppp then
return
end
local iotated_stem, iotated_tr = iotated_ppp(data, stem, tr)
vclass = vclass or data.conj_type
if vclass == "4b" then
local stressed_iotated_stem, stressed_iotated_tr =
com.make_ending_stressed(iotated_stem, iotated_tr)
set_ppp(forms, stressed_iotated_stem, stressed_iotated_tr,
-- (8) occurs with 4b скрои́ть (скро́енный)
data.ppp == "(8)" and "енный" or
-- [(8)] occurs with 4b разгроми́ть (разгромлённый, разгро́мленный)
data.ppp == "[(8)]" and {"ённый", "енный"} or "ённый")
else
set_ppp(forms, iotated_stem, iotated_tr,
-- (7) occurs with 4c раздели́ть (разделённый)
data.ppp == "(7)" and "ённый" or
-- [(7)] occurs with 4a осве́домить (осве́домленный, осведомлённый)
-- [(7)] occurs with 4c иссуши́ть (иссу́шенный, иссушённый)
data.ppp == "[(7)]" and {"енный", "ённый"} or "енный")
end
end
-- Set the past passive participle for class-7 and class-8 verbs. These
-- form the PPP by adding to the base of the 3sg pres/futr (i.e. minus
-- -ет/-ёт). The stress follows the stress of the past singular feminine.
-- Only types a, a(1) and b exist, meaning that if the past singular feminine
-- is ending-stressed then the PPP ending is -ённый, otherwise it is -енный
-- with the stress of the 3sg pres/futr base preserved (and added to the
-- last syllable if the base has no stress, as in 7b укра́сть, 3sg украдёт,
-- fem sg past укра́ла, PPP укра́денный).
local function set_class_7_8_ppp(forms, args, data)
if not data.ppp then
return
end
local sg3_bases = {}
-- Extract 3sg bases. There may be more than one possible form, e.g. in
-- обокра́сть, so support this.
-- FIXME: We don't support checking for overrides here; doing so isn't
-- overly hard but is a bit tricky because the overrides will be either
-- pres_3sg or futr_3sg, depending on the aspect of the verb.
-- FIXME: We don't support manual translit here, because neither 7 nor 8
-- support it elsewhere.
for _, form in ipairs(main_to_all_verb_forms["pres_futr_3sg"]) do
local ru, tr
if forms[form] then
ru, tr = extract_russian_tr(forms[form])
end
if ru and ru ~= "" and ru ~= "-" then
local ruentry, runotes = m_table_tools.separate_notes(ru)
ruentry = rsub(ruentry, "[её]т$", "")
if com.is_unstressed(ruentry) then
ruentry = com.make_ending_stressed(ruentry)
end
ut.insert_if_not(sg3_bases, {ruentry, runotes})
end
end
-- Here we do the same rigmarole as in set_ppp_from_past_m(), to respect
-- any past_f overrides that might have been set. It's unlikely that
-- there is more than one possible form but we support it.
iterate_over_prop(forms, args, "past_f", function(ru, tr, note)
for _, base_and_notes in ipairs(sg3_bases) do
local base, notes = base_and_notes[1], base_and_notes[2]
append_ppp(forms, base, nil,
-- check if past_f is ending-stressed
rfind(ru, AC .. "$") and "ённый" or "енный", notes)
end
end)
end
--[=[
Conjugation functions
]=]
conjugations["1a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"+p", "7", "ё"})
local stem, tr = nom.split_russian_tr(get_stressed_arg(args, 2))
if stem == "-" and not tr then
-- Template space; leave it
else
stem, tr = nom.strip_ending(stem, tr, "ть")
end
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "ть")
append_participles(forms, stem, tr, "ющий", "емый", "я", "вший", "вши", "в")
set_moving_ppp(forms, data)
present_je(forms, stem, tr, "a")
append_imper(forms, stem, tr, "й", "йте")
set_past(forms, stem, tr, "л", "ла", "ло", "ли")
return forms
end
local function guts_of_2(args, data)
local forms = {}
local inf_stem, inf_tr = nom.split_russian_tr(get_stressed_arg(args, 2))
inf_stem, inf_tr = nom.strip_ending(inf_stem, inf_tr, "ть")
no_stray_args(args, 2)
local pres_stem, pres_tr = inf_stem, inf_tr
local variants = args[1] or ""
parse_variants(data, variants, {"+p", "7"})
-- If stem ends in -ева́ть and a past passive participle is called for
-- with stress on the -е-, automatically set -о- or -ё- as required.
if data.ppp and data.ppp ~= "(7)" then
if rfind(inf_stem, "цева́") then
if data.ppp == "[(7)]" then
-- FIXME. Theoretically we should support this but there
-- aren't any verbs requiring it. It won't work properly
-- currently because we need the о to appear only when
-- stressed.
error("Variant [(7)] not supported for class 2")
end
-- цев -> цо́в, e.g. (об)лицева́ть -> (об)лицо́ванный
data.o = true
data.title = data.title .. "(-о-)"
elseif rfind(inf_stem, "ева́") then
data.yo = true
data.title = data.title .. "(-ё-)"
end
end
-- all -ова- change to -у-
pres_stem = rsub(pres_stem, "о(́?)ва(́?)$", "у%1%2")
pres_tr = pres_tr and rsub(pres_tr, "o(́?)va(́?)$", "u%1%2")
-- -ева- change to -ю- after most consonants and vowels, to -у- after hissing sounds and ц
if rfind(pres_stem, "[бвгдзклмнпрстфхь" .. com.vowel .. AC .. "]е(́?)ва(́?)$") then
pres_stem = rsub(pres_stem, "е(́?)ва(́?)$", "ю%1%2")
pres_tr = pres_tr and rsub(pres_tr, "e(́?)va(́?)$", "ju%1%2")
elseif rfind(pres_stem, "[жцчшщ]е(́?)ва(́?)$") then
pres_stem = rsub(pres_stem, "е(́?)ва(́?)$", "у%1%2")
pres_tr = pres_tr and rsub(pres_tr, "e(́?)va(́?)$", "u%1%2")
end
forms["infinitive"] = combine(inf_stem, inf_tr, "ть")
if data.conj_type == "2a" then
append_participles_2stem(forms, pres_stem, pres_tr, inf_stem, inf_tr,
"ющий", "емый", "я", "вший", "вши", "в")
present_je(forms, pres_stem, pres_tr, "a")
else
append_participles_2stem(forms, pres_stem, pres_tr, inf_stem, inf_tr,
"ю́щий", "-", "я́", "вший", "вши", "в")
present_je(forms, pres_stem, pres_tr, "b")
end
set_moving_ppp(forms, data)
append_imper(forms, pres_stem, pres_tr, "й", "йте")
set_past(forms, inf_stem, inf_tr, "л", "ла", "ло", "ли")
return forms
end
conjugations["2a"] = function(args, data)
return guts_of_2(args, data)
end
conjugations["2b"] = function(args, data)
return guts_of_2(args, data)
end
conjugations["3°a"] = function(args, data)
local forms = {}
-- (5), [(6)] or similar; imperative indicators
parse_variants(data, args[1], {"5", "6", "23", "и", "+p", "7", "ё"})
local stem, tr = nom.split_russian_tr(get_stressed_arg(args, 2))
stem, tr = nom.strip_ending(stem, tr, "нуть")
local vowel_stem = is_vowel_stem(stem)
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "нуть")
append_participles(forms, stem, tr,
-- default is blank for pres passive and adverbial
"нущий", "-", "-",
data.var6 == "req" and "нувший" or
data.var6 == "opt" and (vowel_stem and {"вший", "нувший"} or {"ший", "нувший"}) or
vowel_stem and "вший" or "ший",
data.var6 == "req" and "нувши" or
data.var6 == "opt" and (vowel_stem and {"вши", "нувши"} or {"ши", "нувши"}) or
vowel_stem and "вши" or "ши",
data.var6 == "req" and "нув" or
data.var6 == "opt" and (vowel_stem and {"в", "нув"} or "нув") or
vowel_stem and "в" or "-")
set_moving_ppp(forms, data)
present_e_a(forms, stem .. "н", tr and tr .. "n")
append_imper_by_variant(forms, stem .. "н", tr and tr .. "n", data.imper_variant, "3°a")
forms["past_m"] = data.var5 and combine(stem, tr, "нул") or "-"
forms["past_m_short"] = data.var5 ~= "req" and combine(stem, tr, (vowel_stem and "л" or "")) or nil
forms["past_f_short"] = combine(stem, tr, "ла")
forms["past_n_short"] = combine(stem, tr, "ло")
forms["past_pl_short"] = combine(stem, tr, "ли")
return forms
end
conjugations["3a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"23", "и", "+p", "7", "ё"})
local stem, tr = nom.split_russian_tr(get_stressed_arg(args, 2))
-- make sure we can strip нуть from the stem and any translit;
nom.strip_ending(stem, tr, "нуть")
-- but then just strip the -уть and leave the н
stem, tr = nom.strip_ending(stem, tr, "уть")
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "уть")
append_participles(forms, stem, tr,
-- default is blank for pres passive and adverbial
"ущий", "-", "-", "увший", "увши", "ув")
set_moving_ppp(forms, data)
present_e_a(forms, stem, tr)
append_imper_by_variant(forms, stem, tr, data.imper_variant, "3a")
set_past(forms, stem .. "ул", tr and tr .. "ul", "", "а", "о", "и")
return forms
end
local function guts_of_3b_3c(args, data, vclass)
local forms = {}
parse_variants(data, args[1], {"+p", "7", "ё"})
local stem, tr = nom.split_russian_tr(get_stressed_arg(args, 2))
-- make sure we can strip нуть from the stem and any translit;
nom.strip_ending(stem, tr, "ну́ть")
-- but then just strip the -у́ть and leave the н
stem, tr = nom.strip_ending(stem, tr, "у́ть")
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "у́ть")
append_participles(forms, stem, tr,
-- default is blank for pres passive and adverbial
"у́щий", "-", "-", "у́вший", "у́вши", "у́в")
set_moving_ppp(forms, data)
append_imper(forms, stem, tr, "и́", "и́те")
set_past(forms, stem, tr, "у́л", "у́ла", "у́ло", "у́ли")
if data.conj_type == "3b" then
present_e_b(forms, stem, tr)
else
stem, tr = com.make_ending_stressed(stem, tr)
present_e_c(forms, stem, tr)
end
return forms
end
conjugations["3b"] = function(args, data)
return guts_of_3b_3c(args, data)
end
conjugations["3c"] = function(args, data)
return guts_of_3b_3c(args, data)
end
conjugations["4a"] = function(args, data)
local forms = {}
-- imperative variants, also щ, used for verbs like похитить (похи́щу) (4a),
-- защитить (защищу́) (4b), поглотить (поглощу́) (4c) with a different
-- iotation (т -> щ, not ч)
parse_variants(data, args[1], {"23", "и", "щ", "past", "+p", "7", "жд"})
local stem, tr = nom.split_russian_tr(get_stressed_arg(args, 2))
stem, tr = nom.strip_ending(stem, tr, "ить")
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "ить")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(stem, "[шщжч]$")
append_participles(forms, stem, tr, hushing and "ащий" or "ящий",
"awkward-имый", hushing and "а" or "я", "ивший", "ивши", "ив")
set_class_4_ppp(forms, data, stem, tr)
present_i(forms, stem, tr, "a", data.shch)
append_imper_by_variant(forms, stem, tr, data.imper_variant, "4a")
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, stem .. "и",
tr and tr .. "i", args, data)
return forms
end
conjugations["4a1a"] = function(args, data)
local forms = {}
data.title = "4a // 1a"
data.cat_conj_types = {"1a", "4a"}
-- imperative variants, also щ, used for verbs like похитить (похи́щу) (4a),
-- защитить (защищу́) (4b), поглотить (поглощу́) (4c) with a different
-- iotation (т -> щ, not ч)
parse_variants(data, args[1], {"23", "и", "щ", "past", "+p", "7", "жд"})
local stem4, tr4 = nom.split_russian_tr(get_stressed_arg(args, 2))
stem4, tr4 = nom.strip_ending(stem4, tr4, "ить")
local hushing = rfind(stem4, "[шщжч]$")
local stem1, tr1
if hushing then
stem1 = stem4 .. "а"
tr1 = tr4 and tr4 .. "a"
else
stem1 = stem4 .. "я"
tr1 = tr4 and tr4 .. "ja"
end
no_stray_args(args, 2)
forms["infinitive"] = combine(stem4, tr4, "ить")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
append_participles(forms, stem4, tr4, hushing and "ащий" or "ящий",
"awkward-имый", hushing and "а" or "я", "ивший", "ивши", "ив")
append_participles(forms, stem1, tr1, "ющий", "емый", "я", {}, {}, {})
set_class_4_ppp(forms, data, stem4, tr4)
present_i(forms, stem4, tr4, "a", data.shch)
present_je(forms, stem1, tr1, "a", data.shch)
append_imper_by_variant(forms, stem4, tr4, data.imper_variant, "4a")
append_imper(forms, stem1, tr1, "й", "йте")
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, stem4 .. "и",
tr4 and tr4 .. "i", args, data)
return forms
end
conjugations["4b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"щ", "past", "+p", "8", "жд"})
local stem, tr = nom.split_russian_tr(get_stressed_arg(args, 2))
stem, tr = nom.strip_ending(stem, tr, "и́ть")
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "и́ть")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(stem, "[шщжч]$")
append_participles(forms, stem, tr, hushing and "а́щий" or "я́щий",
"awkward-и́мый", hushing and "а́" or "я́", "и́вший", "и́вши", "и́в")
set_class_4_ppp(forms, data, stem, tr)
present_i(forms, stem, tr, "b", data.shch)
append_imper(forms, stem, tr, "и́", "и́те")
-- set prefix to "" as past stem may vary in length and no (1) variants
local stem_noa, tr_noa = com.make_unstressed_once(stem, tr)
set_past_by_stress(forms, data.past_stress, "", nil, stem_noa .. "и́",
tr_noa and tr_noa .. "i" .. AC, args, data)
return forms
end
conjugations["4c"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"щ", "4", "past", "+p", "7", "жд"})
local stem, tr = nom.split_russian_tr(get_stressed_arg(args, 2))
stem, tr = nom.strip_ending(stem, tr, "и́ть")
stem, tr = com.make_ending_stressed(stem, tr)
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "и́ть")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(stem, "[шщжч]$")
local prap_end_stressed = hushing and "а́щий" or "я́щий"
local prap_stem_stressed = hushing and "ащий" or "ящий"
append_participles(forms, stem, tr, data.var4 == "req" and prap_stem_stressed
or data.var4 == "opt" and {prap_end_stressed, prap_stem_stressed}
or prap_end_stressed,
"awkward-и́мый", hushing and "а́" or "я́", "и́вший", "и́вши", "и́в")
set_class_4_ppp(forms, data, stem, tr)
present_i(forms, stem, tr, "c", data.shch)
append_imper(forms, stem, tr, "и́", "и́те")
local stem_noa, tr_noa = com.make_unstressed_once(stem, tr)
set_past_by_stress(forms, data.past_stress, "", nil, stem_noa .. "и́",
tr_noa and tr_noa .. "i" .. AC, args, data)
return forms
end
-- Combined class 5. But there's enough conditional code that it might make
-- more sense to separate them again.
local function guts_of_5(args, data)
local forms = {}
local is5a = data.conj_type == "5a"
local is5b = data.conj_type == "5b"
-- imperative ending (выгнать - выгони) and past stress; imperative is
-- "й" after any vowel (e.g. выстоять), with or without an acute accent,
-- otherwise ь or и
if is5a or is5b then
parse_variants(data, args[1], {"23", "и", "past", "+p", "7", "ё"})
else
parse_variants(data, args[1], {"23", "и", "past", "+p", "7", "ё", "4"})
end
local inf = get_stressed_arg(args, 2)
local past_stem = nom.strip_ending(inf, nil, "ть")
local stem = is5b and get_opt_unstressed_arg(args, 3) or get_opt_stressed_arg(args, 3)
local default_stem = rmatch(past_stem, "^(.*)[еѣая]́?$")
if not default_stem then
error("Argument " .. inf .. " doesn't end in еть, ѣть, ать or ять")
end
if not is5a and not is5b then
default_stem = com.make_ending_stressed(default_stem)
end
stem = stem or default_stem
local pres_note = stem ~= default_stem and IRREG
no_stray_args(args, 3)
forms["infinitive"] = past_stem .. "ть"
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(stem, "[шщжч]$")
if is5a then
append_participles_2stem(forms, stem, nil, past_stem, nil,
hushing and "ащий" or "ящий", "имый", hushing and "а" or "я",
"вший", "вши", "в", pres_note)
elseif is5b then
append_participles_2stem(forms, stem, nil, past_stem, nil,
hushing and "а́щий" or "я́щий", "и́мый", hushing and "а́" or "я́",
"вший", "вши", "в", pres_note)
else
-- var4 occurs with at least терпре́ть and дыша́ть
local prap_end_stressed = hushing and "а́щий" or "я́щий"
local prap_stem_stressed = hushing and "ащий" or "ящий"
append_participles_2stem(forms, stem, nil, past_stem, nil,
data.var4 == "req" and prap_stem_stressed
or data.var4 == "opt" and {prap_end_stressed, prap_stem_stressed}
or prap_end_stressed,
"и́мый", hushing and "а́" or "я́", "вший", "вши", "в", pres_note)
end
set_moving_ppp(forms, data)
present_i(forms, stem, nil, is5a and "a" or is5b and "b" or "c", nil, pres_note)
append_imper_by_variant(forms, stem, nil, data.imper_variant, data.conj_type, pres_note)
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, past_stem, nil,
args, data)
return forms
end
conjugations["5a"] = function(args, data)
return guts_of_5(args, data)
end
conjugations["5b"] = function(args, data)
return guts_of_5(args, data)
end
conjugations["5c"] = function(args, data)
return guts_of_5(args, data)
end
-- Implement 6a, 6°a, 6a1as13, 6a1as14, and 1a6a.
local function guts_of_6a(args, data, vclass)
local forms = {}
-- Type 6a1a, section 13:
-- Forms of both 6a and 1a can occur. They are the same in the infinitive
-- and past. In the present active participle and the present/future, the
-- type 6 forms are preferred and the type 1a forms are colloquial. In the
-- remaining present forms and the imperative, both are equally preferred
-- (we put the type-6 forms first because Zaliznyak lists them first).
-- Type 6a1a section 14, type 1a6a:
-- Forms of both 6a and 1a can occur. They are the same in the infinitive
-- and past. In the present adverbial participle and the imperative, the
-- type 1a forms are preferred and the type 6a forms are dated. In the
-- remaining present forms, one or the other is slightly preferred (type
-- 6a for 6a1a, type 1a for 1a6a).
if vclass == "6a1as13" or vclass == "6a1as14" then
data.title = "6a // 1a"
data.cat_conj_types = {"1a", "6a"}
elseif vclass == "1a6a" then
data.title = "1a // 6a"
data.cat_conj_types = {"1a", "6a"}
end
parse_variants(data, args[1], {"23", "и", "past", "+p", "7", "ё"})
local inf = get_stressed_arg(args, 2)
local inf_past_stem = nom.strip_ending(inf, nil, "ть")
local stem = rmatch(inf_past_stem, "^(.*)[ая]́?$")
if not stem then
error("Argument " .. inf .. " doesn't end in ать or ять")
end
if com.is_unstressed(stem) then
-- колыха́ть, колеба́ть, etc.
stem = com.make_ending_stressed(stem)
end
-- вызвать - вы́зову (в́ызов)
local pres_stem = get_opt_stressed_arg(args, 3) or stem
no_stray_args(args, 3)
local pres_note = pres_stem ~= stem and IRREG
-- no iotation, e.g. вырвать - вы́рву
local no_iotation = vclass == "6°a"
-- replace consonants for 1st person singular present/future
local iotated_stem = no_iotation and pres_stem or com.iotation(pres_stem)
forms["infinitive"] = inf_past_stem .. "ть"
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(iotated_stem, "[шщжч]$") or no_iotation
-- Participles
-- pres_pasv_part is normal if infinitive ends in -ять, nonexistent except
-- with certain lexical exceptions (колеба́ть, колыха́ть, глаго́лать,
-- дви́гать with exceptional form дви́жимый) if infinitive ends in -ать
local prpp_status = rfind(inf_past_stem, "я́?$") and "" or "none-"
if vclass == "6a" or vclass == "6°a" or vclass == "6a1as13" then
append_participles_2stem(forms, iotated_stem, nil, inf_past_stem, nil,
hushing and "ущий" or "ющий", prpp_status .. "емый", hushing and "а" or "я",
"вший", "вши", "в", pres_note)
if vclass == "6a1as13" then
-- then all the type 1a forms (both are the same in the past)
append_participles(forms, inf_past_stem, nil, "ющий*", prpp_status .. "емый", "я")
end
elseif vclass == "6a1as14" then
-- first the preferred type 6a present active/passive participles
append_participles(forms, iotated_stem, nil,
hushing and "ущий" or "ющий", prpp_status .. "емый", {}, {}, {}, {}, pres_note)
-- then all the type 1a forms (both are the same in the past)
append_participles(forms, inf_past_stem, nil, "ющий", "емый", "я",
"вший", "вши", "в")
-- then the dated type 6a present adverbial participle
append_participles(forms, iotated_stem, nil,
{}, {}, hushing and "а*" or "я*", {}, {}, {}, pres_note)
else -- type 1a6a
-- first the preferred type 1a forms (both are the same in the past)
append_participles(forms, inf_past_stem, nil, "ющий", "емый", "я",
"вший", "вши", "в")
-- then the type 6a forms (dated in present adverbial participle)
append_participles(forms, iotated_stem, nil,
hushing and "ущий" or "ющий", prpp_status .. "емый", hushing and "а*" or "я*",
{}, {}, {}, pres_note)
end
set_moving_ppp(forms, data)
-- Present/future tense
local function class_6_present()
if no_iotation then
present_e_a(forms, pres_stem, nil, pres_note)
else
present_je(forms, pres_stem, nil, "a", nil, pres_note)
end
end
if vclass == "6a" or vclass == "6°a" then
class_6_present()
elseif vclass == "1a6a" then
-- Do type 1a forms
present_je(forms, inf_past_stem, nil, "a")
class_6_present()
elseif vclass == "6a1as14" then
class_6_present()
-- Do type 1a forms
present_je(forms, inf_past_stem, nil, "a")
else
-- 6a1as13
class_6_present()
-- Do type 1a forms
present_je(forms, inf_past_stem, nil, "a", nil, "*")
end
-- Imperative forms; if 1a6a or 6a1as14, type 6a forms are dated;
-- if 6a1as13, type 6a forms go first.
local function class_1_impr()
append_imper(forms, inf_past_stem, nil, "й", "йте")
end
local function class_6_impr()
local dated_note = ((vclass == "6a1as14" or vclass == "1a6a") and "*" or "") ..
(pres_note or "")
append_imper_by_variant(forms, iotated_stem, nil, data.imper_variant,
"6a", dated_note)
end
if vclass == "6a1as14" or vclass == "1a6a" then
class_1_impr()
class_6_impr()
elseif vclass == "6a1as13" then
class_6_impr()
class_1_impr()
else
class_6_impr()
end
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, inf_past_stem, nil,
args, data)
if vclass == "6a1as14" or vclass == "1a6a" then
ut.insert_if_not(data.internal_notes, "* Dated.")
elseif vclass == "6a1as13" then
ut.insert_if_not(data.internal_notes, "* Colloquial; type-6 forms preferred.")
end
return forms
end
conjugations["6a"] = function(args, data)
return guts_of_6a(args, data, "6a")
end
conjugations["6°a"] = function(args, data)
return guts_of_6a(args, data, "6°a")
end
conjugations["6a1as13"] = function(args, data)
return guts_of_6a(args, data, "6a1as13")
end
conjugations["6a1as14"] = function(args, data)
return guts_of_6a(args, data, "6a1as14")
end
conjugations["1a6a"] = function(args, data)
return guts_of_6a(args, data, "1a6a")
end
-- implement 6b, 6°b
local function guts_of_6b(args, data, vclass)
local forms = {}
parse_variants(data, args[1], {"past", "+p", "7", "ё"})
local inf = get_stressed_arg(args, 2)
local stem = rmatch(inf, "^(.*)[ая]́ть$")
if not stem then
error("Argument " .. inf .. " doesn't end in ать or ять")
end
-- звать - зов, драть - дер
local pres_stem = get_opt_unstressed_arg(args, 3) or stem
no_stray_args(args, 3)
-- no iotation, e.g. рвать - рву
local no_iotation = vclass == "6°b"
local vowel_end_stem = is_vowel_stem(stem)
local pres_note = pres_stem ~= stem and IRREG
if no_iotation then
present_e_b(forms, pres_stem, nil, pres_note)
else
present_je(forms, pres_stem, nil, "b", nil, pres_note)
end
local impr_end = vowel_end_stem and "́й" -- accent on the preceding vowel
or "и́"
append_imper(forms, pres_stem, nil, impr_end, impr_end .. "те", pres_note)
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(pres_stem, "[шщжч]$")
-- no pres_pasv_part
local past_stem_with_vowel = stem .. (vowel_end_stem and "я́" or "а́")
append_participles_2stem(
forms, pres_stem, nil, past_stem_with_vowel, nil,
((hushing or no_iotation) and "у́щий" or "ю́щий"), {}, (hushing and "а́" or "я́"),
"вший", "вши", "в", pres_note)
forms["infinitive"] = combine(past_stem_with_vowel, nil, "ть")
set_moving_ppp(forms, data)
-- past_f for ждала́, подождала́ now handled through general mechanism
--for разобрало́сь, past_n2 разобрало́ now handled through general mechanism
--for разобрали́сь, past_pl2 разобрали́ now handled through general mechanism
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil,
stem .. (vowel_end_stem and "я́" or "а́"), nil, args, data)
return forms
end
conjugations["6b"] = function(args, data)
return guts_of_6b(args, data, "6b")
end
conjugations["6°b"] = function(args, data)
return guts_of_6b(args, data, "6°b")
end
-- Implement 6c, 6°c and 6c1a.
local function guts_of_6c(args, data, vclass)
local forms = {}
-- In type 6c1a, forms of both 6c and 1a can occur. They are
-- the same in the infinitive and past. In the present active participle
-- and the present/future, the type 6c forms are preferred and the type 1a
-- forms are colloquial. In the remaining present forms and the imperative,
-- both are equally preferred (we put the 6c forms first because Zaliznyak
-- lists 6c first).
if vclass == "6c1a" then
data.title = "6c // 1a"
data.cat_conj_types = {"1a", "6c"}
end
-- optional щ parameter for verbs like клеветать (клевещу́), past stress
parse_variants(data, args[1], {"щ", "past", "+p", "7", "ё"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "а́ть")
stem = com.make_ending_stressed(stem)
-- разостла́ть - расстелю́, рассте́лешь
local pres_stem = get_opt_stressed_arg(args, 3) or stem
no_stray_args(args, 3)
local pres_note = pres_stem ~= stem and IRREG
-- remove accent for some forms
local stem_noa = com.make_unstressed(stem)
-- applies only to стона́ть, застона́ть, простона́ть
local no_iotation = vclass == "6°c"
-- iotate the stem
local iotated_stem =
no_iotation and pres_stem or com.iotation(pres_stem, nil, data.shch)
local stem1a = stem_noa .. "а́"
forms["infinitive"] = stem_noa .. "а́ть"
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(iotated_stem, "[шщжч]$")
-- Participles
append_participles_2stem(forms, iotated_stem, nil, stem_noa, nil,
(hushing or no_iotation) and "ущий" or "ющий", {},
hushing and "а́" or "я́", "а́вший", "а́вши", "а́в", pres_note)
if vclass == "6c1a" then
-- then all the type 1a forms (both are the same in the past)
append_participles(forms, stem1a, nil, "ющий*", "емый", "я")
end
set_moving_ppp(forms, data)
if no_iotation then
present_e_c(forms, pres_stem, nil, pres_note)
else
present_je(forms, pres_stem, nil, "c", data.shch, pres_note)
end
append_imper(forms, iotated_stem, nil, "и́", "и́те", pres_note)
if vclass == "6c1a" then
present_je(forms, stem1a, nil, "a", nil, "*")
append_imper(forms, stem1a, nil, "й", "йте")
end
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, stem_noa .. "а́", nil,
args, data)
if vclass == "6c1a" then
ut.insert_if_not(data.internal_notes, "* Colloquial; type-6 forms preferred.")
end
return forms
end
conjugations["6c"] = function(args, data)
return guts_of_6c(args, data, "6c")
end
conjugations["6°c"] = function(args, data)
return guts_of_6c(args, data, "6°c")
end
conjugations["6c1a"] = function(args, data)
return guts_of_6c(args, data, "6c1a")
end
local function convert_last_e_to_yo(form)
return rsub(form,
"([еѣ])́?([^" .. com.vowel .. "]*)$",
function(e, nonvowels)
return (e == "е" and "ё" or "ѣ̈") .. nonvowels
end)
end
local function guts_of_7(args, data, forms)
local is7b = data.conj_type == "7b"
local full_inf = get_stressed_arg(args, 2)
local pres_stems = is7b and get_unstressed_arg(args, 3) or get_stressed_arg(args, 3)
pres_stems = rsplit(pres_stems, ",")
local past_stem
if past_stem ~= "ёе" then
past_stem = get_opt_stressed_arg(args, 4)
end
local past_stem_vowel_alt = past_stem == "ёе"
if past_stem_vowel_alt then
past_stem = nil
end
no_stray_args(args, 4)
forms["infinitive"] = full_inf
-- Construct the default past and present stem by a combination of
-- infinitive and present final consonant.
-- (1) Deduce the final consonant.
local final_cons
for _, pres_stem in ipairs(pres_stems) do
-- Final cons is -ст if pres stem ends in vowel + ст, else
-- single final cons [дтсзбп] (no actual examples of final п).
-- Note that final -з can occur after a consonant (e.g. ползти́).
local this_final_cons = rmatch(pres_stem,
"[" .. com.vowel .. "]" .. AC .. "?(ст)$")
if not this_final_cons then
this_final_cons = rmatch(pres_stem, "([дтсзбп])$")
end
if not this_final_cons then
error("Unable to determine final consonant from present stem " .. pres_stem)
end
if final_cons and this_final_cons ~= final_cons then
error("Present stems with conflicting final consonants specified: " ..
table.concat(pres_stems, ","))
end
final_cons = this_final_cons
end
-- (2) Find the infinitive minus the termination.
local prefix = rmatch(full_inf, "^(.*)[сз]т[иь]" .. AC .."?$")
if not prefix then
error("Strange infinitive " .. full_inf .. "in class 7")
end
-- (3) Combine infinitive with final consonant.
local default_pres_stem = prefix .. final_cons
if is7b then
default_pres_stem = com.make_unstressed(default_pres_stem)
end
local default_past_stem = default_pres_stem
if com.is_unstressed(default_past_stem) then
default_past_stem = com.make_ending_stressed(default_past_stem)
end
-- (4) Past stems ending in -д and -т when the infinitive ends in -сть (but not -сти or -сти́)
-- lose this consonant (page 85 of Zaliznyak, see also footnote 2 on that page).
if rfind(full_inf, "сть$") then
default_past_stem = rsub(default_past_stem, "[дт]$", "")
end
-- (5) If 7b and the past stem wasn't originally specified as ёе, the past stem gets
-- ё in place of е.
if is7b and not past_stem_vowel_alt then
default_past_stem = convert_last_e_to_yo(default_past_stem)
end
for _, pres_stem in ipairs(pres_stems) do
local pres_note = pres_stem ~= default_pres_stem and IRREG
if is7b then
present_e_b(forms, pres_stem, nil, pres_note)
append_imper(forms, pres_stem, nil, "и́", "и́те", pres_note)
else
present_e_a(forms, pres_stem, nil, pres_note)
append_imper_by_variant(forms, pres_stem, nil, data.imper_variant,
"7a", pres_note)
end
end
-- Construct the past stem if not specified. Note that we then derive a separate
-- past-tense stem from this stem, and this stem as such ends up applying only
-- to the past active and adverbial participles.
if not past_stem then
past_stem = default_past_stem
end
local past_note = past_stem ~= default_past_stem and IRREG
-- Derive the past tense stem from the past stem derived above. This has ё instead of е
-- in 7b verbs; it also loses д and т in all cases, when the past stem derived above only loses
-- these consonants in some cases.
local past_tense_stem = past_stem
if is7b then
past_tense_stem = convert_last_e_to_yo(past_tense_stem)
end
past_tense_stem = rsub(past_tense_stem, "[дт]$", "")
local vowel_pp = is_vowel_stem(past_stem)
local pap = vowel_pp and "вши" or "ши"
local var9_note_symbol = next_note_symbol(data)
for _, pres_stem in ipairs(pres_stems) do
append_participles_2stem(forms, pres_stem, nil, past_stem, nil,
is7b and "у́щий" or "ущий", "-", is7b and "я́" or "я",
vowel_pp and "вший" or "ший",
data.var9 and {is7b and "я́" or "я", pap .. var9_note_symbol} or pap,
vowel_pp and not data.var9 and "в" or "-", pres_note, past_note)
end
if data.var9 then
ut.insert_if_not(data.internal_notes, var9_note_symbol .. " Dated.")
end
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, past_tense_stem, nil,
args, data,
-- 0 ending if the past stem ends in a consonant
not is_vowel_stem(past_tense_stem) and "no-pastml", past_note)
-- set PPP; must be done after both present 3sg and past fem have been set
set_class_7_8_ppp(forms, args, data)
end
conjugations["7a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"23", "и", "9","past", "+p"})
-- лезть - ле́зши - non-existent past_actv_part handled through general mechanism
guts_of_7(args, data, forms)
return forms
end
conjugations["7b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"9", "past", "+p"})
guts_of_7(args, data, forms)
return forms
end
local function class_8a_stem_to_infinitive(stem)
-- map e.g. вы́сек back to высе́чь
return rsub(stem, "[гк]$", "чь")
end
local function class_8b_stem_to_infinitive(stem)
-- map e.g. отвлёк back to отвле́чь
-- map e.g. зажёг back to заже́чь
return com.make_ending_stressed(rsub(rsub(rsub(stem, "ё", "е"), "ѣ̈", "ѣ"), "[гк]$", "чь"))
end
conjugations["8a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local full_inf = get_stressed_arg(args, 2)
local stem = get_stressed_arg(args, 3)
local stressed_past_stem = get_opt_stressed_arg(args, 4) or stem
no_stray_args(args, 4)
forms["infinitive"] = full_inf
local pres_note = class_8a_stem_to_infinitive(stem) ~= full_inf and IRREG
local stressed_past_note =
class_8a_stem_to_infinitive(stressed_past_stem) ~= full_inf and IRREG
-- default for pres_pasv_part is blank
append_participles_2stem(forms, stem, nil, stressed_past_stem, nil,
"ущий", "-", "-", "ший", "ши", "-", pres_note, stressed_past_note)
local iotated_stem = com.iotation(stem)
append_pres_futr(forms, iotated_stem, nil, {}, "ешь", "ет", "ем", "ете", {}, pres_note)
append_pres_futr(forms, stem, nil, "у", {}, {}, {}, {}, "ут", pres_note)
append_imper(forms, stem, nil, "и", "ите", pres_note)
-- set prefix to "" as stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, stem, nil, args, data,
"no-pastml", pres_note)
forms["past_m"] = stressed_past_stem .. (stressed_past_note or "")
-- set PPP; must be done after both present 3sg and past fem have been set
set_class_7_8_ppp(forms, args, data)
return forms
end
conjugations["8b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local full_inf = get_stressed_arg(args, 2)
local stem = get_unstressed_arg(args, 3)
local stressed_past_stems = rsplit(args[4] or "ё", ",")
for _, stressed_past_stem in ipairs(stressed_past_stems) do
if stressed_past_stem ~= "е" then
check_stressed_arg(stressed_past_stem, 4)
end
end
no_stray_args(args, 4)
forms["infinitive"] = full_inf
local pres_note = class_8b_stem_to_infinitive(stem) ~= full_inf and IRREG
local iotated_stem = com.iotation(stem)
append_pres_futr(forms, iotated_stem, nil, {}, "ёшь", "ёт", "ём", "ёте", {}, pres_note)
append_pres_futr(forms, stem, nil, "у́", {}, {}, {}, {}, "у́т", pres_note)
append_imper(forms, stem, nil, "и́", "и́те", pres_note)
-- set prefix to "" as stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil,
com.make_ending_stressed(stem), nil, args, data, "no-pastml", pres_note)
forms["past_m"] = nil
for _, stressed_past_stem in ipairs(stressed_past_stems) do
local pastm_stem, past_part_stem
if stressed_past_stem == "е" then
past_part_stem = com.make_ending_stressed(stem)
pastm_stem = past_part_stem
elseif stressed_past_stem == "ё" then
past_part_stem = convert_last_e_to_yo(com.make_ending_stressed(stem))
pastm_stem = past_part_stem
elseif stressed_past_stem == "ёе" then
past_part_stem = com.make_ending_stressed(stem)
pastm_stem = convert_last_e_to_yo(past_part_stem)
else
pastm_stem = stressed_past_stem
past_part_stem = stressed_past_stem
end
local past_note =
class_8b_stem_to_infinitive(pastm_stem) ~= full_inf and IRREG
-- default for pres_pasv_part is blank; влечь -> влеко́мый handled through
-- general override mechanism
append_participles_2stem(forms, stem, nil, past_part_stem, nil,
"у́щий", "-", "-", "ший", "ши", "-", pres_note, past_note)
append_form(forms, "past_m", pastm_stem, nil, "", past_note)
end
-- set PPP; must be done after both present 3sg and past fem have been set
set_class_7_8_ppp(forms, args, data)
return forms
end
conjugations["9a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "еть")
local pres_stem = get_opt_stressed_arg(args, 3)
no_stray_args(args, 3)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
local default_pres_stem = prefix .. rsub(base, "е", "")
pres_stem = pres_stem or default_pres_stem
local pres_note = pres_stem ~= default_pres_stem and IRREG
forms["infinitive"] = stem .. "еть"
-- perfective only
append_participles(forms, stem, nil, "-", "-", "-", "ший", "ши", "ев")
present_e_a(forms, pres_stem, nil, pres_note)
append_imper(forms, pres_stem, nil, "и", "ите", pres_note)
-- past_m doesn't end in л
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data, "no-pastml")
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["9b"] = function(args, data)
local forms = {}
--for this type, it's important to distinguish impf and pf
local impf = rfind(data.verb_type, "^impf")
parse_variants(data, args[1], {"past", "+p", "*"})
local stem_noa = nom.strip_ending(get_stressed_arg(args, 2), nil, "е́ть")
local stem = rsub(stem_noa, "(.*)е", "%1ё")
local pres_stem = get_opt_unstressed_arg(args, 3)
-- stem used for past active and adverbial participles; defaults to past_m
local past_part_stem = get_opt_stressed_arg(args, 4)
no_stray_args(args, 4)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem, nil, "single_cons_base")
local default_pres_stem =
data.star and construct_long_prefix_variant(prefix) .. rsub(base, "[её]", "") or
prefix .. rsub(base, "[её]", "")
pres_stem = pres_stem or default_pres_stem
local pres_note = pres_stem ~= default_pres_stem and IRREG
forms["infinitive"] = stem_noa .. "е́ть"
present_e_b(forms, pres_stem, nil, pres_note)
append_imper(forms, pres_stem, nil, "и́", "и́те", pres_note)
-- past_m doesn't end in л
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data, "no-pastml")
set_ppp_from_past_m(forms, args, data)
append_participles_2stem(forms, pres_stem, nil, stem, nil, "у́щий", {}, {},
-- impf: тереть -> тёрши
-- pf: растереть -> растёрши, растере́в
-- we handle (рас)тёрши down below because the stress depends on the
-- past_m: запереть -> за́пер, за́перши(й)
{}, {}, impf and {} or "е́в", pres_note)
if past_part_stem then
for _, ppstem in ipairs(rsplit(past_part_stem, ",")) do
append_participles(forms, ppstem, nil, {}, {}, {}, "ший", "ши", {})
end
else
iterate_over_prop(forms, args, "past_m", function(ru, tr, note)
append_participles(forms, ru, tr, {}, {}, {}, "ший", "ши", {}, note)
end)
end
return forms
end
conjugations["10a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"+p", "7"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "оть")
no_stray_args(args, 2)
forms["infinitive"] = stem .. "оть"
-- These verbs are perfective-only, no present participles
append_participles(forms, stem, nil, "-", "-", "-", "овший", "овши", "ов")
set_moving_ppp(forms, data)
present_je(forms, stem, nil, "a")
append_imper(forms, stem, nil, "и", "ите")
set_past(forms, stem .. "ол", nil, "", "а", "о", "и")
return forms
end
conjugations["10c"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"+p", "7"})
local inf_stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "ть")
-- present tense stressed stem "моло́ть" - ме́лет
local pres_stem = get_opt_stressed_arg(args, 3)
no_stray_args(args, 3)
local default_pres_stem =
com.make_ending_stressed(nom.strip_ending(inf_stem, nil, "о́"))
pres_stem = pres_stem or default_pres_stem
-- remove accent for some forms
local pres_stem_noa = com.remove_accents(pres_stem)
local pres_note = pres_stem ~= default_pres_stem and IRREG
forms["infinitive"] = inf_stem .. "ть"
-- default for pres_pasv_part is blank
append_participles_2stem(forms, pres_stem, nil, inf_stem, nil,
"ющий", "-", "я́", "вший", "вши", "в", pres_note)
set_moving_ppp(forms, data)
present_je(forms, pres_stem, nil, "c", nil, pres_note)
append_imper(forms, pres_stem_noa, nil, "и́", "и́те", pres_note)
set_past(forms, inf_stem .. "л", nil, "", "а", "о", "и")
return forms
end
conjugations["11a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "ить")
no_stray_args(args, 2)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem .. "и")
forms["infinitive"] = stem .. "ить"
-- perfective only
append_participles(forms, stem, nil, "-", "-", "-", "ивший", "ивши", "ив")
present_je(forms, stem .. "ь", nil, "a")
append_imper(forms, stem .. "ей", nil, "", "те")
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["11b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p", "*"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "и́ть")
local pres_stem = get_opt_unstressed_arg(args, 3)
no_stray_args(args, 3)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem .. "и́", nil, "single_cons_base")
local default_pres_stem =
data.star and construct_long_prefix_variant(prefix) .. rsub(base, "и́$", "") or
stem
pres_stem = pres_stem or default_pres_stem
local pres_note = pres_stem ~= default_pres_stem and IRREG
forms["infinitive"] = stem .. "и́ть"
append_participles_2stem(forms, pres_stem, nil, stem, nil,
"ью́щий", "-", "ья́", "и́вший", "и́вши", "и́в", pres_note)
present_je(forms, pres_stem .. "ь", nil, "b", nil, pres_note)
append_imper(forms, stem .. "е́й", nil, "", "те")
-- e.g. пила́, лила́
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["12a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = get_opt_stressed_arg(args, 3)
no_stray_args(args, 3)
local default_pres_stem = stem
pres_stem = pres_stem or default_pres_stem
local pres_note = pres_stem ~= default_pres_stem and IRREG
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
append_participles_2stem(forms, pres_stem, nil, stem, nil,
"ющий", "емый", "я", "вший", "вши", "в", pres_note)
present_je(forms, pres_stem, nil, "a", nil, pres_note)
append_imper(forms, pres_stem .. "й", nil, "", "те", pres_note)
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["12b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = get_opt_unstressed_arg(args, 3)
no_stray_args(args, 3)
local default_pres_stem = com.make_unstressed_once(stem)
pres_stem = pres_stem or default_pres_stem
local pres_note = pres_stem ~= default_pres_stem and IRREG
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
append_participles_2stem(forms, pres_stem, nil, stem, nil,
"ю́щий", "-", "я́", "вший", "вши", "в", pres_note)
present_je(forms, pres_stem, nil, "b", nil, pres_note)
-- the preceding vowel is stressed
append_imper(forms, pres_stem .. "́й", nil, "", "те", pres_note)
-- e.g. гнила́ but пе́ла
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["13b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"+p"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = nom.strip_ending(stem, nil, "ва́")
no_stray_args(args, 2)
forms["infinitive"] = stem .. "ть"
-- tricky to use append_participles_2stem() because only pres_actv_part
-- uses pres_stem, not all present participles
forms["pres_actv_part"] = pres_stem .. "ю́щий"
forms["pres_pasv_part"] = stem .. "емый"
forms["pres_adv_part"] = stem .. "я"
forms["past_actv_part"] = stem .. "вший"
forms["past_adv_part"] = stem .. "вши"
forms["past_adv_part_short"] = stem .. "в"
set_moving_ppp(forms, data)
present_je(forms, pres_stem, nil, "b")
forms["impr_sg"] = stem .. "й"
forms["impr_pl"] = stem .. "йте"
set_past(forms, stem .. "л", nil, "", "а", "о", "и")
return forms
end
conjugations["14a"] = function(args, data)
-- only one verb: вы́жать
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = get_stressed_arg(args, 3)
no_stray_args(args, 3)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- perfective only
append_participles(forms, stem, nil, "-", "-", "-", "вший", "вши", "в")
present_e_a(forms, pres_stem)
forms["impr_sg"] = pres_stem .. "и"
forms["impr_pl"] = pres_stem .. "ите"
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["14b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = get_unstressed_arg(args, 3)
no_stray_args(args, 3)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
append_participles_2stem(forms, pres_stem, nil, stem, nil,
"у́щий", "-", "я́", "вший", "вши", "в")
present_e_b(forms, pres_stem)
forms["impr_sg"] = pres_stem .. "и́"
forms["impr_pl"] = pres_stem .. "и́те"
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["14c"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = get_stressed_arg(args, 3)
local pres_stem_noa = com.make_unstressed(pres_stem)
no_stray_args(args, 3)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
append_participles_2stem(forms, pres_stem, nil, stem, nil,
"у́щий", "-", "я́", "вший", "вши", "в")
present_e_c(forms, pres_stem)
forms["impr_sg"] = pres_stem_noa .. "и́"
forms["impr_pl"] = pres_stem_noa .. "и́те"
--two forms for past_m: при́нялся, приня́лся
--изъя́ла but приняла́
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["15a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"+p"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "ть")
no_stray_args(args, 2)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, stem, nil, "нущий", "-", "-", "вший", "вши", "в")
present_e_a(forms, stem .. "н")
forms["impr_sg"] = stem .. "нь"
forms["impr_pl"] = stem .. "ньте"
set_past(forms, stem .. "л", nil, "", "а", "о", "и")
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["16a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "ть")
no_stray_args(args, 2)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, stem, nil, "ву́щий", "-", "-", "вший", "вши", "в")
present_e_a(forms, stem .. "в")
forms["impr_sg"] = stem .. "ви"
forms["impr_pl"] = stem .. "вите"
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["16b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local stem_noa = com.make_unstressed(stem)
no_stray_args(args, 2)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
append_participles(forms, stem, nil, "ву́щий", "-", "вя́", "вший", "вши", "в")
present_e_b(forms, stem_noa .. "в")
forms["impr_sg"] = stem_noa .. "ви́"
forms["impr_pl"] = stem_noa .. "ви́те"
-- e.g. прижило́сь, прижи́лось
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["irreg"] = function(args, data)
local prefix, _, main = split_known_main_verb(get_stressed_arg(args, 2),
-- честь must go before есть
{"бежа́ть", "бѣжа́ть", "хоте́ть", "хотѣ́ть", "да́ть", "че́сть",
"е́сть", "ѣ́сть", "сы́пать", "лга́ть", "мо́чь", "идти́", "йти́",
"е́хать", "ѣ́хать", "мину́ть", "живописа́ть", "ле́чь",
"зи́ждить", "зы́бить", "кля́сть", "стели́ть", "бы́ть", "сса́ть", "сца́ть",
"чти́ть", "шиби́ть", "реве́ть", "има́ть", "вня́ть", "обя́зывать"})
main = com.make_unstressed_once(main)
if not conjugations["irreg-" .. main] then
error("Strange, can't find conjugation for main verb " .. main)
end
return conjugations["irreg-" .. main](args, data)
end
conjugations["irreg-бежать"] = function(args, data)
-- irregular, only for verbs derived from бежать with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2),
{"бежа́ть", "бѣжа́ть"})
data.title = com.is_stressed(prefix) and "5a" or "5b"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "бежа́ть"
append_participles_2stem(forms, "бег", nil, "бежа́", nil,
"у́щий", "-", "-", "вший", "вши", "в", IRREG)
append_imper(forms, "беги́", nil, "", "те", IRREG)
append_pres_futr(forms, "бе", nil,
"гу́" .. IRREG, "жи́шь", "жи́т", "жи́м", "жи́те", "гу́т" .. IRREG)
set_past(forms, "бежа́л", nil, "", "а", "о", "и")
if data.old then
rsub_forms(forms, "^бе", "бѣ")
end
prepend_prefix(forms, prefix)
-- no PPP's for any derivatives of бежать
return forms
end
conjugations["irreg-бѣжать"] = conjugations["irreg-бежать"]
conjugations["irreg-хотеть"] = function(args, data)
-- irregular, only for verbs derived from хотеть with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2),
{"хоте́ть", "хотѣ́ть"})
data.title = "5c'"
data.cat_conj_types = {"5c"} -- no class for 5c', no point in creating for just this verb
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "хоте́ть"
append_participles_2stem(forms, "хот", nil, "хоте́", nil,
"я́щий", "-", "я́", "вший", "вши", "в")
append_imper(forms, "хоти́", nil, "", "те")
append_pres_futr(forms, "", nil,
"хочу́", "хо́чешь" .. IRREG, "хо́чет" .. IRREG, "хоти́м", "хоти́те", "хотя́т")
set_past(forms, "хоте́л", nil, "", "а", "о", "и")
if data.old then
rsub_forms(forms, "^хоте", "хотѣ")
end
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-хотѣть"] = conjugations["irreg-хотеть"]
conjugations["irreg-дать"] = function(args, data)
-- irregular, only for verbs derived from дать with the same stress pattern and вы́дать
local forms = {}
--for this type, it's important to distinguish if it's reflexive to set some stress patterns
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "да́ть")
data.title = com.is_stressed(prefix) and "irreg-a" or "irreg-b"
parse_variants(data, args[1], {"past", "+p"})
no_stray_args(args, 2)
forms["infinitive"] = "да́ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, "", nil, "даю́щий", "-", "-",
"да́вший", "да́вши", "да́в")
append_imper(forms, "да́й", nil, "", "те")
append_pres_futr(forms, "", nil,
"да́м", "да́шь", "да́ст", "дади́м", "дади́те", "даду́т")
prepend_prefix(forms, prefix)
set_past_by_stress(forms, data.past_stress, prefix, nil, "да́", nil,
args, data)
if data.ppp then
if prefix == "пере" then
set_ppp(forms, "", nil, "пе́реданный")
elseif prefix == "раз" then
set_ppp(forms, "", nil, "ро́зданный")
else
set_moving_ppp(forms, data)
end
end
return forms
end
conjugations["irreg-есть"] = function(args, data)
-- irregular, only for verbs derived from есть
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2),
{"е́сть", "ѣ́сть"})
data.title = com.is_stressed(prefix) and "irreg-a" or "irreg-b"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "е́сть"
append_participles_2stem(forms, "ед", nil, "е́", nil,
"я́щий", "о́мый", "я́", "вший", "вши", "в")
if data.ppp then
set_ppp(forms, "е́д", nil, "енный")
end
append_imper(forms, "е́шь", nil, "", "те")
append_pres_futr(forms, "е́", nil,
"м", "шь", "ст", "ди́м", "ди́те", "дя́т")
set_past(forms, "е́л", nil, "", "а", "о", "и")
if data.old then
rsub_forms(forms, "^е", "ѣ")
end
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-ѣсть"] = conjugations["irreg-есть"]
conjugations["irreg-сыпать"] = function(args, data)
-- irregular, only for verbs derived from сыпать
local forms = {}
--for this type, it's important to distinguish if it's reflexive for вы́сыпаться vs. вы́сыпать imperative
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "сы́пать")
data.title = "6a"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "сы́пать"
append_participles(forms, "сы́п", nil,
"лющий", "лемый", {"ля", "я" .. IRREG}, "авший", "авши", "ав")
append_imper(forms, "сы́п", nil,
-- вы́сыпать (but not вы́сыпаться) has two imperative singulars
com.is_stressed(prefix) and not data.refl and {"и", "ь"} or "ь", "ьте", IRREG)
present_je(forms, "сы́пл", nil, "a")
append_pres_futr(forms, "сы́п", nil,
{}, "ешь", "ет", "ем", "ете", {}, IRREG)
set_past(forms, "сы́пал", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
set_moving_ppp(forms, data)
return forms
end
conjugations["irreg-лгать"] = function(args, data)
-- irregular, only for verbs derived from лгать with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "лга́ть")
data.title = "6°b/c"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "лга́ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, "лг", nil,
"у́щий", "-", "-", "а́вший", "а́вши", "а́в")
append_imper(forms, "лги́", nil, "", "те")
append_pres_futr(forms, "", nil,
"лгу́", "лжёшь" .. IRREG, "лжёт" .. IRREG, "лжём" .. IRREG, "лжёте" .. IRREG, "лгу́т")
set_past(forms, "лга́л", nil, "", "а́", "о", "и")
prepend_prefix(forms, prefix)
set_moving_ppp(forms, data)
return forms
end
conjugations["irreg-мочь"] = function(args, data)
-- irregular, only for verbs derived from мочь with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "мо́чь")
data.title = "8c/b"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "мо́чь"
-- no passive or adverbial participles
append_participles(forms, "мо́г", nil,
"у́щий", "-", "-", "ший", "-", "-")
append_imper(forms, "моги́", nil, "", "те")
append_pres_futr(forms, "", nil,
"могу́", "мо́жешь", "мо́жет", "мо́жем", "мо́жете", "мо́гут")
set_past(forms, "мо́г", nil, "", "ла́", "ло́", "ли́")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-идти"] = function(args, data)
-- irregular, only for verbs derived from идти, including прийти́ and в́ыйти
local forms = {}
local prefix = args[2] == "идти́" and "" or
split_known_main_verb(get_stressed_arg(args, 2), "йти́")
data.title = com.is_stressed(prefix) and "irreg-a" or "irreg-b/b"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
-- no pres_pasv_part
if prefix == "" then
-- only идти, present imperfective
forms["infinitive"] = "идти́"
append_imper(forms, "иди́", nil, "", "те")
present_e_b(forms, "ид")
-- no past_adv_part_short
append_participles(forms, "", nil,
"иду́щий", "-", "идя́", "ше́дший", "ше́дши", "-")
elseif rfind(prefix, "и$") then -- при
forms["infinitive"] = "йти́"
append_imper(forms, "ди́", nil, "", "те")
present_e_b(forms, "д")
append_participles(forms, "", nil,
"-", "-", "-", "ше́дший", "ше́дши", "дя́")
else
forms["infinitive"] = "йти́"
append_imper(forms, "йди́", nil, "", "те")
present_e_b(forms, "йд")
append_participles(forms, "", nil,
"-", "-", "-", "ше́дший", "ше́дши", "йдя́")
end
set_past(forms, "", nil, "шёл", "шла́", "шло́", "шли́")
prepend_prefix(forms, prefix)
if data.ppp then
if prefix == "на" or prefix == "про" then
-- найти́ and пройти́ exceptionally have the stress on the prefix
set_ppp(forms, prefix, nil, "́йденный")
else
-- вы́йти and прийти́ are intransitive so we don't have to worry about them
set_ppp(forms, prefix, nil, "йдённый")
end
end
return forms
end
conjugations["irreg-йти"] = conjugations["irreg-идти"]
conjugations["irreg-ехать"] = function(args, data)
-- irregular, only for verbs derived from ехать
local forms = {}
local old = data.old
local prefix = split_known_main_verb(get_stressed_arg(args, 2),
{"е́хать", "ѣ́хать"})
data.title = "irreg-a"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "е́хать"
-- no pres_pasv_part
-- no pres_adv_part
append_participles_2stem(forms, "е́д", nil, "е́х", nil,
"ущий", "-", "-", "авший", "авши", "ав")
present_e_a(forms, "е́д")
set_past(forms, "е́хал", nil, "", "а", "о", "и")
if data.old then
rsub_forms(forms, "^е", "ѣ")
end
prepend_prefix(forms, prefix)
--special-case the imperative
--literary (special) imperative forms for ехать are поезжа́й, поезжа́йте
impstem = data.old and "ѣзжа́й" or "езжа́й"
if prefix == "" then
append_imper(forms, "по" .. impstem, nil, "", "те")
append_imper(forms, impstem, nil, "", "те")
elseif com.is_stressed(prefix) then
append_imper(forms, com.make_unstressed_once(prefix) .. impstem, nil, "", "те")
else
append_imper(forms, prefix .. impstem, nil, "", "те")
end
return forms
end
conjugations["irreg-ѣхать"] = conjugations["irreg-ехать"]
conjugations["irreg-минуть"] = function(args, data)
-- for the irregular verb "мину́ть"
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "мину́ть")
data.title = "3c"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "мину́ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, "ми́н", nil,
"у́щий", "-", "-", "у́вший", "у́вши", "у́в")
present_e_c(forms, "ми́н")
forms["pres_futr_1sg"] = "-" -- no futr 1sg
-- no imperative
-- two possible variants, one with root-only stress, the other with
-- either root or suffix stress.
if not args["root_past_stress"] then
append_past(forms, "мину́л", nil, "", "а", "о", "и")
end
append_past(forms, "ми́нул", nil, "", "а", "о", "и", IRREG)
prepend_prefix(forms, prefix)
set_moving_ppp(forms, data)
return forms
end
conjugations["irreg-живописать"] = function(args, data)
-- for irregular verb "живописа́ть", mixture of types 1 and 2
local forms = {}
local inf = get_stressed_arg(args, 2)
data.title = "1a"
parse_variants(data, args[1], {"+p"})
local inf_stem = nom.strip_ending(inf, nil, "ть")
local pres_stem = rfind(inf_stem, "а́$") and rsub(inf_stem, "а́$", "у́")
or error("Unexpected infinitive " .. inf)
no_stray_args(args, 2)
forms["infinitive"] = inf_stem .. "ть"
-- no pres_pasv_part
append_participles_2stem(forms, pres_stem, nil, inf_stem, nil,
"ющий", "-", "я", "вший", "вши", "в", IRREG)
set_moving_ppp(forms, data)
present_je(forms, pres_stem, nil, "a", nil, IRREG)
append_imper(forms, pres_stem .. "й", nil, "", "те", IRREG)
set_past(forms, inf_stem .. "л", nil, "", "а", "о", "и")
return forms
end
conjugations["irreg-лечь"] = function(args, data)
-- irregular, only for verbs derived from лечь with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "ле́чь")
data.title = "8a/b"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "ле́чь"
-- no pres parts because always perfective
-- no past_adv_part_short
append_participles(forms, "лёг", nil,
"-", "-", "-", "ший", "ши", "-")
append_imper(forms, "ля́г", nil, "", "те", IRREG)
append_pres_futr(forms, "ля́", nil,
"гу", "жешь", "жет", "жем", "жете", "гут", IRREG)
set_past(forms, "", nil, "лёг", "легла́", "легло́", "легли́")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-честь"] = function(args, data)
-- irregular, only for verbs derived from идти, including прийти́ and в́ыйти
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "че́сть")
local pre_two_cons_prefix =
prefix == "об" and "обо" or
prefix == "с" and "со" or
prefix == "рас" and "разо" or
prefix
data.title = prefix == "" and "7b/b" or com.is_stressed(prefix) and "7a⑨" or
pre_two_cons_prefix ~= prefix and "7*b/b⑨" or "7b/b⑨"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
-- no pres_pasv_part
forms["infinitive"] = "че́сть"
append_imper(forms, "чти́", nil, "", "те", IRREG)
present_e_b(forms, "чт", nil, IRREG)
if prefix == "" then
append_participles(forms, "", nil,
"чту́щий", "-", "чтя́", "чти́вший", "чти́вши", "чти́в", IRREG)
elseif com.is_stressed(prefix) then
append_participles(forms, "", nil,
"-", "-", "-", "-", "чтя́", "-", IRREG)
else
append_participles(forms, "", nil,
"-", "-", "-", "-", {"чтя́" .. IRREG, "чётши*"}, "-")
ut.insert_if_not(data.internal_notes, "* Dated.")
end
if data.ppp then
set_ppp(forms, "", nil, "чтённый" .. IRREG)
end
set_past(forms, "", nil, "чёл", "чла́" .. IRREG, "чло́" .. IRREG, "чли́" .. IRREG)
prepend_prefix(forms, prefix, pre_two_cons_prefix)
return forms
end
conjugations["irreg-зиждить"] = function(args, data)
-- irregular, only for verbs derived from зиждить(ся) with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "зи́ждить")
data.title = "irreg-a"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "зи́ждить"
append_participles(forms, "зи́жд", nil,
"ущий", "емый", "я", "ивший", "ивши", "ив")
if data.ppp then
set_ppp(forms, "зи́жд", nil, "енный")
end
append_imper(forms, "зи́жди", nil, "", "те")
present_e_a(forms, "зи́жд")
set_past(forms, "зи́ждил", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-зыбить"] = function(args, data)
-- irregular, only for verbs derived from зыбить
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "зы́бить")
data.title = "irreg-a"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "зы́бить"
append_participles(forms, "зы́б", nil,
"лющий", "лемый", "ля", "ивший", "ивши", "ив")
append_imper(forms, "зы́бли", nil, "", "те")
present_je(forms, "зы́б", nil, "a")
set_past(forms, "зы́бил", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-клясть"] = function(args, data)
-- irregular, only for verbs derived from клясть with the same stress pattern
local forms = {}
--for this type, it's important to distinguish if it's reflexive to set some stress patterns
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "кля́сть")
data.title = "irreg-b"
parse_variants(data, args[1], {"past", "+p"})
no_stray_args(args, 2)
forms["infinitive"] = "кля́сть"
append_participles_2stem(forms, "клян", nil, "кля́", nil,
"у́щий", "и́мый", "я́", "вший", "вши", "в")
append_imper(forms, "кляни́", nil, "", "те")
present_e_b(forms, "клян")
prepend_prefix(forms, prefix)
set_past_by_stress(forms, data.past_stress, prefix, nil, "кля́", nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["irreg-стелить"] = function(args, data)
-- irregular, only for verbs derived from стелить
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "стели́ть")
data.title = com.is_stressed(prefix) and "4a" or "4c"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "стели́ть"
append_participles(forms, "сте́л", nil,
"ющий" .. IRREG, "и́мый", "я́", "и́вший", "и́вши", "и́в")
set_class_4_ppp(forms, data, "сте́л", nil, data.title)
append_imper(forms, "стели́", nil, "", "те")
append_pres_futr(forms, "сте́л", nil, "ю́", {}, {}, {}, {}, {})
append_pres_futr(forms, "сте́л", nil, {}, "ешь", "ет", "ем", "ете", "ют", IRREG)
set_past(forms, "стели́л", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-быть"] = function(args, data)
-- irregular, only for verbs derived from быть with various stress patterns, the actual verb быть different from its derivatives
local forms = {}
--for this type, it's important to distinguish if it's reflexive to set some stress patterns
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "бы́ть")
data.title = "irreg-a"
parse_variants(data, args[1], {"past", "+p"})
no_stray_args(args, 2)
forms["infinitive"] = "бы́ть"
-- no pres_pasv_part
append_participles(forms, "", nil, "су́щий", "-", "бу́дучи",
"бы́вший", "бы́вши", "бы́в")
append_imper(forms, "бу́дь", nil, "", "те")
prepend_prefix(forms, prefix)
-- only for "бы́ть", some forms are archaic
if forms["infinitive"] == "бы́ть" then
append_pres_futr(forms, "", nil, "есть", "есть", "есть", "есть", "есть", "есть")
elseif com.is_stressed(prefix) then
-- if the prefix is stressed, e.g. "вы́быть"
present_e_a(forms, prefix .. "буд")
else
present_e_a(forms, prefix .. "бу́д")
end
set_past_by_stress(forms, data.past_stress, prefix, nil, "бы́", nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["irreg-ссать-сцать"] = function(args, data)
-- irregular, only for verbs derived from ссать and сцать (both vulgar!)
local forms = {}
local prefix, _, stem = split_known_main_verb(get_stressed_arg(args, 2),
{"сса́ть", "сца́ть"})
data.title = com.is_stressed(prefix) and "irreg-a" or "irreg-b"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
stem = nom.strip_ending(stem, nil, "ть")
local pres_stem = rsub(stem, "а́?$", "")
no_stray_args(args, 2)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, pres_stem, nil, "у́щий", "-", "-",
"а́вший", "а́вши", "а́в")
append_imper(forms, pres_stem, nil, "ы́", "ы́те")
append_pres_futr(forms, pres_stem, nil,
"у́", "ы́шь", "ы́т", "ы́м", "ы́те", "у́т")
set_past(forms, stem .. "л", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-ссать"] = conjugations["irreg-ссать-сцать"]
conjugations["irreg-сцать"] = conjugations["irreg-ссать-сцать"]
conjugations["irreg-чтить"] = function(args, data)
-- irregular, only for verbs derived from чтить
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "чти́ть")
data.title = "4b"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "чти́ть"
append_participles_2stem(forms, "чт", nil, "чти́", nil,
{"я́щий", "у́щий" .. IRREG}, "и́мый", "я́", "вший", "вши", "в")
if data.ppp then
set_ppp(forms, "чт", nil, "ённый")
end
append_imper(forms, "чти́", nil, "", "те")
append_pres_futr(forms, "чт", nil,
"у́" .. IRREG, "и́шь", "и́т", "и́м", "и́те", {"я́т", "у́т" .. IRREG})
set_past(forms, "чти́л", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-шибить"] = function(args, data)
-- irregular, only for verbs in -шибить(ся)
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "шиби́ть")
data.title = com.is_stressed(prefix) and "irreg-a" or "irreg-b"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
-- no present participles
forms["infinitive"] = "шиби́ть"
append_participles(forms, "шиби́", nil,
"-", "-", "-", "вший", "вши", "в")
if data.ppp then
set_ppp(forms, "ши́бл", nil, "енный")
end
append_imper(forms, "шиби́", nil, "", "те")
present_e_b(forms, "шиб")
set_past(forms, "ши́б", nil, "", "ла", "ло", "ли")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-реветь"] = function(args, data)
-- irregular, only for verbs derived from "реветь"
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "реве́ть")
data.title = "irreg-b"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "реве́ть"
-- no pres_pasv_part
append_participles_2stem(forms, "рев", nil, "реве́", nil,
"у́щий", "-", "я́", "вший", "вши", "в")
present_e_b(forms, "рев")
append_imper(forms, "реви́", nil, "", "те")
set_past(forms, "реве́л", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-имать"] = function(args, data)
-- irregular, only for внимать and certain archaic verbs (e.g. имать as
-- conjugated in the 18th century, отъимать)
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "има́ть")
data.title = "1a // 6a"
data.cat_conj_types = {"1a", "6a"}
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "има́ть"
-- handle внемл- forms
append_participles(forms, "е́мл", nil,
"ющий", "емый", {"я", "я́"}, {}, {}, {})
-- handle внима́- forms
append_participles(forms, "има́", nil,
"ющий", "емый", "я", "вший", "вши", "в")
if data.ppp then
-- FIXME, do class-1a-type ppp's (e.g. вни́манный) exist?
-- ruwikt marks them with a *
set_ppp(forms, "е́мл", nil, "енный")
end
append_imper(forms, "", nil, {"е́мли", "емли́", "има́й"},
{"е́млите", "емли́те", "има́йте"})
present_je(forms, "е́мл", nil, "a")
-- Both вне́млю and внемлю́ are possible
append_pres_futr(forms, "емл", nil, "ю́", {}, {}, {}, {}, {})
present_je(forms, "има́", nil, "a")
set_past(forms, "има́л", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-внять"] = function(args, data)
-- irregular, only for внять
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "вня́ть")
data.title = "14c/c"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "вня́ть"
-- perfective only; no present participles
append_participles(forms, "вня́", nil,
"-", "-", "-", "вший", "вши", "в")
append_imper(forms, "вними́", nil, "", "те")
append_imper(forms, "вонми́", nil, "", "те")
present_e_c(forms, "вни́м")
present_e_c(forms, "во́нм")
set_past(forms, "вня́л", nil, "", "а́", "о", "и")
set_ppp_from_past_m(forms, args, data)
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-обязывать"] = function(args, data)
-- irregular, only for обязывать and обязываться
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "обя́зывать")
data.title = "1a"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "обя́зывать"
append_participles_2stem(forms, "обя́з", nil, "обя́зыва", nil,
{"ывающий", "у́ющий"}, {"ываемый", "у́емый"}, {"ывая", "у́я"}, "вший", "вши", "в")
append_imper(forms, "обя́зывай", nil, "", "те")
append_imper(forms, "обязу́й", nil, "", "те")
present_je(forms, "обя́зыва", nil, "a")
present_je(forms, "обязу́", nil, "a")
set_past(forms, "обя́зывал", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
--[=[
Partial conjugation functions
]=]
-- Present forms with -e-, no j-vowels.
present_e_a = function(forms, stem, tr, note)
append_pres_futr(forms, stem, tr, "у", "ешь", "ет", "ем", "ете", "ут", note)
end
present_e_b = function(forms, stem, tr, note)
append_pres_futr(forms, stem, tr, "у́", "ёшь", "ёт", "ём", "ёте", "у́т", note)
end
present_e_c = function(forms, stem, tr, note)
append_pres_futr(forms, stem, tr, "у́", "ешь", "ет", "ем", "ете", "ут", note)
end
-- Present forms with -e- and iotated stem. ABC = "a", "b" or "c", indicating
-- the accent pattern. If SHCH is set, iotate final т as щ, not ч. If NOTE
-- is given, add it to each form.
present_je = function(forms, stem, tr, abc, shch, note)
local iotated_stem, iotated_tr = com.iotation(stem, tr, shch)
assert(abc == "a" or abc == "b" or abc == "c")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(iotated_stem, "[шщжч]$") -- or no_iotation
local ending_1sg =
hushing and (abc == "a" and "у" or "у́") or
not hushing and (abc == "a" and "ю" or "ю́")
if abc == "b" then
append_pres_futr(forms, iotated_stem, iotated_tr,
{}, "ёшь", "ёт", "ём", "ёте", (hushing and "у́т" or "ю́т"), note)
else
append_pres_futr(forms, iotated_stem, iotated_tr,
{}, "ешь", "ет", "ем", "ете", (hushing and "ут" or "ют"), note)
end
append_pres_futr(forms, iotated_stem, iotated_tr,
ending_1sg, {}, {}, {}, {}, {}, note)
end
-- Present forms with -i- (and iotated stem in the 1sg). ABC = "a", "b" or "c",
-- indicating the accent pattern. If SHCH is set, iotate final т as щ, not ч.
-- If NOTE is given, add it to each form.
present_i = function(forms, stem, tr, abc, shch, note)
local iotated_stem, iotated_tr = com.iotation(stem, tr, shch)
assert(abc == "a" or abc == "b" or abc == "c")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local iotated_hushing = rfind(iotated_stem, "[шщжч]$")
local hushing = rfind(stem, "[шщжч]$")
local ending_1sg =
iotated_hushing and (abc == "a" and "у" or "у́") or
not iotated_hushing and (abc == "a" and "ю" or "ю́")
if abc == "b" then
append_pres_futr(forms, stem, tr,
{}, "и́шь", "и́т", "и́м", "и́те", hushing and "а́т" or "я́т", note)
else
append_pres_futr(forms, stem, tr,
{}, "ишь", "ит", "им", "ите", hushing and "ат" or "ят", note)
end
append_pres_futr(forms, iotated_stem, iotated_tr,
ending_1sg, {}, {}, {}, {}, {}, note)
end
-- Add the reflexive particle to all verb forms
make_reflexive = function(forms, reflex_stress)
for key, form in pairs(forms) do
local ru, tr = extract_russian_tr(form)
-- check for empty string, dashes and nil's
if ru and ru ~= "" and ru ~= "-" then
local ruentry, runotes = m_table_tools.separate_notes(ru)
local trentry, trnotes
if tr then
trentry, trnotes = m_table_tools.separate_notes(tr)
end
if is_vowel_stem(ruentry) then
forms[key] = {ruentry .. "сь" .. runotes, trentry and trentry .. "sʹ" .. trnotes}
-- if a past_m form doesn't contain a stress, add a stressed
-- particle "ся́" if called for
elseif reflex_stress and com.is_unstressed(ruentry) and rfind(key, "^past_m") then
forms[key] = {ruentry .. "ся́" .. runotes, trentry and trentry .. "sja" .. AC .. trnotes}
else
forms[key] = {ruentry .. "ся" .. runotes, trentry and trentry .. "sja" .. trnotes}
end
end
end
end
-- Convert verb forms to pre-reform style by adding ъ to consonant-final
-- forms (excluding those ending in й and ь) and converting -ий to -ій and
-- -ийся to -ійся
make_pre_reform = function(forms)
for key, form in pairs(forms) do
local ru, tr = extract_russian_tr(form)
-- check for empty string, dashes and nil's
if ru and ru ~= "" and ru ~= "-" then
local ruentry, runotes = m_table_tools.separate_notes(ru)
if rfind(ruentry, "[бцдфгчклмнпрствшхзжщ]$") then
forms[key] = {ruentry .. "ъ" .. runotes, tr}
else
forms[key] = {rsub(rsub(ruentry, "ий$", "ій"), "ийся$", "ійся") .. runotes, tr}
end
end
end
end
local function setup_pres_futr(forms, perf, old)
-- Copy the main form FROMFORM to the main form TOFORM, and copy all
-- associated alternative forms.
local function copy_form(fromform, toform)
local fromforms = main_to_all_verb_forms[fromform]
local toforms = main_to_all_verb_forms[toform]
local numforms = #fromforms
assert(#toforms == numforms)
for i=1,numforms do
forms[toforms[i]] = forms[fromforms[i]]
end
end
-- Copy pres_futr_* to pres_* (imperfective) or futr_* (perfective).
if perf then
copy_form("pres_futr_1sg", "futr_1sg")
copy_form("pres_futr_2sg", "futr_2sg")
copy_form("pres_futr_3sg", "futr_3sg")
copy_form("pres_futr_1pl", "futr_1pl")
copy_form("pres_futr_2pl", "futr_2pl")
copy_form("pres_futr_3pl", "futr_3pl")
else
copy_form("pres_futr_1sg", "pres_1sg")
copy_form("pres_futr_2sg", "pres_2sg")
copy_form("pres_futr_3sg", "pres_3sg")
copy_form("pres_futr_1pl", "pres_1pl")
copy_form("pres_futr_2pl", "pres_2pl")
copy_form("pres_futr_3pl", "pres_3pl")
end
local futr_data = {
{"futr_1sg", "бу́ду", "búdu"},
{"futr_2sg", "бу́дешь", "búdešʹ"},
{"futr_3sg", "бу́дет" .. (old and "ъ" or ""), "búdet"},
{"futr_1pl", "бу́дем" .. (old and "ъ" or ""), "búdem"},
{"futr_2pl", "бу́дете", "búdete"},
{"futr_3pl", "бу́дут" .. (old and "ъ" or ""), "búdut"}
}
local function insert_future(inf, inf_tr)
for _, fut in ipairs(futr_data) do
append_to_arg_chain(forms, fut[1], fut[1],
{fut[2] .. inf, inf_tr and fut[3] .. inf_tr})
end
end
-- Insert future, if required (there may conceivably be multiple infitives).
for _, form in ipairs(main_to_all_verb_forms["infinitive"]) do
local infinitive = forms[form]
if infinitive then
local inf, inf_tr = extract_russian_tr(forms[form])
-- only for "бы́ть" the future forms are бу́ду, бу́дешь, etc.
if inf == "бы́ть" then
insert_future("", nil)
elseif not perf then
insert_future(" " .. inf, inf_tr and " " .. inf_tr)
end
end
end
end
parse_and_stress_override = function(form, val, existing, all_existing)
if rfind(form, "^pres_futr") then
error("Overrides of pres_futr* are illegal, use pres_* or futr_*")
end
local allow_unaccented
val, allow_unaccented = rsubb(val, "^%*", "")
local ru, tr = nom.split_russian_tr(val)
-- past_m can be unaccented in connection with reflex_stress=ся́
if not allow_unaccented and not rfind(form, "^past_m") then
if tr and com.is_unstressed(ru) ~= com.is_unstressed(tr) then
error("Override " .. form .. "=" .. ru .. " and translit " .. tr .. " must have same accent pattern")
end
if com.is_monosyllabic(ru) then
ru, tr = com.make_ending_stressed(ru, tr)
elseif com.needs_accents(ru) then
error("Override " .. form .. "=" .. ru .. " requires an accent")
end
end
if rfind(ru, "%+") then
-- If either the existing or override has manual translit, the resulting
-- form should have manual translit. We specify ALWAYS_TRANSLIT if
-- the override has manual translit, so that we can substitute the
-- existing translit into the override translit.
local existing_ru, existing_tr = extract_russian_tr(existing, not not tr)
-- used especially for present participles; substitute existing form,
-- minus any "awkward-" or "none-" prefixes.
ru = rsub(ru, "%+", strip_arg_status_prefix(existing_ru))
-- If there's existing translit but not in the override, make sure it's
-- carried along.
if existing_tr and not tr then
tr = com.translit(ru)
end
tr = tr and rsub(tr, "%+", strip_arg_status_prefix(existing_tr))
end
-- If there's an override and it doesn't match an existing form, it's
-- irregular and indicate it using the IRREG marker. We don't do this if
-- the override simply removes a form. We do do this if there aren't any
-- existing forms, on the theory that the presence of a form when none is
-- normally called for is an irregularity. When comparing against the
-- existing forms, strip any status prefix (e.g. 'awkward-').
if all_existing then
local all_existing_stripped = {}
for _, ae in ipairs(all_existing) do
local existing_ru, existing_tr = extract_russian_tr(ae)
existing_ru = strip_arg_status_prefix(existing_ru)
existing_tr = existing_tr and strip_arg_status_prefix(existing_tr)
table.insert(all_existing_stripped, {existing_ru, existing_tr})
end
if ru ~= "-" and not contains_form(all_existing_stripped, {ru, tr}) then
ru = ru .. IRREG
tr = tr and tr .. IRREG
end
end
return {ru, tr}
end
-- Set up pres_* or futr_*; handle *sym/*tail/*tailall notes and overrides.
handle_forms_and_overrides = function(args, forms, data)
setup_pres_futr(forms, data.perf, data.old)
local function append_value(forms, prop, value)
if forms[prop] and forms[prop] ~= "" and forms[prop] ~= "-" then
value = nom.split_russian_tr(value, "dopair")
local curval = forms[prop]
if type(curval) == "string" then
curval = {curval}
end
forms[prop] = nom.concat_paired_russian_tr(curval, value)
end
end
local function append_note_all(forms, proplist, value)
for _, prop in ipairs(proplist) do
append_value(forms, prop, value)
end
end
local function append_note_last(forms, proplist, value, gt_one)
local numprops = 0
local lastprop
-- Find the last property in the series with a value
for _, prop in ipairs(proplist) do
if forms[prop] and forms[prop] ~= "" and forms[prop] ~= "-" then
numprops = numprops + 1
lastprop = prop
end
end
if numprops > (gt_one and 1 or 0) then
append_value(forms, lastprop, value)
end
end
for _, proplist in ipairs(all_verb_forms) do
local vallist = {}
-- Handle PROP_sym, which applies to all overridable properties, including
-- alternative forms, and applies to exactly that property.
for _, prop in ipairs(proplist) do
if args[prop .. "_sym"] then
append_value(forms, prop, args[prop .. "_sym"])
end
end
local propname = proplist[1]
-- Handle PROP_tail, which applies to a series of properties (e.g. past_m,
-- past_m2, ...) and appends to the last one.
if args[propname .. "_tail"] then
append_note_last(forms, proplist, args[propname .. "_tail"])
end
-- Handle PROP_tailall, which applies to a series of properties and
-- appends to all.
if args[propname .. "_tailall"] then
append_note_all(forms, proplist, args[propname .. "_tailall"])
end
end
-- Now handle pasttail, pasttailall, prestail, prestailall, etc.
-- Table listing tail-arg prefix and corresponding verb forms.
local tailargs = {
{"past", past_verb_forms},
{"pres", pres_verb_forms},
{"futr", futr_verb_forms},
{"impr", impr_verb_forms},
{"part", part_verb_forms},
{"prespart", pres_part_verb_forms},
{"pastpart", past_part_verb_forms},
{"", all_main_verb_forms}
}
for _, tailspec in ipairs(tailargs) do
tailforms = tailspec[2]
-- Handle the ...tail variants.
tailarg = tailspec[1] .. "tail"
if args[tailarg] then
track(tailarg)
for _, prop in ipairs(tailforms) do
append_note_last(forms, main_to_all_verb_forms[prop], args[tailarg], ">1")
end
end
-- Handle the ...tailall variants.
tailallarg = tailspec[1] .. "tailall"
if args[tailallarg] then
track(tailallarg)
for _, prop in ipairs(tailforms) do
append_note_all(forms, main_to_all_verb_forms[prop], args[tailallarg])
end
end
end
--handle overrides (formerly we only had past_pasv_part as a
--general override, plus scattered main-form overrides in particular
--conjugation classes)
for _, all_forms in pairs(main_to_all_verb_forms) do
local i = 0
local orig_forms = {}
for _, form in ipairs(all_forms) do
if forms[form] then
table.insert(orig_forms, forms[form])
end
end
for _, form in ipairs(all_forms) do
i = i + 1
-- If we auto-generated the past passive participle in order to
-- check for irregular overrides, make sure to erase any such
-- participles that weren't overridden. This happens for example
-- in обнять, where there are two automatically generated past
-- passive participles but a single ppp=о́внятый override.
local override = args[form] or (
data.ppp_auto_generated and rfind(form, "^past_pasv_part") and "-"
)
if override then
forms[form] = parse_and_stress_override(form, override,
forms[form], orig_forms)
elseif i == 1 then
forms[form] = forms[form] or ""
end
end
end
end
-- Finish generating the forms; primarily, clear out unused forms.
finish_generating_forms = function(forms, data)
-- Convert any main form that's nil (meaning no forms at all corresponding
-- to this main form) to the empty string.
for main_form, _ in pairs(main_to_all_verb_forms) do
if not forms[main_form] then
forms[main_form] = ""
end
end
-- Set the main form FORM to the empty string, and corresponding alt forms
-- to nil.
local function clear_form(form)
local i = 0
for _, altform in ipairs(main_to_all_verb_forms[form]) do
i = i + 1
if i == 1 then
forms[altform] = ""
else
forms[altform] = nil
end
end
end
-- Intransitive and reflexive verbs have no passive participles
-- (unless has_prpp=y and/or has_ppp=y).
if data.intr or data.refl then
if not data.has_prpp then
clear_form("pres_pasv_part")
end
if not data.has_ppp then
clear_form("past_pasv_part")
end
end
if data.refl then
-- no past_adv_part_short for reflexive verbs
clear_form("past_adv_part_short")
end
-- Impersonal verbs normally have no passive participles, but allow them
-- if there's specifically an override. We only do this for the present
-- passive participle because the past passive participle isn't inserted
-- by default, and we still want +p to work, which doesn't currently set
-- data.ppp_override.
if data.impers and not data.prpp_override then
clear_form("pres_pasv_part")
end
if data.impers then
clear_form("pres_1sg")
clear_form("pres_2sg")
clear_form("pres_1pl")
clear_form("pres_2pl")
clear_form("pres_3pl")
clear_form("futr_1sg")
clear_form("futr_2sg")
clear_form("futr_1pl")
clear_form("futr_2pl")
clear_form("futr_3pl")
clear_form("past_m")
clear_form("past_f")
clear_form("past_pl")
clear_form("past_m_short")
clear_form("past_f_short")
clear_form("past_pl_short")
clear_form("pres_actv_part")
clear_form("past_actv_part")
clear_form("pres_adv_part")
clear_form("past_adv_part")
clear_form("past_adv_part_short")
clear_form("impr_sg")
clear_form("impr_pl")
end
-- Perfective and iterative verbs have no present forms, as well as
-- verbs marked nopres=1.
if data.perf or data.iter or data.nopres then
clear_form("pres_actv_part")
clear_form("pres_pasv_part")
clear_form("pres_adv_part")
clear_form("pres_1sg")
clear_form("pres_2sg")
clear_form("pres_3sg")
clear_form("pres_1pl")
clear_form("pres_2pl")
clear_form("pres_3pl")
end
-- Some verbs (e.g. грясти́, густи́) have no past
if data.nopast then
clear_form("past_m")
clear_form("past_f")
clear_form("past_n")
clear_form("past_pl")
clear_form("past_m_short")
clear_form("past_f_short")
clear_form("past_n_short")
clear_form("past_pl_short")
clear_form("past_actv_part")
clear_form("past_pasv_part")
clear_form("past_adv_part")
clear_form("past_adv_part_short")
end
-- Iterative verbs and verbs marked noimpr=1 have no imperative forms.
if data.iter or data.noimpr then
clear_form("impr_sg")
clear_form("impr_pl")
end
-- Iterative verbs and verbs marked nofutr=1 have no future forms.
if data.iter or data.nofutr then
clear_form("futr_1sg")
clear_form("futr_2sg")
clear_form("futr_3sg")
clear_form("futr_1pl")
clear_form("futr_2pl")
clear_form("futr_3pl")
end
--handle "none-" and "awkward-" prefixes (used especially for pres_pasv_part)
local footnote_sym = nil
for _, all_forms in pairs(main_to_all_verb_forms) do
local i = 0
for _, form in ipairs(all_forms) do
i = i + 1
if forms[form] then
local formru, formtr = extract_russian_tr(forms[form])
if rfind(formru, "^none%-") then
if i == 1 then
forms[form] = ""
else
forms[form] = nil
end
elseif rfind(formru, "^awkward%-") then
if not footnote_sym then
footnote_sym = next_note_symbol(data)
ut.insert_if_not(data.internal_notes, footnote_sym .. " Rare and awkward.")
end
forms[form] = {rsub(formru, "^awkward%-", "") .. footnote_sym,
formtr and rsub(formtr, "^awkward%-", "") .. footnote_sym}
end
end
end
end
--Insert footnote for IRREG symbol if present.
for _, all_forms in pairs(main_to_all_verb_forms) do
for _, form in ipairs(all_forms) do
if forms[form] then
local formru, formtr = extract_russian_tr(forms[form])
if rfind(formru, IRREG) then
ut.insert_if_not(data.internal_notes, IRREG .. " Irregular.")
end
end
end
end
end
local accel_forms = {
-- present tense
pres_1sg = "1|s|pres|ind",
pres_2sg = "2|s|pres|ind",
pres_3sg = "3|s|pres|ind",
pres_1pl = "1|p|pres|ind",
pres_2pl = "2|p|pres|ind",
pres_3pl = "3|p|pres|ind",
-- future tense
futr_1sg = "1|s|fut|ind",
futr_2sg = "2|s|fut|ind",
futr_3sg = "3|s|fut|ind",
futr_1pl = "1|p|fut|ind",
futr_2pl = "2|p|fut|ind",
futr_3pl = "3|p|fut|ind",
-- imperative
impr_sg = "2|s|imp",
impr_pl = "2|p|imp",
-- past
past_m = "m|s|past|ind",
past_f = "f|s|past|ind",
past_n = "n|s|past|ind",
past_pl = "p|past|ind",
past_m_short = "short|m|s|past|ind",
past_f_short = "short|f|s|past|ind",
past_n_short = "short|n|s|past|ind",
past_pl_short = "short|p|past|ind",
-- active participles
pres_actv_part = "pres|act|part",
past_actv_part = "past|act|part",
-- passive participles
pres_pasv_part = "pres|pass|part",
past_pasv_part = "past|pass|part",
-- adverbial participles
pres_adv_part = "pres|adv|part",
past_adv_part = "past|adv|part",
past_adv_part_short = "short|past|adv|part",
-- infinitive
infinitive = "inf",
}
-- Make the table
make_table = function(forms, title, perf, intr, impers, notes, internal_notes, old)
local infinitives = {}
for _, form in ipairs(main_to_all_verb_forms["infinitive"]) do
local infinitive = forms[form]
if infinitive then
local inf, inf_tr = extract_russian_tr(forms[form])
if inf ~= "-" then
ut.insert_if_not(infinitives, inf)
end
end
end
-- Group forms together for a given key and combine adjacent forms with the same
-- Russian (they should always have different translits). Take care not to introduce
-- manual translit unnecessarily.
local grouped_forms = {}
for dispform, sourceforms in pairs(disp_verb_form_map) do
local entry = {}
for _, form in ipairs(sourceforms) do
local ru, tr = extract_russian_tr(forms[form])
-- check for empty strings, dashes and nil's
if ru and ru ~= "" and ru ~= "-" and ru ~= "—" then
if #entry > 0 then
local lastru, lasttr = extract_russian_tr(entry[#entry])
if lastru == ru then
if not lasttr and not tr or lasttr == tr then
error("Russian form " .. ru .. " is duplicated, probably due to a duplicative override")
end
lasttr = lasttr or com.translit(lastru)
tr = tr or com.translit(ru)
entry[#entry] = {ru, lasttr .. " ''or'' " .. tr}
else
table.insert(entry, {ru, tr})
end
else
table.insert(entry, {ru, tr})
end
end
end
grouped_forms[dispform] = entry
end
local title = (old and "Pre-reform conjugation" or "Conjugation") .. (#infinitives == 0 and "" or
" of <span lang=\"ru\" class=\"Cyrl\">''" .. table.concat(infinitives, ", ") .. "''</span>") ..
(title and " (" .. title .. ")" or "")
local function add_links(ru, rusuf, runotes, tr, trnotes, accel)
local ruspan
if old then
ruspan = m_links.full_link({lang = lang, term = com.remove_jo(ru), accel = accel,
alt = not ru:find("[[", 1, true) and ru, tr = "-"})
else
ruspan = m_links.full_link({lang = lang, term = ru, accel = accel, tr = "-"})
end
if rusuf ~= "" then
rusuf = "<span lang=\"ru\" class=\"Cyrl\">" .. rusuf .. "</span>"
end
return ruspan .. rusuf .. runotes .. "<br/>" .. require("Module:script utilities").tag_translit(tr .. trnotes, lang, "default", 'style="color: #888"')
end
-- NOTE: No need to check for multiple infinitives because the accel system
-- doesn't support multiple lemmas.
local lemma, lemmatr = extract_russian_tr(forms["infinitive"])
-- check for empty strings, dashes and nil's
if lemma and lemma ~= "" and lemma ~= "-" and lemma ~= "—" then
lemma, _ = m_table_tools.separate_notes(lemma)
if lemmatr then
lemmatr, _ = m_table_tools.separate_notes(lemmatr)
end
else
-- In case the lemma is an empty string or dash, set to nil so we don't
-- set a lemma in the accelerator and fall back to the page name.
lemma = nil
lemmatr = nil
end
-- Convert to displayed form
local disp = {}
for key, entry in pairs(grouped_forms) do
for i, form in ipairs(entry) do
local ru, origtr = extract_russian_tr(form)
local tr = origtr or ru and com.translit(ru)
local ruentry, runotes = m_table_tools.get_notes(ru)
local trentry, trnotes = m_table_tools.get_notes(tr)
local accel_form = accel_forms[key]
if not accel_form then
error("Unrecognized key " .. key .. " when looking up accelerator form")
end
local accel
if origtr and origtr:find(" ''or'' ") then
-- Multiple translits for a given Russian term.
-- FIXME! Support this.
accel = nil
else
accel = { form = accel_form, translit = origtr,
lemma = lemma, lemma_translit = lemmatr}
end
if rfind(key, "^futr") then
-- Add link to first word (form of 'to be')
tobe, inf = rmatch(ruentry, "^([^ ]*) ([^ ]*)$")
if tobe then
-- No accelerators for imperfective future, as it's just the future of "to be"
-- plus the infinitive.
entry[i] = add_links(tobe, " " .. inf, runotes, trentry, trnotes, nil)
else
entry[i] = add_links(ruentry, "", runotes, trentry, trnotes, accel)
end
else
entry[i] = add_links(ruentry, "", runotes, trentry, trnotes, accel)
end
end
disp[key] = table.concat(entry, ",<br/>")
if disp[key] == "" then
disp[key] = "—"
end
end
local all_notes = {}
for _, note in ipairs(internal_notes) do
local symbol, entry = m_table_tools.get_initial_notes(note)
table.insert(all_notes, symbol .. entry)
end
for _, note in ipairs(notes) do
local symbol, entry = m_table_tools.get_initial_notes(note)
table.insert(all_notes, symbol .. entry)
end
local notes_text
table.insert(all_notes, 1,
"Note: For declension of participles, see their entries. Adverbial participles are indeclinable.")
notes_text = table.concat(all_notes, "<br />") .. "\n"
return require("Module:TemplateStyles")("Module:ru-verb/style.css") ..
[=[<div class="NavFrame" style="width:49.6em;">
<div class="NavHead" style="text-align:left; background:#e0e0ff;">]=] .. title .. [=[</div>
<div class="NavContent">
{| class="inflection inflection-ru inflection-verb inflection-table"
|+ ]=] .. notes_text .. [=[
|- class="rowgroup"
! colspan="3" | ]=] .. (perf and [=[[[совершенный вид|perfective aspect]]]=] or [=[[[несовершенный вид|imperfective aspect]]]=]) .. [=[
|-
! [[неопределённая форма|infinitive]]
| colspan="2" | ]=] .. disp.infinitive .. [=[
|- class="rowgroup"
! style="width:15em" | [[причастие|participles]]
! [[настоящее время|present tense]]
! [[прошедшее время|past tense]]
|-
! [[действительный залог|active]]
| ]=] .. disp.pres_actv_part .. [=[ || ]=] .. disp.past_actv_part .. [=[
|-
! [[страдательный залог|passive]]
| ]=] .. disp.pres_pasv_part .. [=[ || ]=] .. disp.past_pasv_part .. [=[
|-
! [[деепричастие|adverbial]]
| ]=] .. disp.pres_adv_part .. [=[ || ]=] .. disp.past_adv_part .. [=[
|- class="rowgroup"
!
! [[настоящее время|present tense]]
! [[будущее время|future tense]]
|-
! [[первое лицо|1st]] [[единственное число|singular]] (<span lang="ru" class="Cyrl">я</span>)
| ]=] .. disp.pres_1sg .. [=[ || ]=] .. disp.futr_1sg .. [=[
|-
! [[второе лицо|2nd]] [[единственное число|singular]] (<span lang="ru" class="Cyrl">ты</span>)
| ]=] .. disp.pres_2sg .. [=[ || ]=] .. disp.futr_2sg .. [=[
|-
! [[третье лицо|3rd]] [[единственное число|singular]] (<span lang="ru" class="Cyrl">он/она́/оно́</span>)
| ]=] .. disp.pres_3sg .. [=[ || ]=] .. disp.futr_3sg .. [=[
|-
! [[первое лицо|1st]] [[множественное число|plural]] (<span lang="ru" class="Cyrl">мы</span>)
| ]=] .. disp.pres_1pl .. [=[ || ]=] .. disp.futr_1pl .. [=[
|-
! [[второе лицо|2nd]] [[множественное число|plural]] (<span lang="ru" class="Cyrl">вы</span>)
| ]=] .. disp.pres_2pl .. [=[ || ]=] .. disp.futr_2pl .. [=[
|-
! [[третье лицо|3rd]] [[множественное число|plural]] (<span lang="ru" class="Cyrl">они́</span>)
| ]=] .. disp.pres_3pl .. [=[ || ]=] .. disp.futr_3pl .. [=[
|- class="rowgroup"
! [[повелительное наклонение|imperative]]
! [[единственное число|singular]]
! [[множественное число|plural]]
|-
!
| ]=] .. disp.impr_sg .. [=[ || ]=] .. disp.impr_pl .. [=[
|- class="rowgroup"
! [[прошедшее время|past tense]]
! [[единственное число|singular]]
! [[множественное число|plural]]<br/>(<span lang="ru" class="Cyrl">мы/вы/они́</span>)
|-
! [[мужской род|masculine]] (<span lang="ru" class="Cyrl">я/ты/он</span>)
| ]=] .. disp.past_m .. [=[ || rowspan="3" | ]=] .. disp.past_pl .. [=[
|-
! [[женский род|feminine]] (<span lang="ru" class="Cyrl">я/ты/она́</span>)
| ]=] .. disp.past_f .. [=[
|-
! style="background-color: #ffffe0;" | [[средний род|neuter]] (<span lang="ru" class="Cyrl">оно́</span>)
| ]=] .. disp.past_n .. [=[
|}
</div>
</div>]=]
end
return export
-- For Vim, so we get 4-space tabs
-- vim: set ts=4 sw=4 noet:
ptwcky15mzc4m5e6h6mjj09guntacnb
5672502
5672500
2026-06-29T15:19:40Z
MustafaCavlak
59368
5672502
Scribunto
text/plain
--[=[
This module contains functions for creating inflection tables for Russian
verbs.
Author: Benwing, rewritten from early version by Atitarev, earliest version by CodeCat
NOTE: This module is partly converted to support manual translit, in the
form CYRILLIC//LATIN (i.e. with a // separating the Cyrillic and Latin
parts). All the general infrastructure supports manual translit; the
only thing that doesn't is some of the specific verb conjugation functions.
In particular, all of the class 1, 2, 3 and 4 conjugation functions support
manual translit, and the rest don't. To convert another, follow the
model of one of the already-converted functions.
Note that an individual form (an entry in the 'forms' table) can be
either a string (no special manual translit; generally this originates
from the portion of the code that doesn't support manual translit), or
a one-element list {CYRILLIC} (no special manual translit), or a
two-element list {CYRILLIC, LATIN} with manual translit specified.
The code is careful only to generate manual translit when it's needed,
to avoid penalizing the majority of cases where manual transit isn't
needed.
]=]
local m_utilities = require("Modül:araçlar")
local ut = require("Module:utils")
local m_links = require("Modül:bağlantılar")
local com = require("Modül:ru-genel")
local nom = require("Modül:ru-nominal")
local m_debug = require("Modül:debug")
local m_table_tools = require("Modül:table tools")
-- If enabled, compare this module with new version of module to make
-- sure all conjugations are the same.
local test_new_ru_verb_module = false
local export = {}
-- Within this module, conjugations are the functions that do the actual
-- conjugating by creating the forms of a basic verb.
-- They are defined further down.
local conjugations = {}
local lang = require("Modül:diller").getirKodaGore("ru")
local u = mw.ustring.char
local rfind = mw.ustring.find
local rsubn = mw.ustring.gsub
local rmatch = mw.ustring.match
local rsplit = mw.text.split
local usub = mw.ustring.sub
local AC = u(0x0301) -- acute = ́
local DIA = u(0x0308) -- diaeresis = ̈
local PSEUDOCONS = u(0xFFF2) -- pseudoconsonant placeholder, matching ru-common
local IRREG = "△"
-- version of rsubn() that discards all but the first return value
local function rsub(term, foo, bar)
local retval = rsubn(term, foo, bar)
return retval
end
-- version of rsubn() that returns a 2nd argument boolean indicating whether
-- a substitution was made.
local function rsubb(term, foo, bar)
local retval, nsubs = rsubn(term, foo, bar)
return retval, nsubs > 0
end
-- Fancy version of ine() (if-not-empty). Converts empty string to nil,
-- but also strips leading/trailing space and then single or double quotes,
-- to allow for embedded spaces.
local function ine(arg)
if not arg then return nil end
arg = rsub(arg, "^%s*(.-)%s*$", "%1")
if arg == "" then return nil end
local inside_quotes = rmatch(arg, '^"(.*)"$')
if inside_quotes then
return inside_quotes
end
inside_quotes = rmatch(arg, "^'(.*)'$")
if inside_quotes then
return inside_quotes
end
return arg
end
local function is_vowel_stem(stem)
return rfind(stem, "[" .. com.vowel .. AC .. DIA .. "]$")
end
-- Return the next number to use as an internal note symbol, starting at 1.
-- We look at existing internal notes to see if the symbol is already used.
local function next_note_symbol(data)
local nextsym = 1
while true do
local sym_already_seen = false
for _, note in ipairs(data.internal_notes) do
if rfind(note, "^" .. nextsym .. " ") then
sym_already_seen = true
break
end
end
if sym_already_seen then
nextsym = nextsym + 1
else
break
end
end
return nextsym
end
-- FIXME: Move to utils
-- Iterate over a chain of parameters, FIRST then PREF2, PREF3, ...,
-- inserting into LIST (newly created if omitted). Return LIST.
local function get_arg_chain(args, first, pref, list)
if not list then
list = {}
end
local val = args[first]
local i = 2
while val do
table.insert(list, val)
val = args[pref .. i]
i = i + 1
end
return list
end
-- FIXME: Move to utils
-- Set a chain of parameters, FIRST then PREF2, PREF3, ..., from LIST.
local function set_arg_chain(args, first, pref, list)
local param = first
local i = 2
for _, val in ipairs(list) do
args[param] = val
param = pref .. i
i = i + 1
end
end
-- For a given form in a conjugation table, we allow either strings or
-- two-element lists {RUSSIAN, TRANSLIT}, where TRANSLIT can be nil
-- (equivalent to a one-element list). When comparing them, we have to take
-- this into account.
local function forms_equal(form1, form2)
if type(form1) ~= "table" then
form1 = {form1}
end
if type(form2) ~= "table" then
form2 = {form2}
end
return ut.equals(form1, form2)
end
local function contains_form(forms, form)
for _, f in ipairs(forms) do
if forms_equal(f, form) then
return true
end
end
return false
end
-- FIXME: Move to utils
-- Append to the end of a chain of parameters, FIRST then PREF2, PREF3, ...,
-- if the value isn't already present.
local function append_to_arg_chain(args, first, pref, newval)
local nextarg = first
local i = 2
if newval == "" then
error("Internal error: attempt to insert blank value into arg chain")
end
while true do
if not args[nextarg] then break end
if forms_equal(args[nextarg], newval) then
return nil
end
nextarg = pref .. i
i = i + 1
end
args[nextarg] = newval
return nextarg
end
local function get_true_arg(arg, not_off_by_1)
-- We normally move all params down by one because the first param is the
-- verb type; so reflect this correctly if the arg is numeric and
-- not_off_by_1 isn't given
return (not_off_by_1 or type(arg) ~= "number") and arg or arg + 1
end
local function getarg(args, arg, default, paramdesc, not_off_by_1)
paramdesc = paramdesc or "Parameter " .. get_true_arg(arg, not_off_by_1)
default = default or "-"
--PAGENAME = mw.loadData("Modül:başlık başı/veri").pagename
local NAMESPACE = mw.title.getCurrentTitle().nsText
return args[arg] or (NAMESPACE == "Template" and default) or error(paramdesc .. " has not been provided")
end
local function check_stressed_arg(val, arg)
-- don't consider suffixes
if not rfind(val, "^%-") and not com.is_nonsyllabic(val) and not com.is_stressed(val) then
error("Argument value " .. val .. " (parameter " .. get_true_arg(arg) .. ") must be stressed")
end
return val
end
local function get_stressed_arg(args, arg, default, paramdesc)
local retval = getarg(args, arg, default, paramdesc)
check_stressed_arg(retval, arg)
return retval
end
local function get_opt_stressed_arg(args, arg)
return args[arg] and get_stressed_arg(args, arg) or nil
end
local function check_unstressed_arg(val, arg)
if com.is_stressed(val) then
error("Argument value " .. val .. " (parameter " .. get_true_arg(arg) .. ") should not be stressed")
end
return val
end
local function get_unstressed_arg(args, arg, default, paramdesc)
local retval = getarg(args, arg, default, paramdesc)
check_unstressed_arg(retval, arg)
return retval
end
local function get_opt_unstressed_arg(args, arg)
return args[arg] and get_unstressed_arg(args, arg) or nil
end
local function no_stray_args(args, maxarg)
for i=(maxarg + 1), 20 do
if args[i] then
error("Value for argument " .. get_true_arg(i) .. " not allowed ("
.. args[i] .. " supplied)")
end
end
end
-- Extract a form spec (either a single string or a two-element table {RU, TR}
-- into the component Russian and transliterated components. Normally, if
-- an explicit manual translit wasn't given, the resulting translit will be
-- nil; but if ALWAYS_TRANSLIT is given, it will be auto-transliterated from
-- the Russian as needed.
local function extract_russian_tr(form, always_translit)
local ru, tr
if type(form) == "table" then
ru, tr = form[1], form[2]
else
ru = form
end
if not tr and always_translit then
tr = ru and com.translit(ru)
end
return ru, tr
end
local function strip_arg_status_prefix(arg)
if not arg then
return arg, ""
end
local subbed
arg, subbed = rsubb(arg, "^awkward%-", "")
if subbed then
return arg, "awkward-"
end
arg, subbed = rsubb(arg, "^none%-", "")
if subbed then
return arg, "none-"
end
return arg, ""
end
local function track(page)
m_debug.track("ru-verb/" .. page)
return true
end
-- Forward functions
local present_e_a
local present_e_b
local present_e_c
local present_je
local present_i
local make_reflexive
local make_pre_reform
local parse_and_stress_override
local handle_forms_and_overrides
local finish_generating_forms
local make_table
local all_verb_types = {
"pf", "pf-intr", "pf-refl",
"pf-impers", "pf-intr-impers", "pf-refl-impers",
"impf", "impf-intr", "impf-refl",
"impf-impers", "impf-intr-impers", "impf-refl-impers"}
-- Examples of alternatives in use:
-- past_m2: со́здал/созда́л, пе́редал/переда́л, о́тдал/отда́л, при́нялся/принялся́
-- past_m3: for verbs with three past masculine sg forms: за́нялся, заня́лся, занялс́я (заня́ться)
-- past_n2: да́ло, дал́о; вз́яло, взяло́
-- past_pl2: разобрали́сь (разобрали́)
-- past_m_short: short forms in 3a (исчез, сох, etc.)
-- past_f_short: short forms in 3a (исчезла, сохла, etc.)
-- past_n_short: short forms in 3a (исчезло, сохло, etc.)
-- past_pl_short: short forms in 3a (исчезли, сохли, etc.)
-- past_adv_parts:
-- тереть: тере́вши, тёрши, short: тере́в
-- умереть: умере́вши, у́мерши, short: умере́в
-- pres_adv_part: сыпля, сыпя, лёжа (лежать)
-- pres_2sg2: сыплешь, сыпешь
-- pres_3sg2: сыплет, сыпет
-- pres_1pl2: сыплем, сыпем
-- pres_2pl2: сыплете, сыпете
-- pres_3pl2: сыплют, сыпют
-- futr_2sg2: насыплешь, насыпешь
-- futr_3sg2: насыплет, насыпет
-- futr_1pl2: насыплем, насыпем
-- futr_2pl2: насыплете, насыпете
-- futr_3pl2: насыплют, насыпют
-- List of all main verb forms. Short forms (those ending in "_short")
-- must be listed after the corresponding non-short forms.
local all_main_verb_forms = {
-- present tense
"pres_1sg", "pres_2sg", "pres_3sg", "pres_1pl", "pres_2pl", "pres_3pl",
-- future tense
"futr_1sg", "futr_2sg", "futr_3sg", "futr_1pl", "futr_2pl", "futr_3pl",
-- present-future tense. The conjugation functions generate the
-- "present-future" tense instead of either the present or future tense,
-- since the same forms are used in the present imperfect and future
-- perfect. These forms are later copied into the present or future in
-- finish_generating_forms().
"pres_futr_1sg", "pres_futr_2sg", "pres_futr_3sg", "pres_futr_1pl", "pres_futr_2pl", "pres_futr_3pl",
-- imperative
"impr_sg", "impr_pl",
-- past
"past_m", "past_f", "past_n", "past_pl",
"past_m_short", "past_f_short", "past_n_short", "past_pl_short",
-- active participles
"pres_actv_part", "past_actv_part",
-- passive participles
"pres_pasv_part", "past_pasv_part",
-- adverbial participles
"pres_adv_part", "past_adv_part", "past_adv_part_short",
-- infinitive
"infinitive"
}
-- List of all verb forms. Each element is a list, where the first element
-- is the "main" form and the remainder are alternatives. The following
-- *MUST* hold:
-- 1. Forms must be given in the order they will appear in the outputted
-- table.
-- 2. Short forms (those ending in "_short") must be listed after the
-- corresponding non-short forms.
-- 3. For each person, e.g. '2sg', there must be the same number of
-- futr_PERSON, pres_PERSON and pres_futr_PERSON forms, and the alternative
-- forms must be listed in the same order.
--
-- FIXME!!! We should fix things so we no longer need to compute this table.
local all_verb_forms = {}
-- Compile all_verb_forms
for _, mainform in ipairs(all_main_verb_forms) do
local entry = {}
table.insert(entry, mainform)
for i=2,9 do
table.insert(entry, mainform .. i)
end
table.insert(all_verb_forms, entry)
end
local prop_aliases = {
pap="past_actv_part",
paptail="past_actv_part_tail",
paptailall="past_actv_part_tailall",
ppp="past_pasv_part",
ppptail="past_pasv_part_tail",
ppptailall="past_pasv_part_tailall",
prap="pres_actv_part",
praptail="pres_actv_part_tail",
praptailall="pres_actv_part_tailall",
prpp="pres_pasv_part",
prpptail="pres_pasv_part_tail",
prpptailall="pres_pasv_part_tailall",
padp="past_adv_part",
padptail="past_adv_part_tail",
padptailall="past_adv_part_tailall",
padp_short="past_adv_part_short",
padp_shorttail="past_adv_part_short_tail",
padp_shorttailall="past_adv_part_short_tailall",
pradp="pres_adv_part",
pradptail="pres_adv_part_tail",
pradptailall="pres_adv_part_tailall",
}
-- Table mapping "main" to the list of all forms in the series (e.g.
-- past_m, past_m2, past_m3, etc.). If a main form (e.g. past_m) is missing,
-- it needs to end up with a value of "", whereas the alternatives
-- (e.g. past_m2, past_m3) need to end up with a value of nil.
local main_to_all_verb_forms = {}
-- List of the main verb forms for the past.
local past_verb_forms = {"past_m", "past_f", "past_n", "past_pl"}
-- List of the main verb forms for the present.
local pres_verb_forms = {"pres_1sg", "pres_2sg", "pres_3sg",
"pres_1pl", "pres_2pl", "pres_3pl"}
-- List of the main verb forms for the future.
local futr_verb_forms = {"futr_1sg", "futr_2sg", "futr_3sg",
"futr_1pl", "futr_2pl", "futr_3pl"}
-- List of the main verb forms for the imperative.
local impr_verb_forms = {"impr_sg", "impr_pl"}
-- List of the main verb forms for participles.
local part_verb_forms = {"pres_actv_part", "past_actv_part",
"pres_pasv_part", "past_pasv_part",
"pres_adv_part", "past_adv_part", "past_adv_part_short"}
-- List of the main verb forms for present participles.
local pres_part_verb_forms = {"pres_actv_part", "pres_pasv_part",
"pres_adv_part"}
-- List of the main verb forms for past participles.
local past_part_verb_forms = {"past_actv_part", "past_pasv_part",
"past_adv_part", "past_adv_part_short"}
-- Compile main_to_all_verb_forms.
for _, proplist in ipairs(all_verb_forms) do
main_to_all_verb_forms[proplist[1]] = proplist
end
-- Map listing the forms to be displayed, and the verb forms used to generate
-- the displayed form, in order. For example, under past_m will be found
-- {"past_m_short", "past_m", "past_m2", "past_m3"} because those forms in
-- that order are displayed in the table under "masculine singular past".
local disp_verb_form_map = {}
for _, proplist in ipairs(all_verb_forms) do
local key = proplist[1]
-- if we find short forms, insert them at the beginning of the list for
-- the corresponding full forms. This requires that short forms are
-- listed in all_verb_forms after the corresponding full forms.
if rfind(key, "_short$") then
local full_key = rsub(key, "_short$", "")
-- short forms should occur in list after full forms
assert(#(disp_verb_form_map[full_key]) > 0)
-- build entry for full form, consisting first of the short forms,
-- in order, then the full forms, in order.
local new_entry = {}
for _, form in ipairs(proplist) do
table.insert(new_entry, form)
end
for _, form in ipairs(disp_verb_form_map[full_key]) do
table.insert(new_entry, form)
end
disp_verb_form_map[full_key] = new_entry
elseif rfind(key, "^pres_futr") then
-- skip these forms, not displayed
else
disp_verb_form_map[key] = mw.clone(proplist)
end
end
local all_verb_props = mw.clone(all_verb_forms)
local non_form_props = {"title", "perf", "intr", "impers", "categories", "notes", "internal_notes"}
for _, prop in ipairs(non_form_props) do
table.insert(all_verb_props, {prop})
end
-- Clone parent's args while also assigning nil to empty strings and splitting
-- arg sets (numeric args separated by "or"), assigning named args to
-- all all sets. Handle aliases in the process. Extract conjugation type
-- from the first arg of the arg set (for the initial arg set, this will be
-- arg 2 because arg 1 is the verb type), assigning to '.conj_type' of the
-- arg set. Return arg sets.
local function split_args_handle_aliases(frame)
local args = frame:getParent().args
local arg_sets = {}
local arg_set = {}
-- Verb type, e.g. impf, pf, impf-intr, pf-intr, impf-refl, pf-refl, etc.
-- Default to impf on the template page so that there is no script error.
local verb_type = getarg(args, 1, "impf", "Verb type (first parameter)")
local offset = 1
-- Find maximum-numbered arg, allowing for holes.
local max_arg = 1 -- needs to be 1 not 0 so template pages display ok
for pname, param in pairs(args) do
if type(pname) == "number" and pname > max_arg then
max_arg = pname
end
end
-- Now gather the numbered arguments.
for i=2,(max_arg + 1) do
local end_arg_set = false
if i == max_arg + 1 or args[i] == "or" then
end_arg_set = true
end
if end_arg_set then
table.insert(arg_sets, arg_set)
arg_set = {}
offset = i
else
arg_set[i - offset] = ine(args[i])
end
end
-- Insert named arguments into all arg sets, mapping aliases appropriately.
for pname, param in pairs(args) do
if type(pname) == "string" then
local argval = ine(param)
local mainprop, num = rmatch(pname, "^([a-z_]+)([0-9]*)$")
for i=1,#arg_sets do
if not mainprop then
arg_sets[i][pname] = argval
else
mainprop = prop_aliases[mainprop] or mainprop
arg_sets[i][mainprop .. num] = argval
end
end
end
end
-- If we're conjugating a suffix, insert a pseudoconsonant at the beginning
-- of all forms, so they get conjugated as if ending in a consonant.
-- We remove the pseudoconsonant later.
for i=1,#arg_sets do
asif_prefix = (arg_sets[i]["asif_prefix"] or
arg_sets[i][2] and rfind(arg_sets[i][2], "^%-") and PSEUDOCONS)
if asif_prefix then
for k, v in pairs(arg_sets[i]) do
arg_sets[i][k] = rsub(v, "^%-", "-" .. asif_prefix)
end
end
end
-- Frob conjugation type.
for i=1,#arg_sets do
local arg1 = arg_sets[i][1]
local conj_type
if arg1 then
local orig_arg1 = arg1
-- This complex spec matches matches 3°a, 3oa, 4a1a, 6c1a,
-- 1a6a, 6a1as13, 6a1as14, 11*b, etc.
conj_type = rmatch(arg1, "^([0-9]+[*°o0-9abc]*[abc]s?1?[34]?)")
arg1 = rsub(arg1, "^[0-9]+[*°o0-9abc]*[abc]s?1?[34]?", "")
if not conj_type then
if rfind(arg1, "^irreg") then
conj_type = "irreg"
arg1 = rsub(arg1, "^irreg", "")
end
if not conj_type then
-- Check for Cyrillic, a common mistake (esp. Cyrillic а)
if rfind(orig_arg1, "[абцдеѣфгчийклмнопярстувшхызёюжэщьъ]") then
error("Unrecognized conjugation type (WARNING, has Cyrillic in it): " .. orig_arg1)
else
error("Unrecognized conjugation type: " .. orig_arg1)
end
end
end
-- The * variant is conventionally written e.g. 11*b; if found in
-- the conj_type, move it to the beginning of the remainder
if rfind(conj_type, "%*") then
conj_type = rsub(conj_type, "%*", "")
arg1 = "*" .. arg1
end
arg_sets[i][1] = arg1
else
local NAMESPACE = mw.title.getCurrentTitle().nsText
if NAMESPACE == "Template" and i == 1 then
conj_type = "1a"
else
error("Must specify argument 2 (conjugation type)")
end
end
arg_sets[i]["conj_type"] = conj_type
end
return arg_sets, verb_type
end
function export.do_generate_forms(arg_sets, verb_type, old)
local set1 = arg_sets[1]
local notes = get_arg_chain(set1, "notes", "notes")
local forms = {}
local categories = {}
if not ut.contains(all_verb_types, verb_type) then
error("Invalid verb type " .. verb_type)
end
local data = {}
data.verb_type = verb_type
--impersonal
data.impers = rfind(verb_type, "impers")
data.intr = rfind(verb_type, "intr")
data.perf = rfind(verb_type, "^pf")
data.iter = set1["iter"]
data.nopres = set1["nopres"]
data.nopast = set1["nopast"]
data.nofutr = set1["nofutr"]
data.noimpr = set1["noimpr"]
if data.iter and data.perf then
error("Iterative verbs must be imperfective")
end
data.old = old
data.has_ppp = set1["has_ppp"]
data.has_prpp = set1["has_prpp"]
data.ppp_override = false
data.prpp_override = false
for _, form in ipairs(main_to_all_verb_forms["past_pasv_part"]) do
if set1[form] then
data.ppp_override = true
break
end
end
data.main_ppp_override = not not set1["past_pasv_part"]
for _, form in ipairs(main_to_all_verb_forms["pres_pasv_part"]) do
if set1[form] then
data.prpp_override = true
break
end
end
data.internal_notes = {}
local titles = {}
for i=1,#arg_sets do
local args = arg_sets[i]
local conj_type = args.conj_type
-- Support e.g. 3oa in place of 3°a
conj_type = rsub(conj_type, "o", "°")
track("conj-" .. conj_type) -- FIXME, convert to regular category
track("conj-" .. conj_type .. "/" .. verb_type) -- FIXME, convert to regular category
data.conj_type = conj_type
data.cat_conj_types = {conj_type}
if conj_type == "irreg" then
data.title = "irregular"
else
data.title = conj_type
end
if not conjugations[conj_type] then
error("Unknown conjugation type '" .. conj_type .. "'")
end
if args[2] then
local inf, tr = nom.split_russian_tr(args[2])
if rfind(inf, "[тч]ься$") then
inf = rsub(inf, "ся$", "")
tr = nom.strip_tr_ending(tr, "ся")
data.refl = true
elseif rfind(inf, "ти́?сь$") then
-- 7a (вы́вестись), 7b (вести́сь) or derivative of -йти́ (разойти́сь)
inf = rsub(inf, "сь$", "")
tr = nom.strip_tr_ending(tr, "сь")
data.refl = true
elseif rfind(inf, "[тч]ь$") then
-- Allow monosyllabic infinitives to be specified without stress
if com.is_monosyllabic(inf) and not rfind(inf, "^%-") then
inf, tr = com.make_ending_stressed(inf, tr)
end
end
if tr then
args[2] = inf .. "//" .. tr
else
args[2] = inf
end
end
if data.refl and data.intr then
error("Can't specify -intr with reflexive verbs")
end
if data.has_ppp or data.has_prpp then
if data.refl then
error("Can't specify has_ppp=y or has_prpp=y with reflexive verbs")
end
if not data.intr then
error("Can only specify has_ppp=y or has_prpp=y with intransitive verbs")
end
end
data.shouldnt_have_ppp = data.refl or not data.has_ppp and data.intr
data.shouldnt_have_prpp = data.refl or not data.has_prpp and data.intr
if data.ppp_override and data.shouldnt_have_ppp then
error("Shouldn't specify past passive participle with reflexive or intransitive verbs, if it's needed use has_ppp=y")
elseif data.perf and not data.shouldnt_have_ppp and not data.ppp_override then
-- possible omissions
track("perfective-no-ppp")
end
if data.prpp_override and data.shouldnt_have_prpp then
error("Shouldn't specify present passive participle with reflexive or intransitive verbs, if it's needed use has_prpp=y")
end
-- Call conjugation function. It will return a table of forms
-- as if it's the first arg set. If it is in fact the first
-- arg set, we just use the table directly (we may destructively
-- modify it if there are later arg sets, but this is OK because
-- no one else but us uses the table). Otherwise we need to
-- append the values from the table to those of the previous
-- arg sets.
local arg_set_forms = conjugations[conj_type](args, data)
if i == 1 then
forms = arg_set_forms
else
for _, all_forms in pairs(main_to_all_verb_forms) do
for _, form in ipairs(all_forms) do
if arg_set_forms[form] then
append_to_arg_chain(forms, all_forms[1], all_forms[1],
arg_set_forms[form])
end
end
end
end
ut.insert_if_not(titles, data.title)
if conj_type == "irreg" then
table.insert(categories, "Russian irregular verbs")
end
-- For irregular verbs, if the verb didn't set a specific cat_conj_type,
-- it will be the same as the conj_type and be "irreg". In that case,
-- replace it with the title, which might be a proper conjugation type
-- like 4a or 8c/b (and remove anything starting with a slash, to
-- account for cases like 8c/b). After doing this, the cat_conj_type
-- might still begin with "irreg" (for sufficiently irregular verbs that
-- they can't be assigned to any of the normal classes), in which case
-- we don't create a class for the verb beyond "Russian irregular verbs"
-- (set above).
if data.cat_conj_types[1] == "irreg" then
data.cat_conj_types = {rsub(rsub(data.title, "/.*", ""), "⑨", "")}
end
for _, cat_conj_type in ipairs(data.cat_conj_types) do
if not rmatch(cat_conj_type, "^irreg") then
local class_num = rmatch(cat_conj_type, "^([0-9]+)")
assert(class_num and class_num ~= "")
table.insert(categories, "Russian class " .. class_num .. " verbs")
table.insert(categories, "Russian class " .. cat_conj_type .. " verbs")
end
end
end
data.title = "class " .. table.concat(titles, " // ") ..
(data.perf and " perfective" or " imperfective") ..
(data.refl and " reflexive" or data.intr and " intransitive" or " transitive") ..
(data.impers and " impersonal" or "") ..
(data.iter and " iterative" or "")
-- Perfective/imperfective
if data.perf then
table.insert(categories, "Russian perfective verbs")
else
table.insert(categories, "Russian imperfective verbs")
end
handle_forms_and_overrides(set1, forms, data)
local function remove_pseudo(str)
toremove = set1["asif_prefix"] or PSEUDOCONS
if str == nil then
return str
end
str = rsub(str, "^%-" .. toremove, "-")
-- also handle prefix after space, e.g. in futures
str = rsub(str, " %-" .. toremove, " -")
return str
end
-- Remove pseudoconsonant we may have inserted; if no ending, insert
-- "(no suffix)".
for k, v in pairs(forms) do
if forms[k] == "-" .. PSEUDOCONS or type(forms[k] == "table") and forms[k][1] == "-" .. PSEUDOCONS then
-- Make the translit empty.
forms[k] = {"(no suffix)", ""}
else
if type(forms[k]) == "table" then
forms[k][1] = remove_pseudo(forms[k][1])
forms[k][2] = remove_pseudo(forms[k][2])
else
forms[k] = remove_pseudo(forms[k])
end
end
end
-- Catch errors in verb arguments that lead to the infinitive not matching
-- page title, but only in the main namespace.
local NAMESPACE = mw.title.getCurrentTitle().nsText
if NAMESPACE == "" then
local PAGENAME = mw.loadData("Modül:başlık başı/veri").pagename
for _, form in ipairs(main_to_all_verb_forms["infinitive"]) do
local inf, inf_tr = extract_russian_tr(forms[form])
if inf then
inf, _ = m_table_tools.separate_notes(inf) -- remove any footnote symbols (e.g. грясти́)
local inf_noaccent = com.remove_accents(inf)
if inf ~= "-" then
if data.refl then
if rfind(inf_noaccent, "и$") then
inf_noaccent = inf_noaccent .. "сь"
inf = inf .. "сь"
else
inf_noaccent = inf_noaccent .. "ся"
inf = inf .. "ся"
end
end
if inf_noaccent ~= PAGENAME then
error("Infinitive " .. inf .. " doesn't match pagename " ..
PAGENAME)
end
end
end
end
end
-- Reflexive/intransitive/transitive
if set1["reflex_stress"] then
track("reflex-stress")
end
if data.refl then
local reflex_stress = set1["reflex_stress"] or data.default_reflex_stress -- "ся́"
make_reflexive(forms, reflex_stress and reflex_stress ~= "n" and
reflex_stress ~= "no")
table.insert(categories, "Russian reflexive verbs")
elseif data.intr then
table.insert(categories, "Russian intransitive verbs")
else
table.insert(categories, "Russian transitive verbs")
end
-- Impersonal
if data.impers then
table.insert(categories, "Russian impersonal verbs")
end
-- Iterative
if data.iter then
table.insert(categories, "Russian iterative verbs")
end
if data.old then
make_pre_reform(forms)
end
finish_generating_forms(forms, data)
return forms, data.title, data.perf, data.intr or data.refl, data.impers, categories, notes, data.internal_notes
end
local function fetch_forms(forms)
local function fetch_one_form(form)
local val = forms[form]
local ru, tr
if type(val) == "table" then
ru, tr = val[1], val[2]
elseif type(val) == "string" and val ~= "" and val ~= "-" then
ru = val
end
if not ru then
return nil
end
local ruentry, runotes = m_table_tools.get_notes(ru)
local trentry, trnotes
if tr then
trentry, trnotes = m_table_tools.get_notes(tr)
end
-- There shouldn't be any links.
-- ruentry = m_links.remove_links(ruentry)
-- There shouldn't be any vertical bars.
-- ruentry = rsub(ruentry, "|", "<!>")
-- if trentry then
-- trentry = rsub(trentry, "|", "<!>")
-- end
return trentry and ruentry .. "//" .. trentry or ruentry
end
local vals = {}
for _, proplist in ipairs(all_verb_forms) do
local vallist = {}
local propname = proplist[1]
if not rfind(propname, "^pres_futr") then
for _, prop in ipairs(proplist) do
local val = fetch_one_form(prop)
if val then
table.insert(vallist, val)
end
end
if #vallist > 0 then
table.insert(vals, propname .. "=" .. table.concat(vallist, ","))
end
end
end
return table.concat(vals, "|")
end
function export.generate_forms(frame)
local arg_sets, verb_type = split_args_handle_aliases(frame)
local old = frame.args["old"] or arg_sets[1]["old"]
local forms, title, perf, intr, impers, categories, notes, internal_notes = export.do_generate_forms(arg_sets, verb_type, old)
return fetch_forms(forms)
end
local function concat_vals(val)
if type(val) == "table" then
return table.concat(val, ",")
else
return val
end
end
-- The main entry point.
-- This is the only function that can be invoked from a template.
function export.show(frame)
local arg_sets, verb_type = split_args_handle_aliases(frame)
local old = frame.args["old"] or arg_sets[1]["old"]
local arg_sets_clone
if test_new_ru_verb_module then
-- arg_sets may be modified by do_generate_forms()
arg_sets_clone = mw.clone(arg_sets)
end
local forms, title, perf, intr, impers, categories, notes, internal_notes =
export.do_generate_forms(arg_sets, verb_type, old)
-- Test code to compare existing module to new one.
if test_new_ru_verb_module then
local m_new_ru_verb = require("Modül:User:Benwing2/ru-verb")
local newforms, newtitle, newperf, newintr, newimpers, newcategories, newnotes, newinternal_notes =
m_new_ru_verb.do_generate_forms(arg_sets_clone, verb_type, old)
local vals = mw.clone(forms)
vals.title = title
vals.perf = perf
vals.intr = intr
vals.impers = impers
vals.categories = categories
vals.notes = notes
vals.internal_notes = internal_notes
local newvals = mw.clone(newforms)
newvals.title = newtitle
newvals.perf = newperf
newvals.intr = newintr
newvals.impers = newimpers
newvals.categories = newcategories
newvals.notes = newnotes
newvals.internal_notes = newinternal_notes
local difconj = false
for _, proplist in ipairs(all_verb_props) do
for _, prop in ipairs(proplist) do
local val = vals[prop]
local newval = newvals[prop]
-- deal with impedance mismatch between old style (plain string)
-- and new style (Russian/translit array), and empty string vs. nil
if not ut.contains(non_form_props, prop) then
if type(val) == "string" then val = {val} end
if val and val[1] == "" then val = nil end
if type(newval) == "string" then newval = {newval} end
if newval and newval[1] == "" then newval = nil end
end
-- Ignore changes in pres_futr_*, which aren't displayed
if not forms_equal(val, newval) and not rfind(prop, "^pres_futr") then
-- Uncomment this to display the particular case and
-- differing forms.
--error(prop .. " " .. (val and concat_vals(val) or "nil") .. " || " .. (newval and concat_vals(newval) or "nil"))
difconj = true
break
end
end
end
track(difconj and "different-conj" or "same-conj")
end
return make_table(forms, title, perf, intr, impers, notes, internal_notes, old) .. m_utilities.format_categories(categories, lang)
end
-- Implementation of template 'ru-verb cat'.
function export.catboiler(frame)
local SUBPAGENAME = mw.loadData("Modül:başlık başı/veri").pagename
local cats = {}
local cls, variant, pattern = rmatch(SUBPAGENAME, "^Russian class ([0-9]*)(°?)([abc]?) verbs")
local text = nil
if not cls then
error("Invalid category name, should be e.g. \"Russian class 3a verbs\"")
end
if pattern == "" then
table.insert(cats, "Russian verbs by class|" .. cls .. variant)
text = "This category contains Russian class " .. cls .. " verbs."
else
table.insert(cats, "Russian verbs by class and accent pattern|" .. cls .. pattern)
table.insert(cats, "Russian class " .. cls .. " verbs|" .. pattern)
text = "This category contains Russian class " .. cls .. " verbs of " ..
"accent pattern " .. pattern .. (
variant == "" and "" or " and variant " .. variant) .. ". " .. (
pattern == "a" and "With this pattern, all forms are stem-stressed."
or pattern == "b" and "With this pattern, all forms are ending-stressed."
or "With this pattern, the first singular present indicative and all forms " ..
"outside of the present indicative are ending-stressed, while the remaining " ..
"forms of the present indicative are stem-stressed.").. (
variant == "" and "" or
cls == "3" and " The variant code indicates that the -н of the stem " ..
"is missing in most non-present-tense forms." or
" The variant code indicates that the present tense is not " ..
"[[Appendix:Glossary#iotation|iotated]]. (In most verbs of this class, " ..
"the present tense is iotated, e.g. иска́ть with present tense " ..
"ищу́, и́щешь, и́щет, etc.)")
end
return text .. "\n" ..
mw.getCurrentFrame():expandTemplate{title="ru-categoryTOC", args={}}
.. m_utilities.format_categories(cats, lang, nil, nil, "force")
end
-- Implementation of poscatboiler handler for Russian verb cats. Loaded from
-- [[Module:category tree/poscatboiler/data/lang-specific]].
function export.poscatboiler_verb_class_handler(cls, variant, pattern)
if pattern == "" then
return {
description = "Russian class " .. cls .. " verbs.",
breadcrumb = cls,
parents = {{name = "verbs by class", sort = cls .. variant}},
}
else
return {
description = "Russian class " .. cls .. " verbs of " ..
"accent pattern " .. pattern .. (
variant == "" and "" or " and variant " .. variant) .. ". " .. (
pattern == "a" and "With this pattern, all forms are stem-stressed."
or pattern == "b" and "With this pattern, all forms are ending-stressed."
or "With this pattern, the first singular present indicative and all forms " ..
"outside of the present indicative are ending-stressed, while the remaining " ..
"forms of the present indicative are stem-stressed.") .. (
variant == "" and "" or
cls == "3" and " The variant code indicates that the -н of the stem " ..
"is missing in most non-present-tense forms." or
" The variant code indicates that the present tense is not " ..
"[[Appendix:Glossary#iotation|iotated]]. (In most verbs of this class, " ..
"the present tense is iotated, e.g. иска́ть with present tense " ..
"ищу́, и́щешь, и́щет, etc.)"),
breadcrumb = cls .. variant .. pattern,
parents = {
{name = "class " .. cls .. " verbs", sort = pattern},
{name = "verbs by class and accent pattern", sort = cls .. pattern},
},
}
end
end
--[=[
Functions for working with stems, paradigms, Russian/translit
]=]
-- Combine a stem with optional translit with an ending and possibly a foonote
-- symbol (which may be a tuple {RUNOTES, TRNOTES}), returning a tuple
-- {RUSSIAN, TR}.
local function combine(stem, tr, ending, note)
if not ending or ending == "-" then
return nil
end
local arg_status
ending, arg_status = strip_arg_status_prefix(ending)
if stem ~= "" and com.is_stressed(ending) then
stem, tr = com.make_unstressed_once(stem, tr)
end
stem = arg_status .. stem
if not note then
return nom.concat_russian_tr(stem, tr, ending, nil, "dopair")
else
local runotes, trnotes = extract_russian_tr(note)
local ruending, trending = nom.concat_russian_tr(ending, nil, runotes, trnotes)
return nom.concat_russian_tr(stem, tr, ruending, trending, "dopair")
end
end
-- Set an individual form PARAM in FORMS with value based on stem STEM (with
-- optional translit TR), ENDINGS (either a single string or a list of strings)
-- and NOTE (nil, a string, or a tuple {RUSSIAN, TR}). If there are multiple
-- endings listed, they will go successively into PARAM, PARAM2, etc.
-- (e.g. past_m, past_m2, etc.).
local function set_form(forms, param, stem, tr, endings, note)
if type(endings) ~= "table" then
endings = {endings}
end
local entries = {}
for _, val in ipairs(endings) do
ut.insert_if_not(entries, combine(stem, tr, val, note))
end
set_arg_chain(forms, param, param, entries)
end
-- Append to an individual form PARAM in FORMS with value based on stem STEM
-- (with optional translit TR), ENDINGS (either a single string or a list of
-- strings) and NOTE (nil, a string, or a tuple {RUSSIAN, TR}). If there are
-- multiple endings listed, they will go successively into PARAM, PARAM2, etc.
-- (e.g. past_m, past_m2, etc.), provided there are no existing forms already
-- present. Duplicate forms aren't inserted.
local function append_form(forms, param, stem, tr, endings, note)
if type(endings) ~= "table" then
endings = {endings}
end
for _, val in ipairs(endings) do
append_to_arg_chain(forms, param, param, combine(stem, tr, val, note))
end
end
local function append_pres_futr(forms, stem, tr,
sg1, sg2, sg3, pl1, pl2, pl3, note)
append_form(forms, "pres_futr_1sg", stem, tr, sg1, note)
append_form(forms, "pres_futr_2sg", stem, tr, sg2, note)
append_form(forms, "pres_futr_3sg", stem, tr, sg3, note)
append_form(forms, "pres_futr_1pl", stem, tr, pl1, note)
append_form(forms, "pres_futr_2pl", stem, tr, pl2, note)
append_form(forms, "pres_futr_3pl", stem, tr, pl3, note)
end
local function append_participles_2stem(forms,
pres_stem, pres_tr, past_stem, past_tr,
pres_actv, pres_pasv, pres_adv, past_actv, past_adv, past_adv_short,
pres_note, past_note)
append_form(forms, "pres_actv_part", pres_stem, pres_tr, pres_actv, pres_note)
append_form(forms, "pres_pasv_part", pres_stem, pres_tr, pres_pasv, pres_note)
append_form(forms, "pres_adv_part", pres_stem, pres_tr, pres_adv, pres_note)
append_form(forms, "past_actv_part", past_stem, past_tr, past_actv, past_note)
append_form(forms, "past_adv_part", past_stem, past_tr, past_adv, past_note)
append_form(forms, "past_adv_part_short", past_stem, past_tr, past_adv_short, past_note)
end
local function append_participles(forms, stem, tr,
pres_actv, pres_pasv, pres_adv, past_actv, past_adv, past_adv_short, note)
append_participles_2stem(forms, stem, tr, stem, tr,
pres_actv, pres_pasv, pres_adv, past_actv, past_adv, past_adv_short, note, note)
end
local function set_ppp(forms, stem, tr, ending, note)
set_form(forms, "past_pasv_part", stem, tr, ending, note)
end
local function append_ppp(forms, stem, tr, ending, note)
append_form(forms, "past_pasv_part", stem, tr, ending, note)
end
local function append_imper(forms, stem, tr, sg, pl, note)
append_form(forms, "impr_sg", stem, tr, sg, note)
append_form(forms, "impr_pl", stem, tr, pl, note)
end
local function set_past(forms, stem, tr, m, f, n, pl, note)
set_form(forms, "past_m", stem, tr, m, note)
set_form(forms, "past_f", stem, tr, f, note)
set_form(forms, "past_n", stem, tr, n, note)
set_form(forms, "past_pl", stem, tr, pl, note)
end
local function append_past(forms, stem, tr, m, f, n, pl, note)
append_form(forms, "past_m", stem, tr, m, note)
append_form(forms, "past_f", stem, tr, f, note)
append_form(forms, "past_n", stem, tr, n, note)
append_form(forms, "past_pl", stem, tr, pl, note)
end
-- Prepend a possibly-stressed prefix to all forms; if prefix is stressed,
-- destress the forms before prepending. FIXME: Should support explicit
-- manual translit.
local function prepend_prefix(forms, prefix, pre_two_cons_prefix)
pre_two_cons_prefix = pre_two_cons_prefix or prefix
local stressed_prefix = com.is_stressed(prefix)
for key, form in pairs(forms) do
local ru, tr = extract_russian_tr(form)
if tr then
error("Explicit manual translit not yet supported")
end
-- check for empty string, dashes and nil's
if ru and ru ~= "" and ru ~= "-" then
if stressed_prefix then
ru = com.make_unstressed(ru)
end
if rfind(ru, "^[" .. com.cons .. "][" .. com.cons .. "]") then
forms[key] = pre_two_cons_prefix .. ru
else
forms[key] = prefix .. ru
end
end
end
end
-- Apply regex substitution FROM -> TO to all forms. FIXME: Should support
-- explicit manual translit.
local function rsub_forms(forms, from, to)
for key, form in pairs(forms) do
local ru, tr = extract_russian_tr(form)
if tr then
error("Explicit manual translit not yet supported")
end
-- check for empty string, dashes and nil's
if ru and ru ~= "" and ru ~= "-" then
forms[key] = rsub(ru, from, to)
end
end
end
local variant_to_title = {
["[(2)]"] = "[②]",
["(2)"] = "②",
["[(3)]"] = "[③]",
["(3)"] = "③",
["[(4)]"] = "[④]",
["(4)"] = "④",
["[(5)]"] = "[⑤]",
["(5)"] = "⑤",
["[(6)]"] = "[⑥]",
["(6)"] = "⑥",
["[(7)]"] = "[⑦]",
["(7)"] = "⑦",
["[(8)]"] = "[⑧]",
["(8)"] = "⑧",
["(9)"] = "⑨",
["щ"] = "(-щ-)",
["ё"] = "(-ё-)",
["о"] = "(-о-)",
["жд"] = "(-жд-)",
}
local function prepare_past_stress_indicator(past_stress)
if not past_stress or past_stress == "a" then
return ""
end
past_stress = rsub(past_stress, "%(1%)", "①")
past_stress = rsub(past_stress, "(.),%1①", "%1[①]")
past_stress = rsub(past_stress, "(.)①,%1", "%1[①]")
past_stress = rsub(past_stress, "''", "''")
past_stress = rsub(past_stress, "-nd", "")
past_stress = rsub(past_stress, "-bd", "")
return "/" .. past_stress
end
local function parse_variants(data, variants, allowed)
-- Need to set these to nil in case of multiple arg sets
data.imper_variant = nil
data.var4 = nil
data.var5 = nil
data.var6 = nil
data.ppp = nil
data.var9 = nil
data.shch = nil
data.yo = nil
data.o = nil
data.zhd = nil
data.star = nil
variants = variants or ""
local variant_title = ""
if variants ~= "" then -- short-circuit the most common case
-- Only recognize * variant for long-variant prefix at the beginning
-- of the variant code block (where it gets moved if it's in the
-- middle of the conjugation type, as it normally is) because a *
-- also occurs in b*, a past stress variant code.
if rfind(variants, "^%*") then
-- Specify that the present/future tense has extra -о in the prefix:
-- types 9*b (e.g. растере́ть, futr_1sg разотру́) and 11*b (e.g. изли́ть,
-- futr_1sg изолью́). It can also occur with type 7*b (in -че́сть,
-- e.g. счесть, сочту́; расче́сть, разочту́) and type 8*b (in -же́чь, e.g.
-- сжечь, сожгу́) but these are always irregular and require the
-- present tense to be specified explicitly. It can also occur
-- with type 14*b (e.g. размя́ть, разомну́; сжать, сожну́; подожа́ть, подожму́),
-- but for these verbs the present tense is unpredictable and
-- must be specified explicitly.
--
-- This can also occur where the extra -о occurs in the infinitive
-- and past, but not the present tense: type 5*c (in -гна́ть, e.g.
-- согна́ть, сгоню́; разогна́ться, разгоню́сь), type 6*c (in -стла́ть, e.g.
-- подостла́ть, подстелю́; разостла́ть, расстелю́), type 6°*c
-- (in -зва́ть, -бра́ть, -дра́ть, e.g. подозва́ть, подзову́; разобра́ться, разберу́сь);
-- but these are always irregular and require the present tense
-- to be specified explicitly.
if not ut.contains(allowed, "*") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.star = true
variants = rsub(variants, "^*", "")
end
-- Allow brackets around both 5 and 6, e.g. [(5)(6)]
variants = rsub(variants, "%[(%([56]%))(%([56]%))%]", "[%1][%2]")
-- Handle all remaining variants. We do this using an rsub() function,
-- where we pull out, parse and remove each variant in turn.
variants = rsub(variants, "(%[?%(?[23456789ёощийьж+][дp]?%)?%]?)", function(var)
if ut.contains({"(2)", "[(2)]", "(3)", "[(3)]", "и", "й", "ь"}, var) then
if data.imper_variant then
error("Saw two imperative variants " .. data.imper_variant ..
" and " .. var)
end
local is_23 = ut.contains({"(2)", "[(2)]", "(3)", "[(3)]"}, var)
if is_23 and not ut.contains(allowed, "23") or
not is_23 and not ut.contains(allowed, "и") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.imper_variant = var
elseif ut.contains({"(4)", "[(4)]"}, var) then
if data.var4 then
error("Saw two variant-4 specs " .. data.var4 .. " and " .. var)
end
if not ut.contains(allowed, "4") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.var4 = var == "(4)" and "req" or "opt"
elseif ut.contains({"(5)", "[(5)]"}, var) then
if data.var5 then
error("Saw two variant-5 specs " .. data.var5 .. " and " .. var)
end
if not ut.contains(allowed, "5") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.var5 = var == "(5)" and "req" or "opt"
elseif ut.contains({"(6)", "[(6)]"}, var) then
if data.var6 then
error("Saw two variant-6 specs " .. data.var6 .. " and " .. var)
end
if not ut.contains(allowed, "6") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.var6 = var == "(6)" and "req" or "opt"
elseif ut.contains({"(7)", "[(7)]", "(8)", "[(8)]", "+p"}, var) then
if data.shouldnt_have_ppp then
error("Shouldn't specify past passive participle with reflexive or intransitive verbs, if it's needed use has_ppp=y")
end
if data.ppp then
error("Saw two past passive participle specs " .. data.ppp .. " and " .. var)
end
if ut.contains({"(7)", "[(7)]"}, var) and not ut.contains(allowed, "7") or
ut.contains({"(8)", "[(8)]"}, var) and not ut.contains(allowed, "8") or
var == "+p" and not ut.contains(allowed, "+p") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.ppp = var
elseif var == "(9)" then
if data.var9 then
error("Saw (9) twice")
end
if not ut.contains(allowed, "9") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.var9 = true
elseif var == "щ" then
-- specify that the 1sg pres/futr and past passive participle
-- of class 4/5/6 verbs iotate -т to -щ instead of -ч; cf.
-- похи́тить (похи́щу) (4a), защити́ть (защищу́) (4b),
-- поглоти́ть (поглощу́) (4c), клевета́ть (клевещу́) (6c)
if data.shch then
error("Saw щ twice")
end
if not ut.contains(allowed, "щ") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.shch = "щ"
elseif var == "ё" then
-- specify that the past passive participle has ё instead of е
if data.yo then
error("Saw ё twice")
end
if not ut.contains(allowed, "ё") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.yo = true
elseif var == "о" then
-- specify that the past passive participle has о instead of е
-- NOTE: Not currently allowed as a user-specifiable variant
if data.o then
error("Saw о twice")
end
if not ut.contains(allowed, "о") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.o = true
elseif var == "жд" then
-- specify that the past passive participle of class 4/5/6 verbs
-- iotates -д to -жд instead of -ж
if data.zhd then
error("Saw жд twice")
end
if not ut.contains(allowed, "жд") then
error("Variant " .. var .. " not allowed for this verb class")
end
data.zhd = true
else
error("Unrecognized variant spec: " .. var)
end
variant_title = variant_title .. (variant_to_title[var] or "")
return ""
end)
variant_title = rsub(variant_title, "%[⑤%]%[⑥%]", "[⑤⑥]")
end
if variants ~= "" and not ut.contains(allowed, "past") then
error("Past stress " .. variants .. " not allowed for this verb class")
end
if data.yo and not data.ppp then
error("Variant ё specified without calling for past passive participle")
end
if data.o and not data.ppp then
error("Variant о specified without calling for past passive participle")
end
if data.zhd and not data.ppp then
error("Variant жд specified without calling for past passive participle")
end
if data.perf and not data.ppp and not data.ppp_override and not data.shouldnt_have_ppp and not data.impers then
error("For perfective transitive verbs, need to specify past passive participle by variant or override; use |ppp=- if no such participle")
end
data.past_stress = variants == "" and "a" or rsub(variants, "/", "")
data.title = data.title ..
prepare_past_stress_indicator(data.past_stress) ..
variant_title
if data.star then
data.title = rsub(data.title, "^([0-9]+°?)", "%1*")
end
-- If there's an override of past_pasv_part, generate the normal participle
-- so we can determine whether the override is irregular. But set a flag
-- so we erase any automatically generated past passive participles that
-- aren't overridden. This happens for example in обнять, where there are
-- two automatically generated past passive participles but a single
-- ppp=о́внятый override.
if not data.ppp and data.main_ppp_override then
data.ppp = "+p"
data.ppp_auto_generated = true
end
end
local function set_past_by_stress(forms, past_stresses, prefix, prefixtr, base,
basetr, args, data, no_pastml, note)
-- If there isn't manual translit for the prefix, we need to supply it
-- if there's manual translit for the base, because we often concatenate
-- prefix to the base.
local prefixtr = prefixtr or basetr and com.translit(prefix)
for _, past_stress in ipairs(rsplit(past_stresses, ",")) do
local pastml = no_pastml and "" or "л"
local stressed_prefixtr
if prefix == "пере" then
stressed_prefix = "пе́ре"
stressed_prefixtr = "pe" .. AC .. "re"
elseif prefix == "раз" then
stressed_prefix = "ро́з"
stressed_prefixtr = "ro" .. AC .. "z"
elseif prefix == "рас" then
-- Does this ever occur?
stressed_prefix = "ро́с"
stressed_prefixtr = "ro" .. AC .. "s"
elseif prefix == "ра" and rfind(base, "^[сз]") then
-- Type 9/11/14/16 with automatically split prefix; may never happen.
stressed_prefix = "ро́"
stressed_prefixtr = "ro" .. AC
else
stressed_prefix, stressed_prefixtr =
com.make_ending_stressed(prefix, prefixtr)
end
-- Normally the base is stressed and the prefix isn't, but it could
-- be the other way around, e.g. in запереть and запереться, where
-- the stress on the prefix is used to get prefix-stressed participles.
-- To deal with this, we usually combine base and prefix unchanged,
-- but in combination with stressed_prefix we always want an unstressed
-- base, and when a stressed -ся́ is called for, we want both of them
-- unstressed.
local ubase, ubasetr = com.make_unstressed(base, basetr)
local uprefix, uprefixtr = com.make_unstressed(prefix, prefixtr)
local prefixbase = prefix .. base
local prefixbasetr = basetr and prefixtr .. basetr
local stressed_prefix_ubase = stressed_prefix .. ubase
local stressed_prefix_ubasetr = ubasetr and stressed_prefixtr .. ubasetr
local uprefixubase = uprefix .. ubase
local uprefixubasetr = ubasetr and uprefixtr .. ubasetr
if past_stress == "a" then
-- (/под/пере/при/по)забы́ть, раздобы́ть, (/пере/по)забы́ться
append_past(forms, prefixbase, prefixbasetr, pastml,
"ла", "ло", "ли", note)
elseif past_stress == "a(1)" then
-- вы́дать, вы́быть, etc.; also проби́ть with the meaning
-- "to strike (of a clock)" (which is a(1),a or similar)
append_past(forms, stressed_prefix_ubase,
stressed_prefix_ubasetr, pastml, "ла", "ло", "ли", note)
elseif past_stress == "b" then
append_past(forms, prefixbase, prefixbasetr, pastml,
"ла́", "ло́", "ли́", note)
elseif past_stress == "b*" then
if not data.refl then
error("Only reflexive verbs can take past stress variant " .. past_stress)
end
-- See comment in type c''. We want to see whether we actually
-- added an argument, and if so, where.
local argset = append_to_arg_chain(forms, "past_m", "past_m",
combine(uprefixubase, uprefixubasetr, pastml .. (note or "")))
if argset and not args[argset] and not data.impers then
data.default_reflex_stress = "ся́"
end
append_past(forms, prefixbase, prefixbasetr, {}, "ла́", "ло́", "ли́", note)
elseif past_stress == "c" then
-- изда́ть, возда́ть, сдать, пересозда́ть, воссозда́ть, надда́ть, наподда́ть, etc.
-- быть, избы́ть, сбыть
-- клясть, закля́сть
append_past(forms, prefixbase, prefixbasetr, pastml, "ла́", "ло", "ли", note)
elseif past_stress == "c(1)" then
-- прибы́ть, убы́ть
-- прокля́сть
-- also, c(1),c:
-- зада́ть, обда́ть, отда́ть, подда́ть, переда́ть (пе́редал), преда́ть, прода́ть, разда́ть (ро́здал), созда́ть, etc.
-- отбы́ть, побы́ть, пробы́ть
-- also, c,c(1):
-- добы́ть
-- Because the prefix may vary depending on stress (esp. for
-- раздать [ро́здал/раздала́]), we need to separate the endings that
-- take the stressed prefix and those that take the unstressed
-- prefix with stressed ending.
append_past(forms, stressed_prefix_ubase, stressed_prefix_ubasetr,
pastml, {}, "ло", "ли", note)
append_past(forms, prefixbase, prefixbasetr, {}, "ла́", {}, {}, note)
elseif past_stress == "c'" then
-- дать
--same with "взять"
append_past(forms, prefixbase, prefixbasetr,
pastml, "ла́", {"ло", "ло́"}, "ли", note)
elseif past_stress == "c''" or past_stress == "c''-nd" or past_stress == "c''-bd" then
if not data.refl then
error("Only reflexive verbs can take past stress variant " .. past_stress)
end
-- c'' (-ся́ dated): all verbs in -да́ться; избы́ться, сбы́ться; all verbs in -кля́сться
-- c''-nd (-ся́ not dated): various verbs in -ня́ться per Zaliznyak
-- c''-bd (-ся́ becoming dated): various verbs in -ня́ться per ruwikt
local note_symbol = past_stress == "c''-nd" and "" or
next_note_symbol(data)
append_past(forms, prefixbase, prefixbasetr,
pastml, "ла́", {"ло́", "ло"}, {"ли́", "ли"})
-- We want to see whether we actually added an argument, and if
-- so, where.
local argset = append_to_arg_chain(forms, "past_m", "past_m",
combine(uprefixubase, uprefixubasetr, pastml .. note_symbol .. (note or "")))
-- Only display the internal note and set the default reflex
-- stress if the form with the note will be displayed (i.e. not
-- impersonal, and no override of this form). FIXME: We should
-- have a more general mechanism to check for this.
if not args[argset] and not data.impers then
ut.insert_if_not(data.internal_notes,
past_stress == "c''" and note_symbol .. " Dated." or
past_stress == "c''-bd" and note_symbol .. " Becoming dated." or nil)
data.default_reflex_stress = "ся́"
end
elseif past_stress == "c''(1)" then
-- запере́ться
-- See comment in type c''. We want to see whether we actually
-- added an argument, and if so, where.
local argset = append_to_arg_chain(forms, "past_m", "past_m",
combine(uprefixubase, uprefixubasetr, pastml .. (note or "")))
if argset and not args[argset] and not data.impers then
data.default_reflex_stress = "ся́"
end
append_past(forms, prefixbase, prefixbasetr, {}, "ла́", "ло́", "ли́", note)
append_past(forms, stressed_prefix_ubase, stressed_prefix_ubasetr,
pastml, {}, "ло", "ли", note)
else
error("Unrecognized past-stress value " .. past_stress .. ", should be a, a(1), b, b*, c, c(1), c', c'', c''-nd, c''-bd, c''(1) or comma-separated list")
end
end
end
-- Split a verb stem into a possibly multisyllabic prefix (пере-, переиз-,
-- воссоз-, повы́-, etc.) and a single-syllable main verb (-тер-, -ли́-, -гре́-,
-- etc.). Normally the splitting is done simply by looking for alternating
-- vowel/consonant sequences, meaning that e.g. разгре́ will be split as
-- ра + згре́ and растер will be split as ра + стер. For most purposes, this
-- doesn't matter, but for the * variant it does; in that case, if it is
-- known that the main verb base always begins with a single consonant,
-- specify SINGLE_CONS_BASE and then e.g. растер will be split as рас + тер.
local function split_monosyllabic_main_verb(ru, tr, single_cons_base)
local rusyl, trsyl = com.split_syllables(ru, tr)
local last_ru = rusyl[#rusyl]
local last_tr = trsyl and trsyl[#trsyl]
table.remove(rusyl, #rusyl)
local prefix_ru = table.concat(rusyl, "")
local prefix_tr
if trsyl then
table.remove(trsyl, #trsyl)
prefix_tr = table.concat(trsyl, "")
end
if single_cons_base then
local cons_to_move, rest = rmatch(last_ru, "^([" .. com.cons .. "]+)([" .. com.cons .. "].*)$")
if cons_to_move then
prefix_ru = prefix_ru .. cons_to_move
last_ru = rest
end
if last_tr then
cons_to_move, rest = rmatch(last_tr, "^([" .. com.tr_cons .. "]+)([" .. com.tr_cons .. "].*)$")
if cons_to_move then
prefix_tr = prefix_tr .. cons_to_move
last_tr = rest
end
end
end
return prefix_ru, prefix_tr, last_ru, last_tr
end
local function split_known_main_verb(arg, mains)
-- Given an argument (which may be RUSSIAN//TR), split the prefix from
-- the main verb, which should be one of the verbs in MAINS (which can be
-- a -- single verb or a list of verbs, but in either case all verbs
-- need to be stressed). This correctly handles stressed and unstressed
-- prefixes.
local stem, tr = nom.split_russian_tr(arg)
if type(mains) ~= "table" then
mains = {mains}
end
for _, main in ipairs(mains) do
assert(com.is_stressed(main))
if rfind(stem, main .. "$") then
stem, tr = nom.strip_ending(stem, tr, main)
if com.is_stressed(stem) then
error("Two stresses in " .. arg)
end
return stem, tr, main, nil
end
main = com.make_unstressed_once(main)
if rfind(stem, main .. "$") then
stem, tr = nom.strip_ending(stem, tr, main)
if com.is_unstressed(stem) then
error("No stresses in " .. arg)
end
return stem, tr, main, nil
end
end
if #mains == 1 then
error("Argument " .. arg .. " doesn't end in " .. mains[1])
else
error("Argument " .. arg .. " doesn't end in any of " .. table.concat(mains, ","))
end
end
local function construct_long_prefix_variant(prefix)
if rfind(prefix, "рас$") then
return rsub(prefix, "рас$", "разо")
end
if rfind(prefix, "ис$") then
return rsub(prefix, "ис$", "изо")
end
if rfind(prefix, "вс$") then
return rsub(prefix, "вс$", "взо")
end
return prefix .. "о"
end
local function append_imper_by_variant(forms, stem, tr, variant, verbclass, note)
local vowel_stem = is_vowel_stem(stem)
local stress = rmatch(verbclass, "([abc])$")
if not stress then
error("Unrecognized verb class '" .. verbclass .. "', should end with a, b or c")
end
local longend = stress == "a" and "и" or "и́"
local shortend = vowel_stem and (com.is_unstressed(stem) and "́й" -- accent on previous vowel
or "й") or "ь"
local function append_short_imper()
append_imper(forms, stem, tr, shortend, shortend .. "те", note)
end
local function append_long_imper()
append_imper(forms, stem, tr, longend, longend .. "те", note)
end
if variant and variant ~= "" then
track("explicit-imper")
track("explicit-imper/" .. verbclass)
end
if variant == "(2)" then
-- use short variants with вы́- (for these verbs, long is expected)
if not rfind(stem, "^вы́-") then
error("Should only specify imperative variant (2) with verbs in вы́-, not " .. stem)
end
append_short_imper()
elseif variant == "[(2)]" then
-- use both long and short variants
append_long_imper()
append_short_imper()
elseif variant == "(3)" then
-- long in singular, short in plural
append_imper(forms, stem, tr, longend, shortend .. "те", note)
elseif variant == "[(3)]" then
-- long and short in singular, short in plural
append_imper(forms, stem, tr, {longend, shortend}, shortend .. "те", note)
elseif variant == "ь" or variant == "й" then
-- short variants wanted
append_short_imper()
elseif variant == "и" then
-- long variants wanted
append_long_imper()
else
assert(not variant or variant == "")
if vowel_stem then
if verbclass == "4b" or verbclass == "4c" or (
verbclass == "4a" and rfind(stem, "^вы́-")) then
append_long_imper()
else
append_short_imper()
end
else -- consonant stem
if stress == "b" or stress == "c" then
append_long_imper()
else
assert(stress == "a")
-- "и" after вы́-, e.g. вы́садить
-- "и" after final щ, e.g. тара́щиться (although this particular
-- verb has a [(3)] spec attached to it)
if rfind(stem, "^вы́-") or rfind(stem, "щ$") or
-- "и" after two consonants in a row (мо́рщить, зафре́ндить)
rfind(stem, "[бвгджзклмнпрстфхцчшщь][бвгджзклмнпрстфхцчшщ]$") then
append_long_imper()
else
-- "ь" after a single consonant (бре́дить)
append_short_imper()
end
end
end
end
end
-- Compute the past passive participle stem for verbs that require it to be
-- iotated (class 4, and class 5 in -еть).
local function iotated_ppp(data, stem, tr)
local iotated_stem, iotated_tr
if data.zhd then
local subbed
iotated_stem, subbed = rsubb(stem, "з?д$", "жд")
if not subbed then
error("Variant -жд- specified but stem " .. stem .. " doesn't end in -д")
end
if tr then
iotated_tr, subbed = rsubb(tr, "z?d$", "žd")
if not subbed then
error("Variant -жд- specified but translit " .. tr .. " doesn't end in -d")
end
end
else
iotated_stem, iotated_tr = com.iotation(stem, tr, data.shch)
end
return iotated_stem, iotated_tr
end
-- Set the past passive participle of verbs where the stress is moved left
-- from the ending by one syllable (if possible) if the ending is stressed,
-- otherwise left as-is (except class 1a in -е́ть, which has ending-stressed
-- -ённый). This applies to classes 1, 2, 3, 5, 6, 10 and 13. The stem comes
-- from the infinitive, iotated in class 5 -еть/-ѣть verbs. The participle
-- ending is -анный/-янный for verbs in -ать/-ять, -енный/-ённый for verbs in -еть,
-- -ѣнный/-ѣ̈нный for verbs in -ѣть, otherwise -тый.
local function set_moving_ppp(forms, data)
if not data.ppp then
return
end
-- NOTE: No need to check for multiple infinitives because no verbs have
-- them normally, and we probably don't want to check for overrides here
-- (e.g. it would break достичь and related verbs, which have participles
-- based on the infinitive достигнуть).
local infinitive, infinitivetr = extract_russian_tr(forms["infinitive"])
local stem, ending = rmatch(infinitive, "^(.*)([аеѣоуя]́?ть)$")
if not stem then
error("Strange infinitive " .. infinitive .. " when trying to create participle")
end
local tr, endingtr
if infinitivetr then
if ending == "ять" or ending == "я́ть" then
tr, endingtr = rmatch(infinitivetr, "^(.*)(ja" .. AC .. "?tʹ)$")
else
tr, endingtr = rmatch(infinitivetr, "^(.*)([aeěou]" .. AC .. "?tʹ)$")
end
if not tr then
error("Translit " .. infinitivetr .. " doesn't match Cyrillic " ..
infinitive)
end
end
local ending_vowel = usub(ending, 1, 1)
local ppptype = data.ppp
if com.is_nonsyllabic(stem) then
-- e.g. 3b гну́ть (гну́тый); but not -нуть (type 3a, as a suffix)
ppptype = "(7)"
end
if ut.contains({"5a", "5b", "5c"}, data.conj_type) and
(ending_vowel == "е" or ending_vowel == "ѣ") then
stem, tr = iotated_ppp(data, stem, tr)
end
if not com.is_stressed(stem) then
stem, tr = com.make_ending_stressed(stem, tr)
end
if data.o then
-- цев -> цо́в, e.g. (об)лицева́ть -> (об)лицо́ванный
stem = rsub(stem, "е́", "о́") -- Cyrillic
if tr then
tr = rsub(tr, "e" .. AC, "o" .. AC) -- Latin
end
elseif data.yo then
-- ё occurs with e.g. 1a наверста́ть (навёрстанный)
-- ё occurs with e.g. 3b поверну́ть (повёрнутый)
-- ё occurs with e.g. 5b лежа́ть (лёжанный) but not with 5c держа́ть
-- (де́ржанный)
-- ё occurs always with class 2 in -ева́ть, e.g.
-- (за)тушева́ть ((за)тушёванный) and (за)клева́ть ((за)клёванный)
local subbed
stem, subbed = rsubb(stem, "е́", "ё") -- Cyrillic
if not subbed and data.old then
stem, subbed = rsub(stem, "ѣ́", "ѣ̈")
end
if not subbed then
error("No stressed е" .. (data.old and " or ѣ" or "") ..
" in stem " .. stem ..
" to replace with ё" .. (data.old and " or ѣ̈" or "") ..
" when trying to create participle")
end
if tr then
tr, subbed = rsub(tr, "j[eě]" .. AC, "jo" .. AC) -- Latin
if not subbed then
tr, subbed = rsub(tr, "[eě]" .. AC, "jo" .. AC) -- Latin
end
if not subbed then
error("No stressed е in translit " .. tr .. " to replace with jo when trying to create participle")
end
end
end
if data.conj_type == "1a" and ending_vowel == "е" then
-- 1a, only одоле́ть, преодоле́ть, verbs in -печатле́ть
set_ppp(forms, stem, tr, "ённый")
elseif data.conj_type == "1a" and ending_vowel == "ѣ" then
set_ppp(forms, stem, tr, "ѣ̈нный")
else
local stressed_ending, unstressed_ending
if ending_vowel == "е" then
stressed_ending = "ённый"
unstressed_ending = "енный"
elseif ending_vowel == "ѣ" then
stressed_ending = "ѣ̈нный"
unstressed_ending = "ѣнный"
else
local ppp_ending =
(ending_vowel == "а" or ending_vowel == "я") and "нный" or "тый"
stressed_ending = ending_vowel .. AC .. ppp_ending
unstressed_ending = ending_vowel .. ppp_ending
end
set_ppp(forms, stem, tr,
-- (7) occurs with 1a обуя́ть (обуя́нный)
ppptype == "(7)" and stressed_ending or
-- [(7)] -- when does it occur? may only occur in class 4
ppptype == "[(7)]" and {unstressed_ending, stressed_ending} or
unstressed_ending)
end
end
-- Iterate over the values of a property (e.g. past_m, past_f), handling
-- overrides properly. Call FN on each one, passing in RU, TR, NOTE.
local function iterate_over_prop(forms, args, prop, fn)
for _, form in ipairs(main_to_all_verb_forms[prop]) do
local ru, tr
if args[form] then
local orig_forms = {}
for _, form2 in ipairs(main_to_all_verb_forms[prop]) do
if forms[form2] then
table.insert(orig_forms, forms[form2])
end
end
local override = parse_and_stress_override(form, args[form], forms[form], orig_forms)
ru, tr = extract_russian_tr(override)
end
if (not ru or ru == "" or ru == "-") and forms[form] then
ru, tr = extract_russian_tr(forms[form])
end
-- skip unstressed forms (may occur in the past_m when a stressed
-- reflexive -ся́ should occur; these occur only in запереться and
-- опереться, where they're used to generate the past active part
-- and past adverbial part, and end-stressed forms shouldn't be
-- generated)
if ru and ru ~= "" and ru ~= "-" and not com.is_unstressed(ru) then
local ruentry, runotes = m_table_tools.separate_notes(ru)
local trentry, trnotes
if tr then
trentry, trnotes = m_table_tools.separate_notes(tr)
end
fn(ruentry, trentry, {runotes, trnotes})
end
end
end
-- Set the past passive participle for those classes where it is derived
-- from the past tense masculine singular (9, 11, 12, 14, 15, 16). We need
-- to apply any relevant overrides.
local function set_ppp_from_past_m(forms, args, data)
if not data.ppp then
return
end
iterate_over_prop(forms, args, "past_m", function(ru, tr, note)
if rfind(ru, "л$") then
ru = rsub(ru, "л$", "")
if tr then
tr = rsub(tr, "l$", "")
end
end
append_ppp(forms, ru, tr, "тый", note)
end)
end
-- Set the past passive participle for class-4 verbs.
local function set_class_4_ppp(forms, data, stem, tr, vclass)
if not data.ppp then
return
end
local iotated_stem, iotated_tr = iotated_ppp(data, stem, tr)
vclass = vclass or data.conj_type
if vclass == "4b" then
local stressed_iotated_stem, stressed_iotated_tr =
com.make_ending_stressed(iotated_stem, iotated_tr)
set_ppp(forms, stressed_iotated_stem, stressed_iotated_tr,
-- (8) occurs with 4b скрои́ть (скро́енный)
data.ppp == "(8)" and "енный" or
-- [(8)] occurs with 4b разгроми́ть (разгромлённый, разгро́мленный)
data.ppp == "[(8)]" and {"ённый", "енный"} or "ённый")
else
set_ppp(forms, iotated_stem, iotated_tr,
-- (7) occurs with 4c раздели́ть (разделённый)
data.ppp == "(7)" and "ённый" or
-- [(7)] occurs with 4a осве́домить (осве́домленный, осведомлённый)
-- [(7)] occurs with 4c иссуши́ть (иссу́шенный, иссушённый)
data.ppp == "[(7)]" and {"енный", "ённый"} or "енный")
end
end
-- Set the past passive participle for class-7 and class-8 verbs. These
-- form the PPP by adding to the base of the 3sg pres/futr (i.e. minus
-- -ет/-ёт). The stress follows the stress of the past singular feminine.
-- Only types a, a(1) and b exist, meaning that if the past singular feminine
-- is ending-stressed then the PPP ending is -ённый, otherwise it is -енный
-- with the stress of the 3sg pres/futr base preserved (and added to the
-- last syllable if the base has no stress, as in 7b укра́сть, 3sg украдёт,
-- fem sg past укра́ла, PPP укра́денный).
local function set_class_7_8_ppp(forms, args, data)
if not data.ppp then
return
end
local sg3_bases = {}
-- Extract 3sg bases. There may be more than one possible form, e.g. in
-- обокра́сть, so support this.
-- FIXME: We don't support checking for overrides here; doing so isn't
-- overly hard but is a bit tricky because the overrides will be either
-- pres_3sg or futr_3sg, depending on the aspect of the verb.
-- FIXME: We don't support manual translit here, because neither 7 nor 8
-- support it elsewhere.
for _, form in ipairs(main_to_all_verb_forms["pres_futr_3sg"]) do
local ru, tr
if forms[form] then
ru, tr = extract_russian_tr(forms[form])
end
if ru and ru ~= "" and ru ~= "-" then
local ruentry, runotes = m_table_tools.separate_notes(ru)
ruentry = rsub(ruentry, "[её]т$", "")
if com.is_unstressed(ruentry) then
ruentry = com.make_ending_stressed(ruentry)
end
ut.insert_if_not(sg3_bases, {ruentry, runotes})
end
end
-- Here we do the same rigmarole as in set_ppp_from_past_m(), to respect
-- any past_f overrides that might have been set. It's unlikely that
-- there is more than one possible form but we support it.
iterate_over_prop(forms, args, "past_f", function(ru, tr, note)
for _, base_and_notes in ipairs(sg3_bases) do
local base, notes = base_and_notes[1], base_and_notes[2]
append_ppp(forms, base, nil,
-- check if past_f is ending-stressed
rfind(ru, AC .. "$") and "ённый" or "енный", notes)
end
end)
end
--[=[
Conjugation functions
]=]
conjugations["1a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"+p", "7", "ё"})
local stem, tr = nom.split_russian_tr(get_stressed_arg(args, 2))
if stem == "-" and not tr then
-- Template space; leave it
else
stem, tr = nom.strip_ending(stem, tr, "ть")
end
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "ть")
append_participles(forms, stem, tr, "ющий", "емый", "я", "вший", "вши", "в")
set_moving_ppp(forms, data)
present_je(forms, stem, tr, "a")
append_imper(forms, stem, tr, "й", "йте")
set_past(forms, stem, tr, "л", "ла", "ло", "ли")
return forms
end
local function guts_of_2(args, data)
local forms = {}
local inf_stem, inf_tr = nom.split_russian_tr(get_stressed_arg(args, 2))
inf_stem, inf_tr = nom.strip_ending(inf_stem, inf_tr, "ть")
no_stray_args(args, 2)
local pres_stem, pres_tr = inf_stem, inf_tr
local variants = args[1] or ""
parse_variants(data, variants, {"+p", "7"})
-- If stem ends in -ева́ть and a past passive participle is called for
-- with stress on the -е-, automatically set -о- or -ё- as required.
if data.ppp and data.ppp ~= "(7)" then
if rfind(inf_stem, "цева́") then
if data.ppp == "[(7)]" then
-- FIXME. Theoretically we should support this but there
-- aren't any verbs requiring it. It won't work properly
-- currently because we need the о to appear only when
-- stressed.
error("Variant [(7)] not supported for class 2")
end
-- цев -> цо́в, e.g. (об)лицева́ть -> (об)лицо́ванный
data.o = true
data.title = data.title .. "(-о-)"
elseif rfind(inf_stem, "ева́") then
data.yo = true
data.title = data.title .. "(-ё-)"
end
end
-- all -ова- change to -у-
pres_stem = rsub(pres_stem, "о(́?)ва(́?)$", "у%1%2")
pres_tr = pres_tr and rsub(pres_tr, "o(́?)va(́?)$", "u%1%2")
-- -ева- change to -ю- after most consonants and vowels, to -у- after hissing sounds and ц
if rfind(pres_stem, "[бвгдзклмнпрстфхь" .. com.vowel .. AC .. "]е(́?)ва(́?)$") then
pres_stem = rsub(pres_stem, "е(́?)ва(́?)$", "ю%1%2")
pres_tr = pres_tr and rsub(pres_tr, "e(́?)va(́?)$", "ju%1%2")
elseif rfind(pres_stem, "[жцчшщ]е(́?)ва(́?)$") then
pres_stem = rsub(pres_stem, "е(́?)ва(́?)$", "у%1%2")
pres_tr = pres_tr and rsub(pres_tr, "e(́?)va(́?)$", "u%1%2")
end
forms["infinitive"] = combine(inf_stem, inf_tr, "ть")
if data.conj_type == "2a" then
append_participles_2stem(forms, pres_stem, pres_tr, inf_stem, inf_tr,
"ющий", "емый", "я", "вший", "вши", "в")
present_je(forms, pres_stem, pres_tr, "a")
else
append_participles_2stem(forms, pres_stem, pres_tr, inf_stem, inf_tr,
"ю́щий", "-", "я́", "вший", "вши", "в")
present_je(forms, pres_stem, pres_tr, "b")
end
set_moving_ppp(forms, data)
append_imper(forms, pres_stem, pres_tr, "й", "йте")
set_past(forms, inf_stem, inf_tr, "л", "ла", "ло", "ли")
return forms
end
conjugations["2a"] = function(args, data)
return guts_of_2(args, data)
end
conjugations["2b"] = function(args, data)
return guts_of_2(args, data)
end
conjugations["3°a"] = function(args, data)
local forms = {}
-- (5), [(6)] or similar; imperative indicators
parse_variants(data, args[1], {"5", "6", "23", "и", "+p", "7", "ё"})
local stem, tr = nom.split_russian_tr(get_stressed_arg(args, 2))
stem, tr = nom.strip_ending(stem, tr, "нуть")
local vowel_stem = is_vowel_stem(stem)
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "нуть")
append_participles(forms, stem, tr,
-- default is blank for pres passive and adverbial
"нущий", "-", "-",
data.var6 == "req" and "нувший" or
data.var6 == "opt" and (vowel_stem and {"вший", "нувший"} or {"ший", "нувший"}) or
vowel_stem and "вший" or "ший",
data.var6 == "req" and "нувши" or
data.var6 == "opt" and (vowel_stem and {"вши", "нувши"} or {"ши", "нувши"}) or
vowel_stem and "вши" or "ши",
data.var6 == "req" and "нув" or
data.var6 == "opt" and (vowel_stem and {"в", "нув"} or "нув") or
vowel_stem and "в" or "-")
set_moving_ppp(forms, data)
present_e_a(forms, stem .. "н", tr and tr .. "n")
append_imper_by_variant(forms, stem .. "н", tr and tr .. "n", data.imper_variant, "3°a")
forms["past_m"] = data.var5 and combine(stem, tr, "нул") or "-"
forms["past_m_short"] = data.var5 ~= "req" and combine(stem, tr, (vowel_stem and "л" or "")) or nil
forms["past_f_short"] = combine(stem, tr, "ла")
forms["past_n_short"] = combine(stem, tr, "ло")
forms["past_pl_short"] = combine(stem, tr, "ли")
return forms
end
conjugations["3a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"23", "и", "+p", "7", "ё"})
local stem, tr = nom.split_russian_tr(get_stressed_arg(args, 2))
-- make sure we can strip нуть from the stem and any translit;
nom.strip_ending(stem, tr, "нуть")
-- but then just strip the -уть and leave the н
stem, tr = nom.strip_ending(stem, tr, "уть")
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "уть")
append_participles(forms, stem, tr,
-- default is blank for pres passive and adverbial
"ущий", "-", "-", "увший", "увши", "ув")
set_moving_ppp(forms, data)
present_e_a(forms, stem, tr)
append_imper_by_variant(forms, stem, tr, data.imper_variant, "3a")
set_past(forms, stem .. "ул", tr and tr .. "ul", "", "а", "о", "и")
return forms
end
local function guts_of_3b_3c(args, data, vclass)
local forms = {}
parse_variants(data, args[1], {"+p", "7", "ё"})
local stem, tr = nom.split_russian_tr(get_stressed_arg(args, 2))
-- make sure we can strip нуть from the stem and any translit;
nom.strip_ending(stem, tr, "ну́ть")
-- but then just strip the -у́ть and leave the н
stem, tr = nom.strip_ending(stem, tr, "у́ть")
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "у́ть")
append_participles(forms, stem, tr,
-- default is blank for pres passive and adverbial
"у́щий", "-", "-", "у́вший", "у́вши", "у́в")
set_moving_ppp(forms, data)
append_imper(forms, stem, tr, "и́", "и́те")
set_past(forms, stem, tr, "у́л", "у́ла", "у́ло", "у́ли")
if data.conj_type == "3b" then
present_e_b(forms, stem, tr)
else
stem, tr = com.make_ending_stressed(stem, tr)
present_e_c(forms, stem, tr)
end
return forms
end
conjugations["3b"] = function(args, data)
return guts_of_3b_3c(args, data)
end
conjugations["3c"] = function(args, data)
return guts_of_3b_3c(args, data)
end
conjugations["4a"] = function(args, data)
local forms = {}
-- imperative variants, also щ, used for verbs like похитить (похи́щу) (4a),
-- защитить (защищу́) (4b), поглотить (поглощу́) (4c) with a different
-- iotation (т -> щ, not ч)
parse_variants(data, args[1], {"23", "и", "щ", "past", "+p", "7", "жд"})
local stem, tr = nom.split_russian_tr(get_stressed_arg(args, 2))
stem, tr = nom.strip_ending(stem, tr, "ить")
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "ить")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(stem, "[шщжч]$")
append_participles(forms, stem, tr, hushing and "ащий" or "ящий",
"awkward-имый", hushing and "а" or "я", "ивший", "ивши", "ив")
set_class_4_ppp(forms, data, stem, tr)
present_i(forms, stem, tr, "a", data.shch)
append_imper_by_variant(forms, stem, tr, data.imper_variant, "4a")
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, stem .. "и",
tr and tr .. "i", args, data)
return forms
end
conjugations["4a1a"] = function(args, data)
local forms = {}
data.title = "4a // 1a"
data.cat_conj_types = {"1a", "4a"}
-- imperative variants, also щ, used for verbs like похитить (похи́щу) (4a),
-- защитить (защищу́) (4b), поглотить (поглощу́) (4c) with a different
-- iotation (т -> щ, not ч)
parse_variants(data, args[1], {"23", "и", "щ", "past", "+p", "7", "жд"})
local stem4, tr4 = nom.split_russian_tr(get_stressed_arg(args, 2))
stem4, tr4 = nom.strip_ending(stem4, tr4, "ить")
local hushing = rfind(stem4, "[шщжч]$")
local stem1, tr1
if hushing then
stem1 = stem4 .. "а"
tr1 = tr4 and tr4 .. "a"
else
stem1 = stem4 .. "я"
tr1 = tr4 and tr4 .. "ja"
end
no_stray_args(args, 2)
forms["infinitive"] = combine(stem4, tr4, "ить")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
append_participles(forms, stem4, tr4, hushing and "ащий" or "ящий",
"awkward-имый", hushing and "а" or "я", "ивший", "ивши", "ив")
append_participles(forms, stem1, tr1, "ющий", "емый", "я", {}, {}, {})
set_class_4_ppp(forms, data, stem4, tr4)
present_i(forms, stem4, tr4, "a", data.shch)
present_je(forms, stem1, tr1, "a", data.shch)
append_imper_by_variant(forms, stem4, tr4, data.imper_variant, "4a")
append_imper(forms, stem1, tr1, "й", "йте")
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, stem4 .. "и",
tr4 and tr4 .. "i", args, data)
return forms
end
conjugations["4b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"щ", "past", "+p", "8", "жд"})
local stem, tr = nom.split_russian_tr(get_stressed_arg(args, 2))
stem, tr = nom.strip_ending(stem, tr, "и́ть")
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "и́ть")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(stem, "[шщжч]$")
append_participles(forms, stem, tr, hushing and "а́щий" or "я́щий",
"awkward-и́мый", hushing and "а́" or "я́", "и́вший", "и́вши", "и́в")
set_class_4_ppp(forms, data, stem, tr)
present_i(forms, stem, tr, "b", data.shch)
append_imper(forms, stem, tr, "и́", "и́те")
-- set prefix to "" as past stem may vary in length and no (1) variants
local stem_noa, tr_noa = com.make_unstressed_once(stem, tr)
set_past_by_stress(forms, data.past_stress, "", nil, stem_noa .. "и́",
tr_noa and tr_noa .. "i" .. AC, args, data)
return forms
end
conjugations["4c"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"щ", "4", "past", "+p", "7", "жд"})
local stem, tr = nom.split_russian_tr(get_stressed_arg(args, 2))
stem, tr = nom.strip_ending(stem, tr, "и́ть")
stem, tr = com.make_ending_stressed(stem, tr)
no_stray_args(args, 2)
forms["infinitive"] = combine(stem, tr, "и́ть")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(stem, "[шщжч]$")
local prap_end_stressed = hushing and "а́щий" or "я́щий"
local prap_stem_stressed = hushing and "ащий" or "ящий"
append_participles(forms, stem, tr, data.var4 == "req" and prap_stem_stressed
or data.var4 == "opt" and {prap_end_stressed, prap_stem_stressed}
or prap_end_stressed,
"awkward-и́мый", hushing and "а́" or "я́", "и́вший", "и́вши", "и́в")
set_class_4_ppp(forms, data, stem, tr)
present_i(forms, stem, tr, "c", data.shch)
append_imper(forms, stem, tr, "и́", "и́те")
local stem_noa, tr_noa = com.make_unstressed_once(stem, tr)
set_past_by_stress(forms, data.past_stress, "", nil, stem_noa .. "и́",
tr_noa and tr_noa .. "i" .. AC, args, data)
return forms
end
-- Combined class 5. But there's enough conditional code that it might make
-- more sense to separate them again.
local function guts_of_5(args, data)
local forms = {}
local is5a = data.conj_type == "5a"
local is5b = data.conj_type == "5b"
-- imperative ending (выгнать - выгони) and past stress; imperative is
-- "й" after any vowel (e.g. выстоять), with or without an acute accent,
-- otherwise ь or и
if is5a or is5b then
parse_variants(data, args[1], {"23", "и", "past", "+p", "7", "ё"})
else
parse_variants(data, args[1], {"23", "и", "past", "+p", "7", "ё", "4"})
end
local inf = get_stressed_arg(args, 2)
local past_stem = nom.strip_ending(inf, nil, "ть")
local stem = is5b and get_opt_unstressed_arg(args, 3) or get_opt_stressed_arg(args, 3)
local default_stem = rmatch(past_stem, "^(.*)[еѣая]́?$")
if not default_stem then
error("Argument " .. inf .. " doesn't end in еть, ѣть, ать or ять")
end
if not is5a and not is5b then
default_stem = com.make_ending_stressed(default_stem)
end
stem = stem or default_stem
local pres_note = stem ~= default_stem and IRREG
no_stray_args(args, 3)
forms["infinitive"] = past_stem .. "ть"
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(stem, "[шщжч]$")
if is5a then
append_participles_2stem(forms, stem, nil, past_stem, nil,
hushing and "ащий" or "ящий", "имый", hushing and "а" or "я",
"вший", "вши", "в", pres_note)
elseif is5b then
append_participles_2stem(forms, stem, nil, past_stem, nil,
hushing and "а́щий" or "я́щий", "и́мый", hushing and "а́" or "я́",
"вший", "вши", "в", pres_note)
else
-- var4 occurs with at least терпре́ть and дыша́ть
local prap_end_stressed = hushing and "а́щий" or "я́щий"
local prap_stem_stressed = hushing and "ащий" or "ящий"
append_participles_2stem(forms, stem, nil, past_stem, nil,
data.var4 == "req" and prap_stem_stressed
or data.var4 == "opt" and {prap_end_stressed, prap_stem_stressed}
or prap_end_stressed,
"и́мый", hushing and "а́" or "я́", "вший", "вши", "в", pres_note)
end
set_moving_ppp(forms, data)
present_i(forms, stem, nil, is5a and "a" or is5b and "b" or "c", nil, pres_note)
append_imper_by_variant(forms, stem, nil, data.imper_variant, data.conj_type, pres_note)
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, past_stem, nil,
args, data)
return forms
end
conjugations["5a"] = function(args, data)
return guts_of_5(args, data)
end
conjugations["5b"] = function(args, data)
return guts_of_5(args, data)
end
conjugations["5c"] = function(args, data)
return guts_of_5(args, data)
end
-- Implement 6a, 6°a, 6a1as13, 6a1as14, and 1a6a.
local function guts_of_6a(args, data, vclass)
local forms = {}
-- Type 6a1a, section 13:
-- Forms of both 6a and 1a can occur. They are the same in the infinitive
-- and past. In the present active participle and the present/future, the
-- type 6 forms are preferred and the type 1a forms are colloquial. In the
-- remaining present forms and the imperative, both are equally preferred
-- (we put the type-6 forms first because Zaliznyak lists them first).
-- Type 6a1a section 14, type 1a6a:
-- Forms of both 6a and 1a can occur. They are the same in the infinitive
-- and past. In the present adverbial participle and the imperative, the
-- type 1a forms are preferred and the type 6a forms are dated. In the
-- remaining present forms, one or the other is slightly preferred (type
-- 6a for 6a1a, type 1a for 1a6a).
if vclass == "6a1as13" or vclass == "6a1as14" then
data.title = "6a // 1a"
data.cat_conj_types = {"1a", "6a"}
elseif vclass == "1a6a" then
data.title = "1a // 6a"
data.cat_conj_types = {"1a", "6a"}
end
parse_variants(data, args[1], {"23", "и", "past", "+p", "7", "ё"})
local inf = get_stressed_arg(args, 2)
local inf_past_stem = nom.strip_ending(inf, nil, "ть")
local stem = rmatch(inf_past_stem, "^(.*)[ая]́?$")
if not stem then
error("Argument " .. inf .. " doesn't end in ать or ять")
end
if com.is_unstressed(stem) then
-- колыха́ть, колеба́ть, etc.
stem = com.make_ending_stressed(stem)
end
-- вызвать - вы́зову (в́ызов)
local pres_stem = get_opt_stressed_arg(args, 3) or stem
no_stray_args(args, 3)
local pres_note = pres_stem ~= stem and IRREG
-- no iotation, e.g. вырвать - вы́рву
local no_iotation = vclass == "6°a"
-- replace consonants for 1st person singular present/future
local iotated_stem = no_iotation and pres_stem or com.iotation(pres_stem)
forms["infinitive"] = inf_past_stem .. "ть"
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(iotated_stem, "[шщжч]$") or no_iotation
-- Participles
-- pres_pasv_part is normal if infinitive ends in -ять, nonexistent except
-- with certain lexical exceptions (колеба́ть, колыха́ть, глаго́лать,
-- дви́гать with exceptional form дви́жимый) if infinitive ends in -ать
local prpp_status = rfind(inf_past_stem, "я́?$") and "" or "none-"
if vclass == "6a" or vclass == "6°a" or vclass == "6a1as13" then
append_participles_2stem(forms, iotated_stem, nil, inf_past_stem, nil,
hushing and "ущий" or "ющий", prpp_status .. "емый", hushing and "а" or "я",
"вший", "вши", "в", pres_note)
if vclass == "6a1as13" then
-- then all the type 1a forms (both are the same in the past)
append_participles(forms, inf_past_stem, nil, "ющий*", prpp_status .. "емый", "я")
end
elseif vclass == "6a1as14" then
-- first the preferred type 6a present active/passive participles
append_participles(forms, iotated_stem, nil,
hushing and "ущий" or "ющий", prpp_status .. "емый", {}, {}, {}, {}, pres_note)
-- then all the type 1a forms (both are the same in the past)
append_participles(forms, inf_past_stem, nil, "ющий", "емый", "я",
"вший", "вши", "в")
-- then the dated type 6a present adverbial participle
append_participles(forms, iotated_stem, nil,
{}, {}, hushing and "а*" or "я*", {}, {}, {}, pres_note)
else -- type 1a6a
-- first the preferred type 1a forms (both are the same in the past)
append_participles(forms, inf_past_stem, nil, "ющий", "емый", "я",
"вший", "вши", "в")
-- then the type 6a forms (dated in present adverbial participle)
append_participles(forms, iotated_stem, nil,
hushing and "ущий" or "ющий", prpp_status .. "емый", hushing and "а*" or "я*",
{}, {}, {}, pres_note)
end
set_moving_ppp(forms, data)
-- Present/future tense
local function class_6_present()
if no_iotation then
present_e_a(forms, pres_stem, nil, pres_note)
else
present_je(forms, pres_stem, nil, "a", nil, pres_note)
end
end
if vclass == "6a" or vclass == "6°a" then
class_6_present()
elseif vclass == "1a6a" then
-- Do type 1a forms
present_je(forms, inf_past_stem, nil, "a")
class_6_present()
elseif vclass == "6a1as14" then
class_6_present()
-- Do type 1a forms
present_je(forms, inf_past_stem, nil, "a")
else
-- 6a1as13
class_6_present()
-- Do type 1a forms
present_je(forms, inf_past_stem, nil, "a", nil, "*")
end
-- Imperative forms; if 1a6a or 6a1as14, type 6a forms are dated;
-- if 6a1as13, type 6a forms go first.
local function class_1_impr()
append_imper(forms, inf_past_stem, nil, "й", "йте")
end
local function class_6_impr()
local dated_note = ((vclass == "6a1as14" or vclass == "1a6a") and "*" or "") ..
(pres_note or "")
append_imper_by_variant(forms, iotated_stem, nil, data.imper_variant,
"6a", dated_note)
end
if vclass == "6a1as14" or vclass == "1a6a" then
class_1_impr()
class_6_impr()
elseif vclass == "6a1as13" then
class_6_impr()
class_1_impr()
else
class_6_impr()
end
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, inf_past_stem, nil,
args, data)
if vclass == "6a1as14" or vclass == "1a6a" then
ut.insert_if_not(data.internal_notes, "* Dated.")
elseif vclass == "6a1as13" then
ut.insert_if_not(data.internal_notes, "* Colloquial; type-6 forms preferred.")
end
return forms
end
conjugations["6a"] = function(args, data)
return guts_of_6a(args, data, "6a")
end
conjugations["6°a"] = function(args, data)
return guts_of_6a(args, data, "6°a")
end
conjugations["6a1as13"] = function(args, data)
return guts_of_6a(args, data, "6a1as13")
end
conjugations["6a1as14"] = function(args, data)
return guts_of_6a(args, data, "6a1as14")
end
conjugations["1a6a"] = function(args, data)
return guts_of_6a(args, data, "1a6a")
end
-- implement 6b, 6°b
local function guts_of_6b(args, data, vclass)
local forms = {}
parse_variants(data, args[1], {"past", "+p", "7", "ё"})
local inf = get_stressed_arg(args, 2)
local stem = rmatch(inf, "^(.*)[ая]́ть$")
if not stem then
error("Argument " .. inf .. " doesn't end in ать or ять")
end
-- звать - зов, драть - дер
local pres_stem = get_opt_unstressed_arg(args, 3) or stem
no_stray_args(args, 3)
-- no iotation, e.g. рвать - рву
local no_iotation = vclass == "6°b"
local vowel_end_stem = is_vowel_stem(stem)
local pres_note = pres_stem ~= stem and IRREG
if no_iotation then
present_e_b(forms, pres_stem, nil, pres_note)
else
present_je(forms, pres_stem, nil, "b", nil, pres_note)
end
local impr_end = vowel_end_stem and "́й" -- accent on the preceding vowel
or "и́"
append_imper(forms, pres_stem, nil, impr_end, impr_end .. "те", pres_note)
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(pres_stem, "[шщжч]$")
-- no pres_pasv_part
local past_stem_with_vowel = stem .. (vowel_end_stem and "я́" or "а́")
append_participles_2stem(
forms, pres_stem, nil, past_stem_with_vowel, nil,
((hushing or no_iotation) and "у́щий" or "ю́щий"), {}, (hushing and "а́" or "я́"),
"вший", "вши", "в", pres_note)
forms["infinitive"] = combine(past_stem_with_vowel, nil, "ть")
set_moving_ppp(forms, data)
-- past_f for ждала́, подождала́ now handled through general mechanism
--for разобрало́сь, past_n2 разобрало́ now handled through general mechanism
--for разобрали́сь, past_pl2 разобрали́ now handled through general mechanism
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil,
stem .. (vowel_end_stem and "я́" or "а́"), nil, args, data)
return forms
end
conjugations["6b"] = function(args, data)
return guts_of_6b(args, data, "6b")
end
conjugations["6°b"] = function(args, data)
return guts_of_6b(args, data, "6°b")
end
-- Implement 6c, 6°c and 6c1a.
local function guts_of_6c(args, data, vclass)
local forms = {}
-- In type 6c1a, forms of both 6c and 1a can occur. They are
-- the same in the infinitive and past. In the present active participle
-- and the present/future, the type 6c forms are preferred and the type 1a
-- forms are colloquial. In the remaining present forms and the imperative,
-- both are equally preferred (we put the 6c forms first because Zaliznyak
-- lists 6c first).
if vclass == "6c1a" then
data.title = "6c // 1a"
data.cat_conj_types = {"1a", "6c"}
end
-- optional щ parameter for verbs like клеветать (клевещу́), past stress
parse_variants(data, args[1], {"щ", "past", "+p", "7", "ё"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "а́ть")
stem = com.make_ending_stressed(stem)
-- разостла́ть - расстелю́, рассте́лешь
local pres_stem = get_opt_stressed_arg(args, 3) or stem
no_stray_args(args, 3)
local pres_note = pres_stem ~= stem and IRREG
-- remove accent for some forms
local stem_noa = com.make_unstressed(stem)
-- applies only to стона́ть, застона́ть, простона́ть
local no_iotation = vclass == "6°c"
-- iotate the stem
local iotated_stem =
no_iotation and pres_stem or com.iotation(pres_stem, nil, data.shch)
local stem1a = stem_noa .. "а́"
forms["infinitive"] = stem_noa .. "а́ть"
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(iotated_stem, "[шщжч]$")
-- Participles
append_participles_2stem(forms, iotated_stem, nil, stem_noa, nil,
(hushing or no_iotation) and "ущий" or "ющий", {},
hushing and "а́" or "я́", "а́вший", "а́вши", "а́в", pres_note)
if vclass == "6c1a" then
-- then all the type 1a forms (both are the same in the past)
append_participles(forms, stem1a, nil, "ющий*", "емый", "я")
end
set_moving_ppp(forms, data)
if no_iotation then
present_e_c(forms, pres_stem, nil, pres_note)
else
present_je(forms, pres_stem, nil, "c", data.shch, pres_note)
end
append_imper(forms, iotated_stem, nil, "и́", "и́те", pres_note)
if vclass == "6c1a" then
present_je(forms, stem1a, nil, "a", nil, "*")
append_imper(forms, stem1a, nil, "й", "йте")
end
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, stem_noa .. "а́", nil,
args, data)
if vclass == "6c1a" then
ut.insert_if_not(data.internal_notes, "* Colloquial; type-6 forms preferred.")
end
return forms
end
conjugations["6c"] = function(args, data)
return guts_of_6c(args, data, "6c")
end
conjugations["6°c"] = function(args, data)
return guts_of_6c(args, data, "6°c")
end
conjugations["6c1a"] = function(args, data)
return guts_of_6c(args, data, "6c1a")
end
local function convert_last_e_to_yo(form)
return rsub(form,
"([еѣ])́?([^" .. com.vowel .. "]*)$",
function(e, nonvowels)
return (e == "е" and "ё" or "ѣ̈") .. nonvowels
end)
end
local function guts_of_7(args, data, forms)
local is7b = data.conj_type == "7b"
local full_inf = get_stressed_arg(args, 2)
local pres_stems = is7b and get_unstressed_arg(args, 3) or get_stressed_arg(args, 3)
pres_stems = rsplit(pres_stems, ",")
local past_stem
if past_stem ~= "ёе" then
past_stem = get_opt_stressed_arg(args, 4)
end
local past_stem_vowel_alt = past_stem == "ёе"
if past_stem_vowel_alt then
past_stem = nil
end
no_stray_args(args, 4)
forms["infinitive"] = full_inf
-- Construct the default past and present stem by a combination of
-- infinitive and present final consonant.
-- (1) Deduce the final consonant.
local final_cons
for _, pres_stem in ipairs(pres_stems) do
-- Final cons is -ст if pres stem ends in vowel + ст, else
-- single final cons [дтсзбп] (no actual examples of final п).
-- Note that final -з can occur after a consonant (e.g. ползти́).
local this_final_cons = rmatch(pres_stem,
"[" .. com.vowel .. "]" .. AC .. "?(ст)$")
if not this_final_cons then
this_final_cons = rmatch(pres_stem, "([дтсзбп])$")
end
if not this_final_cons then
error("Unable to determine final consonant from present stem " .. pres_stem)
end
if final_cons and this_final_cons ~= final_cons then
error("Present stems with conflicting final consonants specified: " ..
table.concat(pres_stems, ","))
end
final_cons = this_final_cons
end
-- (2) Find the infinitive minus the termination.
local prefix = rmatch(full_inf, "^(.*)[сз]т[иь]" .. AC .."?$")
if not prefix then
error("Strange infinitive " .. full_inf .. "in class 7")
end
-- (3) Combine infinitive with final consonant.
local default_pres_stem = prefix .. final_cons
if is7b then
default_pres_stem = com.make_unstressed(default_pres_stem)
end
local default_past_stem = default_pres_stem
if com.is_unstressed(default_past_stem) then
default_past_stem = com.make_ending_stressed(default_past_stem)
end
-- (4) Past stems ending in -д and -т when the infinitive ends in -сть (but not -сти or -сти́)
-- lose this consonant (page 85 of Zaliznyak, see also footnote 2 on that page).
if rfind(full_inf, "сть$") then
default_past_stem = rsub(default_past_stem, "[дт]$", "")
end
-- (5) If 7b and the past stem wasn't originally specified as ёе, the past stem gets
-- ё in place of е.
if is7b and not past_stem_vowel_alt then
default_past_stem = convert_last_e_to_yo(default_past_stem)
end
for _, pres_stem in ipairs(pres_stems) do
local pres_note = pres_stem ~= default_pres_stem and IRREG
if is7b then
present_e_b(forms, pres_stem, nil, pres_note)
append_imper(forms, pres_stem, nil, "и́", "и́те", pres_note)
else
present_e_a(forms, pres_stem, nil, pres_note)
append_imper_by_variant(forms, pres_stem, nil, data.imper_variant,
"7a", pres_note)
end
end
-- Construct the past stem if not specified. Note that we then derive a separate
-- past-tense stem from this stem, and this stem as such ends up applying only
-- to the past active and adverbial participles.
if not past_stem then
past_stem = default_past_stem
end
local past_note = past_stem ~= default_past_stem and IRREG
-- Derive the past tense stem from the past stem derived above. This has ё instead of е
-- in 7b verbs; it also loses д and т in all cases, when the past stem derived above only loses
-- these consonants in some cases.
local past_tense_stem = past_stem
if is7b then
past_tense_stem = convert_last_e_to_yo(past_tense_stem)
end
past_tense_stem = rsub(past_tense_stem, "[дт]$", "")
local vowel_pp = is_vowel_stem(past_stem)
local pap = vowel_pp and "вши" or "ши"
local var9_note_symbol = next_note_symbol(data)
for _, pres_stem in ipairs(pres_stems) do
append_participles_2stem(forms, pres_stem, nil, past_stem, nil,
is7b and "у́щий" or "ущий", "-", is7b and "я́" or "я",
vowel_pp and "вший" or "ший",
data.var9 and {is7b and "я́" or "я", pap .. var9_note_symbol} or pap,
vowel_pp and not data.var9 and "в" or "-", pres_note, past_note)
end
if data.var9 then
ut.insert_if_not(data.internal_notes, var9_note_symbol .. " Dated.")
end
-- set prefix to "" as past stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, past_tense_stem, nil,
args, data,
-- 0 ending if the past stem ends in a consonant
not is_vowel_stem(past_tense_stem) and "no-pastml", past_note)
-- set PPP; must be done after both present 3sg and past fem have been set
set_class_7_8_ppp(forms, args, data)
end
conjugations["7a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"23", "и", "9","past", "+p"})
-- лезть - ле́зши - non-existent past_actv_part handled through general mechanism
guts_of_7(args, data, forms)
return forms
end
conjugations["7b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"9", "past", "+p"})
guts_of_7(args, data, forms)
return forms
end
local function class_8a_stem_to_infinitive(stem)
-- map e.g. вы́сек back to высе́чь
return rsub(stem, "[гк]$", "чь")
end
local function class_8b_stem_to_infinitive(stem)
-- map e.g. отвлёк back to отвле́чь
-- map e.g. зажёг back to заже́чь
return com.make_ending_stressed(rsub(rsub(rsub(stem, "ё", "е"), "ѣ̈", "ѣ"), "[гк]$", "чь"))
end
conjugations["8a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local full_inf = get_stressed_arg(args, 2)
local stem = get_stressed_arg(args, 3)
local stressed_past_stem = get_opt_stressed_arg(args, 4) or stem
no_stray_args(args, 4)
forms["infinitive"] = full_inf
local pres_note = class_8a_stem_to_infinitive(stem) ~= full_inf and IRREG
local stressed_past_note =
class_8a_stem_to_infinitive(stressed_past_stem) ~= full_inf and IRREG
-- default for pres_pasv_part is blank
append_participles_2stem(forms, stem, nil, stressed_past_stem, nil,
"ущий", "-", "-", "ший", "ши", "-", pres_note, stressed_past_note)
local iotated_stem = com.iotation(stem)
append_pres_futr(forms, iotated_stem, nil, {}, "ешь", "ет", "ем", "ете", {}, pres_note)
append_pres_futr(forms, stem, nil, "у", {}, {}, {}, {}, "ут", pres_note)
append_imper(forms, stem, nil, "и", "ите", pres_note)
-- set prefix to "" as stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil, stem, nil, args, data,
"no-pastml", pres_note)
forms["past_m"] = stressed_past_stem .. (stressed_past_note or "")
-- set PPP; must be done after both present 3sg and past fem have been set
set_class_7_8_ppp(forms, args, data)
return forms
end
conjugations["8b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local full_inf = get_stressed_arg(args, 2)
local stem = get_unstressed_arg(args, 3)
local stressed_past_stems = rsplit(args[4] or "ё", ",")
for _, stressed_past_stem in ipairs(stressed_past_stems) do
if stressed_past_stem ~= "е" then
check_stressed_arg(stressed_past_stem, 4)
end
end
no_stray_args(args, 4)
forms["infinitive"] = full_inf
local pres_note = class_8b_stem_to_infinitive(stem) ~= full_inf and IRREG
local iotated_stem = com.iotation(stem)
append_pres_futr(forms, iotated_stem, nil, {}, "ёшь", "ёт", "ём", "ёте", {}, pres_note)
append_pres_futr(forms, stem, nil, "у́", {}, {}, {}, {}, "у́т", pres_note)
append_imper(forms, stem, nil, "и́", "и́те", pres_note)
-- set prefix to "" as stem may vary in length and no (1) variants
set_past_by_stress(forms, data.past_stress, "", nil,
com.make_ending_stressed(stem), nil, args, data, "no-pastml", pres_note)
forms["past_m"] = nil
for _, stressed_past_stem in ipairs(stressed_past_stems) do
local pastm_stem, past_part_stem
if stressed_past_stem == "е" then
past_part_stem = com.make_ending_stressed(stem)
pastm_stem = past_part_stem
elseif stressed_past_stem == "ё" then
past_part_stem = convert_last_e_to_yo(com.make_ending_stressed(stem))
pastm_stem = past_part_stem
elseif stressed_past_stem == "ёе" then
past_part_stem = com.make_ending_stressed(stem)
pastm_stem = convert_last_e_to_yo(past_part_stem)
else
pastm_stem = stressed_past_stem
past_part_stem = stressed_past_stem
end
local past_note =
class_8b_stem_to_infinitive(pastm_stem) ~= full_inf and IRREG
-- default for pres_pasv_part is blank; влечь -> влеко́мый handled through
-- general override mechanism
append_participles_2stem(forms, stem, nil, past_part_stem, nil,
"у́щий", "-", "-", "ший", "ши", "-", pres_note, past_note)
append_form(forms, "past_m", pastm_stem, nil, "", past_note)
end
-- set PPP; must be done after both present 3sg and past fem have been set
set_class_7_8_ppp(forms, args, data)
return forms
end
conjugations["9a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "еть")
local pres_stem = get_opt_stressed_arg(args, 3)
no_stray_args(args, 3)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
local default_pres_stem = prefix .. rsub(base, "е", "")
pres_stem = pres_stem or default_pres_stem
local pres_note = pres_stem ~= default_pres_stem and IRREG
forms["infinitive"] = stem .. "еть"
-- perfective only
append_participles(forms, stem, nil, "-", "-", "-", "ший", "ши", "ев")
present_e_a(forms, pres_stem, nil, pres_note)
append_imper(forms, pres_stem, nil, "и", "ите", pres_note)
-- past_m doesn't end in л
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data, "no-pastml")
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["9b"] = function(args, data)
local forms = {}
--for this type, it's important to distinguish impf and pf
local impf = rfind(data.verb_type, "^impf")
parse_variants(data, args[1], {"past", "+p", "*"})
local stem_noa = nom.strip_ending(get_stressed_arg(args, 2), nil, "е́ть")
local stem = rsub(stem_noa, "(.*)е", "%1ё")
local pres_stem = get_opt_unstressed_arg(args, 3)
-- stem used for past active and adverbial participles; defaults to past_m
local past_part_stem = get_opt_stressed_arg(args, 4)
no_stray_args(args, 4)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem, nil, "single_cons_base")
local default_pres_stem =
data.star and construct_long_prefix_variant(prefix) .. rsub(base, "[её]", "") or
prefix .. rsub(base, "[её]", "")
pres_stem = pres_stem or default_pres_stem
local pres_note = pres_stem ~= default_pres_stem and IRREG
forms["infinitive"] = stem_noa .. "е́ть"
present_e_b(forms, pres_stem, nil, pres_note)
append_imper(forms, pres_stem, nil, "и́", "и́те", pres_note)
-- past_m doesn't end in л
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data, "no-pastml")
set_ppp_from_past_m(forms, args, data)
append_participles_2stem(forms, pres_stem, nil, stem, nil, "у́щий", {}, {},
-- impf: тереть -> тёрши
-- pf: растереть -> растёрши, растере́в
-- we handle (рас)тёрши down below because the stress depends on the
-- past_m: запереть -> за́пер, за́перши(й)
{}, {}, impf and {} or "е́в", pres_note)
if past_part_stem then
for _, ppstem in ipairs(rsplit(past_part_stem, ",")) do
append_participles(forms, ppstem, nil, {}, {}, {}, "ший", "ши", {})
end
else
iterate_over_prop(forms, args, "past_m", function(ru, tr, note)
append_participles(forms, ru, tr, {}, {}, {}, "ший", "ши", {}, note)
end)
end
return forms
end
conjugations["10a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"+p", "7"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "оть")
no_stray_args(args, 2)
forms["infinitive"] = stem .. "оть"
-- These verbs are perfective-only, no present participles
append_participles(forms, stem, nil, "-", "-", "-", "овший", "овши", "ов")
set_moving_ppp(forms, data)
present_je(forms, stem, nil, "a")
append_imper(forms, stem, nil, "и", "ите")
set_past(forms, stem .. "ол", nil, "", "а", "о", "и")
return forms
end
conjugations["10c"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"+p", "7"})
local inf_stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "ть")
-- present tense stressed stem "моло́ть" - ме́лет
local pres_stem = get_opt_stressed_arg(args, 3)
no_stray_args(args, 3)
local default_pres_stem =
com.make_ending_stressed(nom.strip_ending(inf_stem, nil, "о́"))
pres_stem = pres_stem or default_pres_stem
-- remove accent for some forms
local pres_stem_noa = com.remove_accents(pres_stem)
local pres_note = pres_stem ~= default_pres_stem and IRREG
forms["infinitive"] = inf_stem .. "ть"
-- default for pres_pasv_part is blank
append_participles_2stem(forms, pres_stem, nil, inf_stem, nil,
"ющий", "-", "я́", "вший", "вши", "в", pres_note)
set_moving_ppp(forms, data)
present_je(forms, pres_stem, nil, "c", nil, pres_note)
append_imper(forms, pres_stem_noa, nil, "и́", "и́те", pres_note)
set_past(forms, inf_stem .. "л", nil, "", "а", "о", "и")
return forms
end
conjugations["11a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "ить")
no_stray_args(args, 2)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem .. "и")
forms["infinitive"] = stem .. "ить"
-- perfective only
append_participles(forms, stem, nil, "-", "-", "-", "ивший", "ивши", "ив")
present_je(forms, stem .. "ь", nil, "a")
append_imper(forms, stem .. "ей", nil, "", "те")
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["11b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p", "*"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "и́ть")
local pres_stem = get_opt_unstressed_arg(args, 3)
no_stray_args(args, 3)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem .. "и́", nil, "single_cons_base")
local default_pres_stem =
data.star and construct_long_prefix_variant(prefix) .. rsub(base, "и́$", "") or
stem
pres_stem = pres_stem or default_pres_stem
local pres_note = pres_stem ~= default_pres_stem and IRREG
forms["infinitive"] = stem .. "и́ть"
append_participles_2stem(forms, pres_stem, nil, stem, nil,
"ью́щий", "-", "ья́", "и́вший", "и́вши", "и́в", pres_note)
present_je(forms, pres_stem .. "ь", nil, "b", nil, pres_note)
append_imper(forms, stem .. "е́й", nil, "", "те")
-- e.g. пила́, лила́
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["12a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = get_opt_stressed_arg(args, 3)
no_stray_args(args, 3)
local default_pres_stem = stem
pres_stem = pres_stem or default_pres_stem
local pres_note = pres_stem ~= default_pres_stem and IRREG
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
append_participles_2stem(forms, pres_stem, nil, stem, nil,
"ющий", "емый", "я", "вший", "вши", "в", pres_note)
present_je(forms, pres_stem, nil, "a", nil, pres_note)
append_imper(forms, pres_stem .. "й", nil, "", "те", pres_note)
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["12b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = get_opt_unstressed_arg(args, 3)
no_stray_args(args, 3)
local default_pres_stem = com.make_unstressed_once(stem)
pres_stem = pres_stem or default_pres_stem
local pres_note = pres_stem ~= default_pres_stem and IRREG
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
append_participles_2stem(forms, pres_stem, nil, stem, nil,
"ю́щий", "-", "я́", "вший", "вши", "в", pres_note)
present_je(forms, pres_stem, nil, "b", nil, pres_note)
-- the preceding vowel is stressed
append_imper(forms, pres_stem .. "́й", nil, "", "те", pres_note)
-- e.g. гнила́ but пе́ла
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["13b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"+p"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = nom.strip_ending(stem, nil, "ва́")
no_stray_args(args, 2)
forms["infinitive"] = stem .. "ть"
-- tricky to use append_participles_2stem() because only pres_actv_part
-- uses pres_stem, not all present participles
forms["pres_actv_part"] = pres_stem .. "ю́щий"
forms["pres_pasv_part"] = stem .. "емый"
forms["pres_adv_part"] = stem .. "я"
forms["past_actv_part"] = stem .. "вший"
forms["past_adv_part"] = stem .. "вши"
forms["past_adv_part_short"] = stem .. "в"
set_moving_ppp(forms, data)
present_je(forms, pres_stem, nil, "b")
forms["impr_sg"] = stem .. "й"
forms["impr_pl"] = stem .. "йте"
set_past(forms, stem .. "л", nil, "", "а", "о", "и")
return forms
end
conjugations["14a"] = function(args, data)
-- only one verb: вы́жать
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = get_stressed_arg(args, 3)
no_stray_args(args, 3)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- perfective only
append_participles(forms, stem, nil, "-", "-", "-", "вший", "вши", "в")
present_e_a(forms, pres_stem)
forms["impr_sg"] = pres_stem .. "и"
forms["impr_pl"] = pres_stem .. "ите"
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["14b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = get_unstressed_arg(args, 3)
no_stray_args(args, 3)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
append_participles_2stem(forms, pres_stem, nil, stem, nil,
"у́щий", "-", "я́", "вший", "вши", "в")
present_e_b(forms, pres_stem)
forms["impr_sg"] = pres_stem .. "и́"
forms["impr_pl"] = pres_stem .. "и́те"
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["14c"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local pres_stem = get_stressed_arg(args, 3)
local pres_stem_noa = com.make_unstressed(pres_stem)
no_stray_args(args, 3)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
append_participles_2stem(forms, pres_stem, nil, stem, nil,
"у́щий", "-", "я́", "вший", "вши", "в")
present_e_c(forms, pres_stem)
forms["impr_sg"] = pres_stem_noa .. "и́"
forms["impr_pl"] = pres_stem_noa .. "и́те"
--two forms for past_m: при́нялся, приня́лся
--изъя́ла but приняла́
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["15a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"+p"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "ть")
no_stray_args(args, 2)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, stem, nil, "нущий", "-", "-", "вший", "вши", "в")
present_e_a(forms, stem .. "н")
forms["impr_sg"] = stem .. "нь"
forms["impr_pl"] = stem .. "ньте"
set_past(forms, stem .. "л", nil, "", "а", "о", "и")
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["16a"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "ть")
no_stray_args(args, 2)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, stem, nil, "ву́щий", "-", "-", "вший", "вши", "в")
present_e_a(forms, stem .. "в")
forms["impr_sg"] = stem .. "ви"
forms["impr_pl"] = stem .. "вите"
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["16b"] = function(args, data)
local forms = {}
parse_variants(data, args[1], {"past", "+p"})
local stem = nom.strip_ending(get_stressed_arg(args, 2), nil, "ть")
local stem_noa = com.make_unstressed(stem)
no_stray_args(args, 2)
local prefix, _, base, _ = split_monosyllabic_main_verb(stem)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
append_participles(forms, stem, nil, "ву́щий", "-", "вя́", "вший", "вши", "в")
present_e_b(forms, stem_noa .. "в")
forms["impr_sg"] = stem_noa .. "ви́"
forms["impr_pl"] = stem_noa .. "ви́те"
-- e.g. прижило́сь, прижи́лось
set_past_by_stress(forms, data.past_stress, prefix, nil, base, nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["irreg"] = function(args, data)
local prefix, _, main = split_known_main_verb(get_stressed_arg(args, 2),
-- честь must go before есть
{"бежа́ть", "бѣжа́ть", "хоте́ть", "хотѣ́ть", "да́ть", "че́сть",
"е́сть", "ѣ́сть", "сы́пать", "лга́ть", "мо́чь", "идти́", "йти́",
"е́хать", "ѣ́хать", "мину́ть", "живописа́ть", "ле́чь",
"зи́ждить", "зы́бить", "кля́сть", "стели́ть", "бы́ть", "сса́ть", "сца́ть",
"чти́ть", "шиби́ть", "реве́ть", "има́ть", "вня́ть", "обя́зывать"})
main = com.make_unstressed_once(main)
if not conjugations["irreg-" .. main] then
error("Strange, can't find conjugation for main verb " .. main)
end
return conjugations["irreg-" .. main](args, data)
end
conjugations["irreg-бежать"] = function(args, data)
-- irregular, only for verbs derived from бежать with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2),
{"бежа́ть", "бѣжа́ть"})
data.title = com.is_stressed(prefix) and "5a" or "5b"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "бежа́ть"
append_participles_2stem(forms, "бег", nil, "бежа́", nil,
"у́щий", "-", "-", "вший", "вши", "в", IRREG)
append_imper(forms, "беги́", nil, "", "те", IRREG)
append_pres_futr(forms, "бе", nil,
"гу́" .. IRREG, "жи́шь", "жи́т", "жи́м", "жи́те", "гу́т" .. IRREG)
set_past(forms, "бежа́л", nil, "", "а", "о", "и")
if data.old then
rsub_forms(forms, "^бе", "бѣ")
end
prepend_prefix(forms, prefix)
-- no PPP's for any derivatives of бежать
return forms
end
conjugations["irreg-бѣжать"] = conjugations["irreg-бежать"]
conjugations["irreg-хотеть"] = function(args, data)
-- irregular, only for verbs derived from хотеть with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2),
{"хоте́ть", "хотѣ́ть"})
data.title = "5c'"
data.cat_conj_types = {"5c"} -- no class for 5c', no point in creating for just this verb
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "хоте́ть"
append_participles_2stem(forms, "хот", nil, "хоте́", nil,
"я́щий", "-", "я́", "вший", "вши", "в")
append_imper(forms, "хоти́", nil, "", "те")
append_pres_futr(forms, "", nil,
"хочу́", "хо́чешь" .. IRREG, "хо́чет" .. IRREG, "хоти́м", "хоти́те", "хотя́т")
set_past(forms, "хоте́л", nil, "", "а", "о", "и")
if data.old then
rsub_forms(forms, "^хоте", "хотѣ")
end
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-хотѣть"] = conjugations["irreg-хотеть"]
conjugations["irreg-дать"] = function(args, data)
-- irregular, only for verbs derived from дать with the same stress pattern and вы́дать
local forms = {}
--for this type, it's important to distinguish if it's reflexive to set some stress patterns
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "да́ть")
data.title = com.is_stressed(prefix) and "irreg-a" or "irreg-b"
parse_variants(data, args[1], {"past", "+p"})
no_stray_args(args, 2)
forms["infinitive"] = "да́ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, "", nil, "даю́щий", "-", "-",
"да́вший", "да́вши", "да́в")
append_imper(forms, "да́й", nil, "", "те")
append_pres_futr(forms, "", nil,
"да́м", "да́шь", "да́ст", "дади́м", "дади́те", "даду́т")
prepend_prefix(forms, prefix)
set_past_by_stress(forms, data.past_stress, prefix, nil, "да́", nil,
args, data)
if data.ppp then
if prefix == "пере" then
set_ppp(forms, "", nil, "пе́реданный")
elseif prefix == "раз" then
set_ppp(forms, "", nil, "ро́зданный")
else
set_moving_ppp(forms, data)
end
end
return forms
end
conjugations["irreg-есть"] = function(args, data)
-- irregular, only for verbs derived from есть
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2),
{"е́сть", "ѣ́сть"})
data.title = com.is_stressed(prefix) and "irreg-a" or "irreg-b"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "е́сть"
append_participles_2stem(forms, "ед", nil, "е́", nil,
"я́щий", "о́мый", "я́", "вший", "вши", "в")
if data.ppp then
set_ppp(forms, "е́д", nil, "енный")
end
append_imper(forms, "е́шь", nil, "", "те")
append_pres_futr(forms, "е́", nil,
"м", "шь", "ст", "ди́м", "ди́те", "дя́т")
set_past(forms, "е́л", nil, "", "а", "о", "и")
if data.old then
rsub_forms(forms, "^е", "ѣ")
end
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-ѣсть"] = conjugations["irreg-есть"]
conjugations["irreg-сыпать"] = function(args, data)
-- irregular, only for verbs derived from сыпать
local forms = {}
--for this type, it's important to distinguish if it's reflexive for вы́сыпаться vs. вы́сыпать imperative
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "сы́пать")
data.title = "6a"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "сы́пать"
append_participles(forms, "сы́п", nil,
"лющий", "лемый", {"ля", "я" .. IRREG}, "авший", "авши", "ав")
append_imper(forms, "сы́п", nil,
-- вы́сыпать (but not вы́сыпаться) has two imperative singulars
com.is_stressed(prefix) and not data.refl and {"и", "ь"} or "ь", "ьте", IRREG)
present_je(forms, "сы́пл", nil, "a")
append_pres_futr(forms, "сы́п", nil,
{}, "ешь", "ет", "ем", "ете", {}, IRREG)
set_past(forms, "сы́пал", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
set_moving_ppp(forms, data)
return forms
end
conjugations["irreg-лгать"] = function(args, data)
-- irregular, only for verbs derived from лгать with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "лга́ть")
data.title = "6°b/c"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "лга́ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, "лг", nil,
"у́щий", "-", "-", "а́вший", "а́вши", "а́в")
append_imper(forms, "лги́", nil, "", "те")
append_pres_futr(forms, "", nil,
"лгу́", "лжёшь" .. IRREG, "лжёт" .. IRREG, "лжём" .. IRREG, "лжёте" .. IRREG, "лгу́т")
set_past(forms, "лга́л", nil, "", "а́", "о", "и")
prepend_prefix(forms, prefix)
set_moving_ppp(forms, data)
return forms
end
conjugations["irreg-мочь"] = function(args, data)
-- irregular, only for verbs derived from мочь with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "мо́чь")
data.title = "8c/b"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "мо́чь"
-- no passive or adverbial participles
append_participles(forms, "мо́г", nil,
"у́щий", "-", "-", "ший", "-", "-")
append_imper(forms, "моги́", nil, "", "те")
append_pres_futr(forms, "", nil,
"могу́", "мо́жешь", "мо́жет", "мо́жем", "мо́жете", "мо́гут")
set_past(forms, "мо́г", nil, "", "ла́", "ло́", "ли́")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-идти"] = function(args, data)
-- irregular, only for verbs derived from идти, including прийти́ and в́ыйти
local forms = {}
local prefix = args[2] == "идти́" and "" or
split_known_main_verb(get_stressed_arg(args, 2), "йти́")
data.title = com.is_stressed(prefix) and "irreg-a" or "irreg-b/b"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
-- no pres_pasv_part
if prefix == "" then
-- only идти, present imperfective
forms["infinitive"] = "идти́"
append_imper(forms, "иди́", nil, "", "те")
present_e_b(forms, "ид")
-- no past_adv_part_short
append_participles(forms, "", nil,
"иду́щий", "-", "идя́", "ше́дший", "ше́дши", "-")
elseif rfind(prefix, "и$") then -- при
forms["infinitive"] = "йти́"
append_imper(forms, "ди́", nil, "", "те")
present_e_b(forms, "д")
append_participles(forms, "", nil,
"-", "-", "-", "ше́дший", "ше́дши", "дя́")
else
forms["infinitive"] = "йти́"
append_imper(forms, "йди́", nil, "", "те")
present_e_b(forms, "йд")
append_participles(forms, "", nil,
"-", "-", "-", "ше́дший", "ше́дши", "йдя́")
end
set_past(forms, "", nil, "шёл", "шла́", "шло́", "шли́")
prepend_prefix(forms, prefix)
if data.ppp then
if prefix == "на" or prefix == "про" then
-- найти́ and пройти́ exceptionally have the stress on the prefix
set_ppp(forms, prefix, nil, "́йденный")
else
-- вы́йти and прийти́ are intransitive so we don't have to worry about them
set_ppp(forms, prefix, nil, "йдённый")
end
end
return forms
end
conjugations["irreg-йти"] = conjugations["irreg-идти"]
conjugations["irreg-ехать"] = function(args, data)
-- irregular, only for verbs derived from ехать
local forms = {}
local old = data.old
local prefix = split_known_main_verb(get_stressed_arg(args, 2),
{"е́хать", "ѣ́хать"})
data.title = "irreg-a"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "е́хать"
-- no pres_pasv_part
-- no pres_adv_part
append_participles_2stem(forms, "е́д", nil, "е́х", nil,
"ущий", "-", "-", "авший", "авши", "ав")
present_e_a(forms, "е́д")
set_past(forms, "е́хал", nil, "", "а", "о", "и")
if data.old then
rsub_forms(forms, "^е", "ѣ")
end
prepend_prefix(forms, prefix)
--special-case the imperative
--literary (special) imperative forms for ехать are поезжа́й, поезжа́йте
impstem = data.old and "ѣзжа́й" or "езжа́й"
if prefix == "" then
append_imper(forms, "по" .. impstem, nil, "", "те")
append_imper(forms, impstem, nil, "", "те")
elseif com.is_stressed(prefix) then
append_imper(forms, com.make_unstressed_once(prefix) .. impstem, nil, "", "те")
else
append_imper(forms, prefix .. impstem, nil, "", "те")
end
return forms
end
conjugations["irreg-ѣхать"] = conjugations["irreg-ехать"]
conjugations["irreg-минуть"] = function(args, data)
-- for the irregular verb "мину́ть"
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "мину́ть")
data.title = "3c"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "мину́ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, "ми́н", nil,
"у́щий", "-", "-", "у́вший", "у́вши", "у́в")
present_e_c(forms, "ми́н")
forms["pres_futr_1sg"] = "-" -- no futr 1sg
-- no imperative
-- two possible variants, one with root-only stress, the other with
-- either root or suffix stress.
if not args["root_past_stress"] then
append_past(forms, "мину́л", nil, "", "а", "о", "и")
end
append_past(forms, "ми́нул", nil, "", "а", "о", "и", IRREG)
prepend_prefix(forms, prefix)
set_moving_ppp(forms, data)
return forms
end
conjugations["irreg-живописать"] = function(args, data)
-- for irregular verb "живописа́ть", mixture of types 1 and 2
local forms = {}
local inf = get_stressed_arg(args, 2)
data.title = "1a"
parse_variants(data, args[1], {"+p"})
local inf_stem = nom.strip_ending(inf, nil, "ть")
local pres_stem = rfind(inf_stem, "а́$") and rsub(inf_stem, "а́$", "у́")
or error("Unexpected infinitive " .. inf)
no_stray_args(args, 2)
forms["infinitive"] = inf_stem .. "ть"
-- no pres_pasv_part
append_participles_2stem(forms, pres_stem, nil, inf_stem, nil,
"ющий", "-", "я", "вший", "вши", "в", IRREG)
set_moving_ppp(forms, data)
present_je(forms, pres_stem, nil, "a", nil, IRREG)
append_imper(forms, pres_stem .. "й", nil, "", "те", IRREG)
set_past(forms, inf_stem .. "л", nil, "", "а", "о", "и")
return forms
end
conjugations["irreg-лечь"] = function(args, data)
-- irregular, only for verbs derived from лечь with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "ле́чь")
data.title = "8a/b"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "ле́чь"
-- no pres parts because always perfective
-- no past_adv_part_short
append_participles(forms, "лёг", nil,
"-", "-", "-", "ший", "ши", "-")
append_imper(forms, "ля́г", nil, "", "те", IRREG)
append_pres_futr(forms, "ля́", nil,
"гу", "жешь", "жет", "жем", "жете", "гут", IRREG)
set_past(forms, "", nil, "лёг", "легла́", "легло́", "легли́")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-честь"] = function(args, data)
-- irregular, only for verbs derived from идти, including прийти́ and в́ыйти
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "че́сть")
local pre_two_cons_prefix =
prefix == "об" and "обо" or
prefix == "с" and "со" or
prefix == "рас" and "разо" or
prefix
data.title = prefix == "" and "7b/b" or com.is_stressed(prefix) and "7a⑨" or
pre_two_cons_prefix ~= prefix and "7*b/b⑨" or "7b/b⑨"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
-- no pres_pasv_part
forms["infinitive"] = "че́сть"
append_imper(forms, "чти́", nil, "", "те", IRREG)
present_e_b(forms, "чт", nil, IRREG)
if prefix == "" then
append_participles(forms, "", nil,
"чту́щий", "-", "чтя́", "чти́вший", "чти́вши", "чти́в", IRREG)
elseif com.is_stressed(prefix) then
append_participles(forms, "", nil,
"-", "-", "-", "-", "чтя́", "-", IRREG)
else
append_participles(forms, "", nil,
"-", "-", "-", "-", {"чтя́" .. IRREG, "чётши*"}, "-")
ut.insert_if_not(data.internal_notes, "* Dated.")
end
if data.ppp then
set_ppp(forms, "", nil, "чтённый" .. IRREG)
end
set_past(forms, "", nil, "чёл", "чла́" .. IRREG, "чло́" .. IRREG, "чли́" .. IRREG)
prepend_prefix(forms, prefix, pre_two_cons_prefix)
return forms
end
conjugations["irreg-зиждить"] = function(args, data)
-- irregular, only for verbs derived from зиждить(ся) with the same stress pattern
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "зи́ждить")
data.title = "irreg-a"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "зи́ждить"
append_participles(forms, "зи́жд", nil,
"ущий", "емый", "я", "ивший", "ивши", "ив")
if data.ppp then
set_ppp(forms, "зи́жд", nil, "енный")
end
append_imper(forms, "зи́жди", nil, "", "те")
present_e_a(forms, "зи́жд")
set_past(forms, "зи́ждил", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-зыбить"] = function(args, data)
-- irregular, only for verbs derived from зыбить
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "зы́бить")
data.title = "irreg-a"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "зы́бить"
append_participles(forms, "зы́б", nil,
"лющий", "лемый", "ля", "ивший", "ивши", "ив")
append_imper(forms, "зы́бли", nil, "", "те")
present_je(forms, "зы́б", nil, "a")
set_past(forms, "зы́бил", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-клясть"] = function(args, data)
-- irregular, only for verbs derived from клясть with the same stress pattern
local forms = {}
--for this type, it's important to distinguish if it's reflexive to set some stress patterns
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "кля́сть")
data.title = "irreg-b"
parse_variants(data, args[1], {"past", "+p"})
no_stray_args(args, 2)
forms["infinitive"] = "кля́сть"
append_participles_2stem(forms, "клян", nil, "кля́", nil,
"у́щий", "и́мый", "я́", "вший", "вши", "в")
append_imper(forms, "кляни́", nil, "", "те")
present_e_b(forms, "клян")
prepend_prefix(forms, prefix)
set_past_by_stress(forms, data.past_stress, prefix, nil, "кля́", nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["irreg-стелить"] = function(args, data)
-- irregular, only for verbs derived from стелить
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "стели́ть")
data.title = com.is_stressed(prefix) and "4a" or "4c"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "стели́ть"
append_participles(forms, "сте́л", nil,
"ющий" .. IRREG, "и́мый", "я́", "и́вший", "и́вши", "и́в")
set_class_4_ppp(forms, data, "сте́л", nil, data.title)
append_imper(forms, "стели́", nil, "", "те")
append_pres_futr(forms, "сте́л", nil, "ю́", {}, {}, {}, {}, {})
append_pres_futr(forms, "сте́л", nil, {}, "ешь", "ет", "ем", "ете", "ют", IRREG)
set_past(forms, "стели́л", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-быть"] = function(args, data)
-- irregular, only for verbs derived from быть with various stress patterns, the actual verb быть different from its derivatives
local forms = {}
--for this type, it's important to distinguish if it's reflexive to set some stress patterns
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "бы́ть")
data.title = "irreg-a"
parse_variants(data, args[1], {"past", "+p"})
no_stray_args(args, 2)
forms["infinitive"] = "бы́ть"
-- no pres_pasv_part
append_participles(forms, "", nil, "су́щий", "-", "бу́дучи",
"бы́вший", "бы́вши", "бы́в")
append_imper(forms, "бу́дь", nil, "", "те")
prepend_prefix(forms, prefix)
-- only for "бы́ть", some forms are archaic
if forms["infinitive"] == "бы́ть" then
append_pres_futr(forms, "", nil, "есть", "есть", "есть", "есть", "есть", "есть")
elseif com.is_stressed(prefix) then
-- if the prefix is stressed, e.g. "вы́быть"
present_e_a(forms, prefix .. "буд")
else
present_e_a(forms, prefix .. "бу́д")
end
set_past_by_stress(forms, data.past_stress, prefix, nil, "бы́", nil,
args, data)
set_ppp_from_past_m(forms, args, data)
return forms
end
conjugations["irreg-ссать-сцать"] = function(args, data)
-- irregular, only for verbs derived from ссать and сцать (both vulgar!)
local forms = {}
local prefix, _, stem = split_known_main_verb(get_stressed_arg(args, 2),
{"сса́ть", "сца́ть"})
data.title = com.is_stressed(prefix) and "irreg-a" or "irreg-b"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
stem = nom.strip_ending(stem, nil, "ть")
local pres_stem = rsub(stem, "а́?$", "")
no_stray_args(args, 2)
forms["infinitive"] = stem .. "ть"
-- no pres_pasv_part
-- no pres_adv_part
append_participles(forms, pres_stem, nil, "у́щий", "-", "-",
"а́вший", "а́вши", "а́в")
append_imper(forms, pres_stem, nil, "ы́", "ы́те")
append_pres_futr(forms, pres_stem, nil,
"у́", "ы́шь", "ы́т", "ы́м", "ы́те", "у́т")
set_past(forms, stem .. "л", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-ссать"] = conjugations["irreg-ссать-сцать"]
conjugations["irreg-сцать"] = conjugations["irreg-ссать-сцать"]
conjugations["irreg-чтить"] = function(args, data)
-- irregular, only for verbs derived from чтить
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "чти́ть")
data.title = "4b"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "чти́ть"
append_participles_2stem(forms, "чт", nil, "чти́", nil,
{"я́щий", "у́щий" .. IRREG}, "и́мый", "я́", "вший", "вши", "в")
if data.ppp then
set_ppp(forms, "чт", nil, "ённый")
end
append_imper(forms, "чти́", nil, "", "те")
append_pres_futr(forms, "чт", nil,
"у́" .. IRREG, "и́шь", "и́т", "и́м", "и́те", {"я́т", "у́т" .. IRREG})
set_past(forms, "чти́л", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-шибить"] = function(args, data)
-- irregular, only for verbs in -шибить(ся)
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "шиби́ть")
data.title = com.is_stressed(prefix) and "irreg-a" or "irreg-b"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
-- no present participles
forms["infinitive"] = "шиби́ть"
append_participles(forms, "шиби́", nil,
"-", "-", "-", "вший", "вши", "в")
if data.ppp then
set_ppp(forms, "ши́бл", nil, "енный")
end
append_imper(forms, "шиби́", nil, "", "те")
present_e_b(forms, "шиб")
set_past(forms, "ши́б", nil, "", "ла", "ло", "ли")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-реветь"] = function(args, data)
-- irregular, only for verbs derived from "реветь"
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "реве́ть")
data.title = "irreg-b"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "реве́ть"
-- no pres_pasv_part
append_participles_2stem(forms, "рев", nil, "реве́", nil,
"у́щий", "-", "я́", "вший", "вши", "в")
present_e_b(forms, "рев")
append_imper(forms, "реви́", nil, "", "те")
set_past(forms, "реве́л", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-имать"] = function(args, data)
-- irregular, only for внимать and certain archaic verbs (e.g. имать as
-- conjugated in the 18th century, отъимать)
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "има́ть")
data.title = "1a // 6a"
data.cat_conj_types = {"1a", "6a"}
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "има́ть"
-- handle внемл- forms
append_participles(forms, "е́мл", nil,
"ющий", "емый", {"я", "я́"}, {}, {}, {})
-- handle внима́- forms
append_participles(forms, "има́", nil,
"ющий", "емый", "я", "вший", "вши", "в")
if data.ppp then
-- FIXME, do class-1a-type ppp's (e.g. вни́манный) exist?
-- ruwikt marks them with a *
set_ppp(forms, "е́мл", nil, "енный")
end
append_imper(forms, "", nil, {"е́мли", "емли́", "има́й"},
{"е́млите", "емли́те", "има́йте"})
present_je(forms, "е́мл", nil, "a")
-- Both вне́млю and внемлю́ are possible
append_pres_futr(forms, "емл", nil, "ю́", {}, {}, {}, {}, {})
present_je(forms, "има́", nil, "a")
set_past(forms, "има́л", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-внять"] = function(args, data)
-- irregular, only for внять
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "вня́ть")
data.title = "14c/c"
parse_variants(data, args[1], {"+p"})
no_stray_args(args, 2)
forms["infinitive"] = "вня́ть"
-- perfective only; no present participles
append_participles(forms, "вня́", nil,
"-", "-", "-", "вший", "вши", "в")
append_imper(forms, "вними́", nil, "", "те")
append_imper(forms, "вонми́", nil, "", "те")
present_e_c(forms, "вни́м")
present_e_c(forms, "во́нм")
set_past(forms, "вня́л", nil, "", "а́", "о", "и")
set_ppp_from_past_m(forms, args, data)
prepend_prefix(forms, prefix)
return forms
end
conjugations["irreg-обязывать"] = function(args, data)
-- irregular, only for обязывать and обязываться
local forms = {}
local prefix = split_known_main_verb(get_stressed_arg(args, 2), "обя́зывать")
data.title = "1a"
-- no past passive participles of any verbs of this type
parse_variants(data, args[1], {})
no_stray_args(args, 2)
forms["infinitive"] = "обя́зывать"
append_participles_2stem(forms, "обя́з", nil, "обя́зыва", nil,
{"ывающий", "у́ющий"}, {"ываемый", "у́емый"}, {"ывая", "у́я"}, "вший", "вши", "в")
append_imper(forms, "обя́зывай", nil, "", "те")
append_imper(forms, "обязу́й", nil, "", "те")
present_je(forms, "обя́зыва", nil, "a")
present_je(forms, "обязу́", nil, "a")
set_past(forms, "обя́зывал", nil, "", "а", "о", "и")
prepend_prefix(forms, prefix)
return forms
end
--[=[
Partial conjugation functions
]=]
-- Present forms with -e-, no j-vowels.
present_e_a = function(forms, stem, tr, note)
append_pres_futr(forms, stem, tr, "у", "ешь", "ет", "ем", "ете", "ут", note)
end
present_e_b = function(forms, stem, tr, note)
append_pres_futr(forms, stem, tr, "у́", "ёшь", "ёт", "ём", "ёте", "у́т", note)
end
present_e_c = function(forms, stem, tr, note)
append_pres_futr(forms, stem, tr, "у́", "ешь", "ет", "ем", "ете", "ут", note)
end
-- Present forms with -e- and iotated stem. ABC = "a", "b" or "c", indicating
-- the accent pattern. If SHCH is set, iotate final т as щ, not ч. If NOTE
-- is given, add it to each form.
present_je = function(forms, stem, tr, abc, shch, note)
local iotated_stem, iotated_tr = com.iotation(stem, tr, shch)
assert(abc == "a" or abc == "b" or abc == "c")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local hushing = rfind(iotated_stem, "[шщжч]$") -- or no_iotation
local ending_1sg =
hushing and (abc == "a" and "у" or "у́") or
not hushing and (abc == "a" and "ю" or "ю́")
if abc == "b" then
append_pres_futr(forms, iotated_stem, iotated_tr,
{}, "ёшь", "ёт", "ём", "ёте", (hushing and "у́т" or "ю́т"), note)
else
append_pres_futr(forms, iotated_stem, iotated_tr,
{}, "ешь", "ет", "ем", "ете", (hushing and "ут" or "ют"), note)
end
append_pres_futr(forms, iotated_stem, iotated_tr,
ending_1sg, {}, {}, {}, {}, {}, note)
end
-- Present forms with -i- (and iotated stem in the 1sg). ABC = "a", "b" or "c",
-- indicating the accent pattern. If SHCH is set, iotate final т as щ, not ч.
-- If NOTE is given, add it to each form.
present_i = function(forms, stem, tr, abc, shch, note)
local iotated_stem, iotated_tr = com.iotation(stem, tr, shch)
assert(abc == "a" or abc == "b" or abc == "c")
-- Verbs ending in a hushing consonant do not get j-vowels in the endings.
local iotated_hushing = rfind(iotated_stem, "[шщжч]$")
local hushing = rfind(stem, "[шщжч]$")
local ending_1sg =
iotated_hushing and (abc == "a" and "у" or "у́") or
not iotated_hushing and (abc == "a" and "ю" or "ю́")
if abc == "b" then
append_pres_futr(forms, stem, tr,
{}, "и́шь", "и́т", "и́м", "и́те", hushing and "а́т" or "я́т", note)
else
append_pres_futr(forms, stem, tr,
{}, "ишь", "ит", "им", "ите", hushing and "ат" or "ят", note)
end
append_pres_futr(forms, iotated_stem, iotated_tr,
ending_1sg, {}, {}, {}, {}, {}, note)
end
-- Add the reflexive particle to all verb forms
make_reflexive = function(forms, reflex_stress)
for key, form in pairs(forms) do
local ru, tr = extract_russian_tr(form)
-- check for empty string, dashes and nil's
if ru and ru ~= "" and ru ~= "-" then
local ruentry, runotes = m_table_tools.separate_notes(ru)
local trentry, trnotes
if tr then
trentry, trnotes = m_table_tools.separate_notes(tr)
end
if is_vowel_stem(ruentry) then
forms[key] = {ruentry .. "сь" .. runotes, trentry and trentry .. "sʹ" .. trnotes}
-- if a past_m form doesn't contain a stress, add a stressed
-- particle "ся́" if called for
elseif reflex_stress and com.is_unstressed(ruentry) and rfind(key, "^past_m") then
forms[key] = {ruentry .. "ся́" .. runotes, trentry and trentry .. "sja" .. AC .. trnotes}
else
forms[key] = {ruentry .. "ся" .. runotes, trentry and trentry .. "sja" .. trnotes}
end
end
end
end
-- Convert verb forms to pre-reform style by adding ъ to consonant-final
-- forms (excluding those ending in й and ь) and converting -ий to -ій and
-- -ийся to -ійся
make_pre_reform = function(forms)
for key, form in pairs(forms) do
local ru, tr = extract_russian_tr(form)
-- check for empty string, dashes and nil's
if ru and ru ~= "" and ru ~= "-" then
local ruentry, runotes = m_table_tools.separate_notes(ru)
if rfind(ruentry, "[бцдфгчклмнпрствшхзжщ]$") then
forms[key] = {ruentry .. "ъ" .. runotes, tr}
else
forms[key] = {rsub(rsub(ruentry, "ий$", "ій"), "ийся$", "ійся") .. runotes, tr}
end
end
end
end
local function setup_pres_futr(forms, perf, old)
-- Copy the main form FROMFORM to the main form TOFORM, and copy all
-- associated alternative forms.
local function copy_form(fromform, toform)
local fromforms = main_to_all_verb_forms[fromform]
local toforms = main_to_all_verb_forms[toform]
local numforms = #fromforms
assert(#toforms == numforms)
for i=1,numforms do
forms[toforms[i]] = forms[fromforms[i]]
end
end
-- Copy pres_futr_* to pres_* (imperfective) or futr_* (perfective).
if perf then
copy_form("pres_futr_1sg", "futr_1sg")
copy_form("pres_futr_2sg", "futr_2sg")
copy_form("pres_futr_3sg", "futr_3sg")
copy_form("pres_futr_1pl", "futr_1pl")
copy_form("pres_futr_2pl", "futr_2pl")
copy_form("pres_futr_3pl", "futr_3pl")
else
copy_form("pres_futr_1sg", "pres_1sg")
copy_form("pres_futr_2sg", "pres_2sg")
copy_form("pres_futr_3sg", "pres_3sg")
copy_form("pres_futr_1pl", "pres_1pl")
copy_form("pres_futr_2pl", "pres_2pl")
copy_form("pres_futr_3pl", "pres_3pl")
end
local futr_data = {
{"futr_1sg", "бу́ду", "búdu"},
{"futr_2sg", "бу́дешь", "búdešʹ"},
{"futr_3sg", "бу́дет" .. (old and "ъ" or ""), "búdet"},
{"futr_1pl", "бу́дем" .. (old and "ъ" or ""), "búdem"},
{"futr_2pl", "бу́дете", "búdete"},
{"futr_3pl", "бу́дут" .. (old and "ъ" or ""), "búdut"}
}
local function insert_future(inf, inf_tr)
for _, fut in ipairs(futr_data) do
append_to_arg_chain(forms, fut[1], fut[1],
{fut[2] .. inf, inf_tr and fut[3] .. inf_tr})
end
end
-- Insert future, if required (there may conceivably be multiple infitives).
for _, form in ipairs(main_to_all_verb_forms["infinitive"]) do
local infinitive = forms[form]
if infinitive then
local inf, inf_tr = extract_russian_tr(forms[form])
-- only for "бы́ть" the future forms are бу́ду, бу́дешь, etc.
if inf == "бы́ть" then
insert_future("", nil)
elseif not perf then
insert_future(" " .. inf, inf_tr and " " .. inf_tr)
end
end
end
end
parse_and_stress_override = function(form, val, existing, all_existing)
if rfind(form, "^pres_futr") then
error("Overrides of pres_futr* are illegal, use pres_* or futr_*")
end
local allow_unaccented
val, allow_unaccented = rsubb(val, "^%*", "")
local ru, tr = nom.split_russian_tr(val)
-- past_m can be unaccented in connection with reflex_stress=ся́
if not allow_unaccented and not rfind(form, "^past_m") then
if tr and com.is_unstressed(ru) ~= com.is_unstressed(tr) then
error("Override " .. form .. "=" .. ru .. " and translit " .. tr .. " must have same accent pattern")
end
if com.is_monosyllabic(ru) then
ru, tr = com.make_ending_stressed(ru, tr)
elseif com.needs_accents(ru) then
error("Override " .. form .. "=" .. ru .. " requires an accent")
end
end
if rfind(ru, "%+") then
-- If either the existing or override has manual translit, the resulting
-- form should have manual translit. We specify ALWAYS_TRANSLIT if
-- the override has manual translit, so that we can substitute the
-- existing translit into the override translit.
local existing_ru, existing_tr = extract_russian_tr(existing, not not tr)
-- used especially for present participles; substitute existing form,
-- minus any "awkward-" or "none-" prefixes.
ru = rsub(ru, "%+", strip_arg_status_prefix(existing_ru))
-- If there's existing translit but not in the override, make sure it's
-- carried along.
if existing_tr and not tr then
tr = com.translit(ru)
end
tr = tr and rsub(tr, "%+", strip_arg_status_prefix(existing_tr))
end
-- If there's an override and it doesn't match an existing form, it's
-- irregular and indicate it using the IRREG marker. We don't do this if
-- the override simply removes a form. We do do this if there aren't any
-- existing forms, on the theory that the presence of a form when none is
-- normally called for is an irregularity. When comparing against the
-- existing forms, strip any status prefix (e.g. 'awkward-').
if all_existing then
local all_existing_stripped = {}
for _, ae in ipairs(all_existing) do
local existing_ru, existing_tr = extract_russian_tr(ae)
existing_ru = strip_arg_status_prefix(existing_ru)
existing_tr = existing_tr and strip_arg_status_prefix(existing_tr)
table.insert(all_existing_stripped, {existing_ru, existing_tr})
end
if ru ~= "-" and not contains_form(all_existing_stripped, {ru, tr}) then
ru = ru .. IRREG
tr = tr and tr .. IRREG
end
end
return {ru, tr}
end
-- Set up pres_* or futr_*; handle *sym/*tail/*tailall notes and overrides.
handle_forms_and_overrides = function(args, forms, data)
setup_pres_futr(forms, data.perf, data.old)
local function append_value(forms, prop, value)
if forms[prop] and forms[prop] ~= "" and forms[prop] ~= "-" then
value = nom.split_russian_tr(value, "dopair")
local curval = forms[prop]
if type(curval) == "string" then
curval = {curval}
end
forms[prop] = nom.concat_paired_russian_tr(curval, value)
end
end
local function append_note_all(forms, proplist, value)
for _, prop in ipairs(proplist) do
append_value(forms, prop, value)
end
end
local function append_note_last(forms, proplist, value, gt_one)
local numprops = 0
local lastprop
-- Find the last property in the series with a value
for _, prop in ipairs(proplist) do
if forms[prop] and forms[prop] ~= "" and forms[prop] ~= "-" then
numprops = numprops + 1
lastprop = prop
end
end
if numprops > (gt_one and 1 or 0) then
append_value(forms, lastprop, value)
end
end
for _, proplist in ipairs(all_verb_forms) do
local vallist = {}
-- Handle PROP_sym, which applies to all overridable properties, including
-- alternative forms, and applies to exactly that property.
for _, prop in ipairs(proplist) do
if args[prop .. "_sym"] then
append_value(forms, prop, args[prop .. "_sym"])
end
end
local propname = proplist[1]
-- Handle PROP_tail, which applies to a series of properties (e.g. past_m,
-- past_m2, ...) and appends to the last one.
if args[propname .. "_tail"] then
append_note_last(forms, proplist, args[propname .. "_tail"])
end
-- Handle PROP_tailall, which applies to a series of properties and
-- appends to all.
if args[propname .. "_tailall"] then
append_note_all(forms, proplist, args[propname .. "_tailall"])
end
end
-- Now handle pasttail, pasttailall, prestail, prestailall, etc.
-- Table listing tail-arg prefix and corresponding verb forms.
local tailargs = {
{"past", past_verb_forms},
{"pres", pres_verb_forms},
{"futr", futr_verb_forms},
{"impr", impr_verb_forms},
{"part", part_verb_forms},
{"prespart", pres_part_verb_forms},
{"pastpart", past_part_verb_forms},
{"", all_main_verb_forms}
}
for _, tailspec in ipairs(tailargs) do
tailforms = tailspec[2]
-- Handle the ...tail variants.
tailarg = tailspec[1] .. "tail"
if args[tailarg] then
track(tailarg)
for _, prop in ipairs(tailforms) do
append_note_last(forms, main_to_all_verb_forms[prop], args[tailarg], ">1")
end
end
-- Handle the ...tailall variants.
tailallarg = tailspec[1] .. "tailall"
if args[tailallarg] then
track(tailallarg)
for _, prop in ipairs(tailforms) do
append_note_all(forms, main_to_all_verb_forms[prop], args[tailallarg])
end
end
end
--handle overrides (formerly we only had past_pasv_part as a
--general override, plus scattered main-form overrides in particular
--conjugation classes)
for _, all_forms in pairs(main_to_all_verb_forms) do
local i = 0
local orig_forms = {}
for _, form in ipairs(all_forms) do
if forms[form] then
table.insert(orig_forms, forms[form])
end
end
for _, form in ipairs(all_forms) do
i = i + 1
-- If we auto-generated the past passive participle in order to
-- check for irregular overrides, make sure to erase any such
-- participles that weren't overridden. This happens for example
-- in обнять, where there are two automatically generated past
-- passive participles but a single ppp=о́внятый override.
local override = args[form] or (
data.ppp_auto_generated and rfind(form, "^past_pasv_part") and "-"
)
if override then
forms[form] = parse_and_stress_override(form, override,
forms[form], orig_forms)
elseif i == 1 then
forms[form] = forms[form] or ""
end
end
end
end
-- Finish generating the forms; primarily, clear out unused forms.
finish_generating_forms = function(forms, data)
-- Convert any main form that's nil (meaning no forms at all corresponding
-- to this main form) to the empty string.
for main_form, _ in pairs(main_to_all_verb_forms) do
if not forms[main_form] then
forms[main_form] = ""
end
end
-- Set the main form FORM to the empty string, and corresponding alt forms
-- to nil.
local function clear_form(form)
local i = 0
for _, altform in ipairs(main_to_all_verb_forms[form]) do
i = i + 1
if i == 1 then
forms[altform] = ""
else
forms[altform] = nil
end
end
end
-- Intransitive and reflexive verbs have no passive participles
-- (unless has_prpp=y and/or has_ppp=y).
if data.intr or data.refl then
if not data.has_prpp then
clear_form("pres_pasv_part")
end
if not data.has_ppp then
clear_form("past_pasv_part")
end
end
if data.refl then
-- no past_adv_part_short for reflexive verbs
clear_form("past_adv_part_short")
end
-- Impersonal verbs normally have no passive participles, but allow them
-- if there's specifically an override. We only do this for the present
-- passive participle because the past passive participle isn't inserted
-- by default, and we still want +p to work, which doesn't currently set
-- data.ppp_override.
if data.impers and not data.prpp_override then
clear_form("pres_pasv_part")
end
if data.impers then
clear_form("pres_1sg")
clear_form("pres_2sg")
clear_form("pres_1pl")
clear_form("pres_2pl")
clear_form("pres_3pl")
clear_form("futr_1sg")
clear_form("futr_2sg")
clear_form("futr_1pl")
clear_form("futr_2pl")
clear_form("futr_3pl")
clear_form("past_m")
clear_form("past_f")
clear_form("past_pl")
clear_form("past_m_short")
clear_form("past_f_short")
clear_form("past_pl_short")
clear_form("pres_actv_part")
clear_form("past_actv_part")
clear_form("pres_adv_part")
clear_form("past_adv_part")
clear_form("past_adv_part_short")
clear_form("impr_sg")
clear_form("impr_pl")
end
-- Perfective and iterative verbs have no present forms, as well as
-- verbs marked nopres=1.
if data.perf or data.iter or data.nopres then
clear_form("pres_actv_part")
clear_form("pres_pasv_part")
clear_form("pres_adv_part")
clear_form("pres_1sg")
clear_form("pres_2sg")
clear_form("pres_3sg")
clear_form("pres_1pl")
clear_form("pres_2pl")
clear_form("pres_3pl")
end
-- Some verbs (e.g. грясти́, густи́) have no past
if data.nopast then
clear_form("past_m")
clear_form("past_f")
clear_form("past_n")
clear_form("past_pl")
clear_form("past_m_short")
clear_form("past_f_short")
clear_form("past_n_short")
clear_form("past_pl_short")
clear_form("past_actv_part")
clear_form("past_pasv_part")
clear_form("past_adv_part")
clear_form("past_adv_part_short")
end
-- Iterative verbs and verbs marked noimpr=1 have no imperative forms.
if data.iter or data.noimpr then
clear_form("impr_sg")
clear_form("impr_pl")
end
-- Iterative verbs and verbs marked nofutr=1 have no future forms.
if data.iter or data.nofutr then
clear_form("futr_1sg")
clear_form("futr_2sg")
clear_form("futr_3sg")
clear_form("futr_1pl")
clear_form("futr_2pl")
clear_form("futr_3pl")
end
--handle "none-" and "awkward-" prefixes (used especially for pres_pasv_part)
local footnote_sym = nil
for _, all_forms in pairs(main_to_all_verb_forms) do
local i = 0
for _, form in ipairs(all_forms) do
i = i + 1
if forms[form] then
local formru, formtr = extract_russian_tr(forms[form])
if rfind(formru, "^none%-") then
if i == 1 then
forms[form] = ""
else
forms[form] = nil
end
elseif rfind(formru, "^awkward%-") then
if not footnote_sym then
footnote_sym = next_note_symbol(data)
ut.insert_if_not(data.internal_notes, footnote_sym .. " Rare and awkward.")
end
forms[form] = {rsub(formru, "^awkward%-", "") .. footnote_sym,
formtr and rsub(formtr, "^awkward%-", "") .. footnote_sym}
end
end
end
end
--Insert footnote for IRREG symbol if present.
for _, all_forms in pairs(main_to_all_verb_forms) do
for _, form in ipairs(all_forms) do
if forms[form] then
local formru, formtr = extract_russian_tr(forms[form])
if rfind(formru, IRREG) then
ut.insert_if_not(data.internal_notes, IRREG .. " Irregular.")
end
end
end
end
end
local accel_forms = {
-- present tense
pres_1sg = "1|s|pres|ind",
pres_2sg = "2|s|pres|ind",
pres_3sg = "3|s|pres|ind",
pres_1pl = "1|p|pres|ind",
pres_2pl = "2|p|pres|ind",
pres_3pl = "3|p|pres|ind",
-- future tense
futr_1sg = "1|s|fut|ind",
futr_2sg = "2|s|fut|ind",
futr_3sg = "3|s|fut|ind",
futr_1pl = "1|p|fut|ind",
futr_2pl = "2|p|fut|ind",
futr_3pl = "3|p|fut|ind",
-- imperative
impr_sg = "2|s|imp",
impr_pl = "2|p|imp",
-- past
past_m = "m|s|past|ind",
past_f = "f|s|past|ind",
past_n = "n|s|past|ind",
past_pl = "p|past|ind",
past_m_short = "short|m|s|past|ind",
past_f_short = "short|f|s|past|ind",
past_n_short = "short|n|s|past|ind",
past_pl_short = "short|p|past|ind",
-- active participles
pres_actv_part = "pres|act|part",
past_actv_part = "past|act|part",
-- passive participles
pres_pasv_part = "pres|pass|part",
past_pasv_part = "past|pass|part",
-- adverbial participles
pres_adv_part = "pres|adv|part",
past_adv_part = "past|adv|part",
past_adv_part_short = "short|past|adv|part",
-- infinitive
infinitive = "inf",
}
-- Make the table
make_table = function(forms, title, perf, intr, impers, notes, internal_notes, old)
local infinitives = {}
for _, form in ipairs(main_to_all_verb_forms["infinitive"]) do
local infinitive = forms[form]
if infinitive then
local inf, inf_tr = extract_russian_tr(forms[form])
if inf ~= "-" then
ut.insert_if_not(infinitives, inf)
end
end
end
-- Group forms together for a given key and combine adjacent forms with the same
-- Russian (they should always have different translits). Take care not to introduce
-- manual translit unnecessarily.
local grouped_forms = {}
for dispform, sourceforms in pairs(disp_verb_form_map) do
local entry = {}
for _, form in ipairs(sourceforms) do
local ru, tr = extract_russian_tr(forms[form])
-- check for empty strings, dashes and nil's
if ru and ru ~= "" and ru ~= "-" and ru ~= "—" then
if #entry > 0 then
local lastru, lasttr = extract_russian_tr(entry[#entry])
if lastru == ru then
if not lasttr and not tr or lasttr == tr then
error("Russian form " .. ru .. " is duplicated, probably due to a duplicative override")
end
lasttr = lasttr or com.translit(lastru)
tr = tr or com.translit(ru)
entry[#entry] = {ru, lasttr .. " ''or'' " .. tr}
else
table.insert(entry, {ru, tr})
end
else
table.insert(entry, {ru, tr})
end
end
end
grouped_forms[dispform] = entry
end
local title = (old and "Pre-reform conjugation" or "Conjugation") .. (#infinitives == 0 and "" or
" of <span lang=\"ru\" class=\"Cyrl\">''" .. table.concat(infinitives, ", ") .. "''</span>") ..
(title and " (" .. title .. ")" or "")
local function add_links(ru, rusuf, runotes, tr, trnotes, accel)
local ruspan
if old then
ruspan = m_links.full_link({lang = lang, term = com.remove_jo(ru), accel = accel,
alt = not ru:find("[[", 1, true) and ru, tr = "-"})
else
ruspan = m_links.full_link({lang = lang, term = ru, accel = accel, tr = "-"})
end
if rusuf ~= "" then
rusuf = "<span lang=\"ru\" class=\"Cyrl\">" .. rusuf .. "</span>"
end
return ruspan .. rusuf .. runotes .. "<br/>" .. require("Modül:alfabe araçları").tag_translit(tr .. trnotes, lang, "default", 'style="color: #888"')
end
-- NOTE: No need to check for multiple infinitives because the accel system
-- doesn't support multiple lemmas.
local lemma, lemmatr = extract_russian_tr(forms["infinitive"])
-- check for empty strings, dashes and nil's
if lemma and lemma ~= "" and lemma ~= "-" and lemma ~= "—" then
lemma, _ = m_table_tools.separate_notes(lemma)
if lemmatr then
lemmatr, _ = m_table_tools.separate_notes(lemmatr)
end
else
-- In case the lemma is an empty string or dash, set to nil so we don't
-- set a lemma in the accelerator and fall back to the page name.
lemma = nil
lemmatr = nil
end
-- Convert to displayed form
local disp = {}
for key, entry in pairs(grouped_forms) do
for i, form in ipairs(entry) do
local ru, origtr = extract_russian_tr(form)
local tr = origtr or ru and com.translit(ru)
local ruentry, runotes = m_table_tools.get_notes(ru)
local trentry, trnotes = m_table_tools.get_notes(tr)
local accel_form = accel_forms[key]
if not accel_form then
error("Unrecognized key " .. key .. " when looking up accelerator form")
end
local accel
if origtr and origtr:find(" ''or'' ") then
-- Multiple translits for a given Russian term.
-- FIXME! Support this.
accel = nil
else
accel = { form = accel_form, translit = origtr,
lemma = lemma, lemma_translit = lemmatr}
end
if rfind(key, "^futr") then
-- Add link to first word (form of 'to be')
tobe, inf = rmatch(ruentry, "^([^ ]*) ([^ ]*)$")
if tobe then
-- No accelerators for imperfective future, as it's just the future of "to be"
-- plus the infinitive.
entry[i] = add_links(tobe, " " .. inf, runotes, trentry, trnotes, nil)
else
entry[i] = add_links(ruentry, "", runotes, trentry, trnotes, accel)
end
else
entry[i] = add_links(ruentry, "", runotes, trentry, trnotes, accel)
end
end
disp[key] = table.concat(entry, ",<br/>")
if disp[key] == "" then
disp[key] = "—"
end
end
local all_notes = {}
for _, note in ipairs(internal_notes) do
local symbol, entry = m_table_tools.get_initial_notes(note)
table.insert(all_notes, symbol .. entry)
end
for _, note in ipairs(notes) do
local symbol, entry = m_table_tools.get_initial_notes(note)
table.insert(all_notes, symbol .. entry)
end
local notes_text
table.insert(all_notes, 1,
"Note: For declension of participles, see their entries. Adverbial participles are indeclinable.")
notes_text = table.concat(all_notes, "<br />") .. "\n"
return require("Modül:TemplateStyles")("Modül:ru-eylem/style.css") ..
[=[<div class="NavFrame" style="width:49.6em;">
<div class="NavHead" style="text-align:left; background:#e0e0ff;">]=] .. title .. [=[</div>
<div class="NavContent">
{| class="inflection inflection-ru inflection-verb inflection-table"
|+ ]=] .. notes_text .. [=[
|- class="rowgroup"
! colspan="3" | ]=] .. (perf and [=[[[совершенный вид|perfective aspect]]]=] or [=[[[несовершенный вид|imperfective aspect]]]=]) .. [=[
|-
! [[неопределённая форма|infinitive]]
| colspan="2" | ]=] .. disp.infinitive .. [=[
|- class="rowgroup"
! style="width:15em" | [[причастие|participles]]
! [[настоящее время|present tense]]
! [[прошедшее время|past tense]]
|-
! [[действительный залог|active]]
| ]=] .. disp.pres_actv_part .. [=[ || ]=] .. disp.past_actv_part .. [=[
|-
! [[страдательный залог|passive]]
| ]=] .. disp.pres_pasv_part .. [=[ || ]=] .. disp.past_pasv_part .. [=[
|-
! [[деепричастие|adverbial]]
| ]=] .. disp.pres_adv_part .. [=[ || ]=] .. disp.past_adv_part .. [=[
|- class="rowgroup"
!
! [[настоящее время|present tense]]
! [[будущее время|future tense]]
|-
! [[первое лицо|1st]] [[единственное число|singular]] (<span lang="ru" class="Cyrl">я</span>)
| ]=] .. disp.pres_1sg .. [=[ || ]=] .. disp.futr_1sg .. [=[
|-
! [[второе лицо|2nd]] [[единственное число|singular]] (<span lang="ru" class="Cyrl">ты</span>)
| ]=] .. disp.pres_2sg .. [=[ || ]=] .. disp.futr_2sg .. [=[
|-
! [[третье лицо|3rd]] [[единственное число|singular]] (<span lang="ru" class="Cyrl">он/она́/оно́</span>)
| ]=] .. disp.pres_3sg .. [=[ || ]=] .. disp.futr_3sg .. [=[
|-
! [[первое лицо|1st]] [[множественное число|plural]] (<span lang="ru" class="Cyrl">мы</span>)
| ]=] .. disp.pres_1pl .. [=[ || ]=] .. disp.futr_1pl .. [=[
|-
! [[второе лицо|2nd]] [[множественное число|plural]] (<span lang="ru" class="Cyrl">вы</span>)
| ]=] .. disp.pres_2pl .. [=[ || ]=] .. disp.futr_2pl .. [=[
|-
! [[третье лицо|3rd]] [[множественное число|plural]] (<span lang="ru" class="Cyrl">они́</span>)
| ]=] .. disp.pres_3pl .. [=[ || ]=] .. disp.futr_3pl .. [=[
|- class="rowgroup"
! [[повелительное наклонение|imperative]]
! [[единственное число|singular]]
! [[множественное число|plural]]
|-
!
| ]=] .. disp.impr_sg .. [=[ || ]=] .. disp.impr_pl .. [=[
|- class="rowgroup"
! [[прошедшее время|past tense]]
! [[единственное число|singular]]
! [[множественное число|plural]]<br/>(<span lang="ru" class="Cyrl">мы/вы/они́</span>)
|-
! [[мужской род|masculine]] (<span lang="ru" class="Cyrl">я/ты/он</span>)
| ]=] .. disp.past_m .. [=[ || rowspan="3" | ]=] .. disp.past_pl .. [=[
|-
! [[женский род|feminine]] (<span lang="ru" class="Cyrl">я/ты/она́</span>)
| ]=] .. disp.past_f .. [=[
|-
! style="background-color: #ffffe0;" | [[средний род|neuter]] (<span lang="ru" class="Cyrl">оно́</span>)
| ]=] .. disp.past_n .. [=[
|}
</div>
</div>]=]
end
return export
-- For Vim, so we get 4-space tabs
-- vim: set ts=4 sw=4 noet:
gcr17s4n934y6n22i13264uu1outam8
Modül:require when needed
828
1591008
5672501
2026-06-29T15:12:10Z
MustafaCavlak
59368
imported from en
5672501
Scribunto
text/plain
local getmetatable = getmetatable
local ipairs = ipairs
local loaded = package.loaded
local pairs = pairs
local require = require
local select = select
local setmetatable = setmetatable
local tostring = tostring
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local function get_nested(obj, ...)
local n = select("#", ...)
if n == 0 then
return obj
end
obj = obj[...]
for i = 2, n do
obj = obj[select(i, ...)]
end
return obj
end
local function get_obj(mt)
local obj = require(mt[1])
if #mt > 1 then
obj = get_nested(obj, unpack(mt, 2))
end
mt[0] = obj
return obj
end
local function __call(self, ...)
local mt = getmetatable(self)
local obj = mt[0]
if obj == nil then
obj = get_obj(mt)
end
return obj(...)
end
local function __index(self, k)
local mt = getmetatable(self)
local obj = mt[0]
if obj == nil then
obj = get_obj(mt)
end
return obj[k]
end
local function __ipairs(self)
local mt = getmetatable(self)
local obj = mt[0]
if obj == nil then
obj = get_obj(mt)
end
return ipairs(obj)
end
local function __newindex(self, k, v)
local mt = getmetatable(self)
local obj = mt[0]
if obj == nil then
obj = get_obj(mt)
end
obj[k] = v
end
local function __pairs(self)
local mt = getmetatable(self)
local obj = mt[0]
if obj == nil then
obj = get_obj(mt)
end
return pairs(obj)
end
local function __tostring(self)
local mt = getmetatable(self)
local obj = mt[0]
if obj == nil then
obj = get_obj(mt)
end
return tostring(obj)
end
return function(modname, ...)
local mod = loaded[modname]
if mod ~= nil then
return get_nested(mod, ...)
end
return setmetatable({}, {
modname,
__call = __call,
__index = __index,
__ipairs = __ipairs,
__newindex = __newindex,
__pairs = __pairs,
__tostring = __tostring,
-- TODO: other metamethods, if needed.
...
})
end
1p8upm5p2cm943t5atixatwvtsenpe2
Modül:table/getUnprotectedMetatable
828
1591009
5672505
2026-06-29T15:31:55Z
MustafaCavlak
59368
imported from en
5672505
Scribunto
text/plain
local _getmetatable = debug.getmetatable
-- For testing (and just in case it gets enabled).
if _getmetatable ~= nil then
-- Avoid debug.getmetatable() throwing an error if 0 arguments are passed,
-- for parity with the other function.
return function(t)
return _getmetatable(t)
end
end
_getmetatable = getmetatable
local pcall = pcall
local rawget = rawget
local setmetatable = setmetatable
local type = type
--[==[
Attempts to retrieve the input value's metatable, and returns it if found. If the value does not have a metatable, returns {nil}. If the input value does have a metatable, but that metatable is not possible to retrieve because it is protected with the `__metatable` metamethod, returns {false}.
This is a useful way to ensure that functions can reliably distinguish between objects that do not have metamethods, objects with known metamethods, and objects with unknown metamethods.]==]
return function(t)
local mt = _getmetatable(t)
-- If `mt` is nil, there's no metatable.
if mt == nil then
return nil
-- If `mt` is not a table, the real metatable is protected and there's no
-- way of retrieving it.
elseif type(mt) ~= "table" then
return false
end
-- Try setting `mt` as the metatable with `setmetatable`; if the metatable
-- is protected, this will cause an error to be thrown (revealing it as
-- protected), and if it isn't, then `mt` must be the real metatable anyway,
-- so nothing has changed. Also make a special exception for data loaded via
-- mw.loadData(), which sets each metatable at its own __metatable key as a
-- way to stop the use of setmetatable() without actually hiding it. This is
-- spoofable, but low-risk.
return (pcall(setmetatable, t, mt) or rawget(mt, "mw_loadData") == true) and mt or false
end
oqd72lzzcljldqpmbzxsx5fm947exar
Modül:table/getMetamethod
828
1591010
5672506
2026-06-29T15:36:08Z
MustafaCavlak
59368
imported from en
5672506
Scribunto
text/plain
local table_get_unprotected_metatable = "Modül:table/getUnprotectedMetatable"
local rawget = rawget
local select = select
local function get_unprotected_metatable(...)
get_unprotected_metatable = require(table_get_unprotected_metatable)
return get_unprotected_metatable(...)
end
local function get_metamethod(n, i, mt, mm, ...)
if mt then
mm = rawget(mt, mm)
else
mm = nil
end
if i == n then
return mm
end
return mm, get_metamethod(n, i + 1, mt, ...)
end
--[==[
Takes an input value and any number of metamethods, and attempts to retrieve the values at those keys in the value's metatable. Returns a boolean stating whether the value's metamethods are findable, followed by a return value for each metamethod.
A value's metamethods are findable if it does not have a protected metatable, so the first return value is {true} if the value either has a metatable which does not contain the {__metatable} metamethod, or it has no metatable at all. If the value does have a protected metatable, the first return value is {false}, and all remaining return values default to {nil}.]==]
return function(t, ...)
local mt, n = get_unprotected_metatable(t), select("#", ...)
-- get_unprotected_metatable() returns the metatable if it's unprotected,
-- false if it's protected, or nil if there is no metatable. It checks
-- whether a metatable is protected by trying pcall(setmetatable, t),
-- so it's always possible to determine accurately.
if n == 0 then
return mt ~= false
end
return mt ~= false, get_metamethod(n, 1, mt, ...)
end
skbyag86pbpny59d8nma70atje78exb
Modül:fun/isCallable
828
1591011
5672507
2026-06-29T15:36:36Z
MustafaCavlak
59368
imported from en
5672507
Scribunto
text/plain
local debug_track_module = "Modül:debug/track"
local table_get_metamethod_module = "Modül:table/getMetamethod"
local require = require
local type = type
local function debug_track(...)
debug_track = require(debug_track_module)
return debug_track(...)
end
local function get_metamethod(...)
get_metamethod = require(table_get_metamethod_module)
return get_metamethod(...)
end
--[==[
Return {true} if the input is a function or functor (an object which can be called like a function, because it has a {__call} metamethod).
Note: if the input is an object with a {__call} metamethod, but this function is not able to find it because the object's metatable is protected with {__metatable}, then it will return {false} by default, or {nil} if the {allow_maybe} flag is set.]==]
return function(obj, allow_maybe)
if type(obj) == "function" then
return true
end
-- An object is callable if it has a __call metamethod, so try to get it
-- with get_metamethod().
local success, __call = get_metamethod(obj, "__call")
-- If this succeeds, `obj` will only be callable if the __call metamethod is
-- a function (i.e. it can't itself be a callable table), so don't recurse
-- to check it.
if __call and type(__call) == "function" then
return true
-- If not, then the metatable is protected, so it's not possible to know if
-- `obj` is callable without actually calling it.
elseif not success then
debug_track("fun/isCallable/protected metatable")
if allow_maybe then
return nil
end
end
return false
end
q2uw0kspncmdq9uyy3cxjm1xqg59xc3
Modül:string/patternEscape
828
1591012
5672508
2026-06-29T15:39:14Z
MustafaCavlak
59368
imported from en
5672508
Scribunto
text/plain
local gsub = string.gsub
local chars
local function get_chars()
chars, get_chars = {
["\000"] = "%z", ["$"] = "%$", ["%"] = "%%", ["("] = "%(", [")"] = "%)",
["*"] = "%*", ["+"] = "%+", ["-"] = "%-", ["."] = "%.", ["?"] = "%?",
["["] = "%[", ["]"] = "%]", ["^"] = "%^",
}, nil
return chars
end
--[==[Escapes the magic characters used in a pattern: {$%()*+-.?[]^}, and converts the null character to {%z}. For example, {"^$()%.[]*+-?\0"} becomes {"%^%$%(%)%%%.%[%]%*%+%-%?%z"}. This is necessary when constructing a pattern involving arbitrary text (e.g. from user input).]==]
return function(str)
return (gsub(str, "[%z$%%()*+%-.?[%]^]", chars or get_chars()))
end
kdhwp5dohwvh931huz7m0oufqqh05wl
Modül:string/replacementEscape
828
1591013
5672509
2026-06-29T15:40:35Z
MustafaCavlak
59368
imported from en
5672509
Scribunto
text/plain
local gsub = string.gsub
--[==[Escapes {%}, which is the only magic character used in replacement strings, which are given as the third argument to {string.gsub} and {mw.ustring.gsub}, as well as format strings given to {string.format} and {mw.ustring.format}.]==]
return function(str)
return (gsub(str, "%%", "%%%%"))
end
aid90he3azqkc4qrytnczmfsjczbfe3
Modül:başlık başı araçları
828
1591014
5672510
2026-06-29T15:41:54Z
MustafaCavlak
59368
imported from en
5672510
Scribunto
text/plain
local export = {}
local fun_is_callable_module = "Modül:fun/isCallable"
local languages_module = "Modül:diller"
local links_module = "Modül:bağlantılar"
local parse_utilities_module = "Modül:parse utilities"
local string_pattern_escape_module = "Modül:string/patternEscape"
local string_replacement_escape_module = "Modül:string/replacementEscape"
local string_utilities_module = "Modül:string araçları"
local table_module = "Modül:table"
local dump = mw.dumpObject
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local insert = table.insert
local concat = table.concat
local remove = table.remove
local sort = table.sort
local function deepEquals(...)
deepEquals = require(table_module).deepEquals
return deepEquals(...)
end
local function escape_wikicode(...)
escape_wikicode = require(parse_utilities_module).escape_wikicode
return escape_wikicode(...)
end
local function extend(...)
extend = require(table_module).extend
return extend(...)
end
local function get_lang(...)
get_lang = require(languages_module).getByCode
return get_lang(...)
end
local function insert_if_not(...)
insert_if_not = require(table_module).insertIfNot
return insert_if_not(...)
end
local function is_callable(...)
is_callable = require(fun_is_callable_module)
return is_callable(...)
end
local function parse_inline_modifiers(...)
parse_inline_modifiers = require(parse_utilities_module).parse_inline_modifiers
return parse_inline_modifiers(...)
end
local function pattern_escape(...)
pattern_escape = require(string_pattern_escape_module)
return pattern_escape(...)
end
local function replacement_escape(...)
replacement_escape = require(string_replacement_escape_module)
return replacement_escape(...)
end
local function shallow_copy(...)
shallow_copy = require(table_module).shallowCopy
return shallow_copy(...)
end
local function split(...)
split = require(string_utilities_module).split
return split(...)
end
local function term_contains_top_level_html(...)
term_contains_top_level_html = require(parse_utilities_module).term_contains_top_level_html
return term_contains_top_level_html(...)
end
local function ugsub(...)
ugsub = require(string_utilities_module).gsub
return ugsub(...)
end
local function umatch(...)
umatch = require(string_utilities_module).match
return umatch(...)
end
local param_mods = {
id = {}, -- disabled when `is_head = true`
q = {type = "qualifier"},
qq = {type = "qualifier"},
l = {type = "labels"},
ll = {type = "labels"},
-- [[Modül:başlık başı]] expects part references in `.refs`.
ref = {item_dest = "refs", type = "references", store = "insert-flattened"},
}
local optional_param_mods = {
g = {item_dest = "genders", type = "genders"},
alt = {},
lang = {type = "language"},
sc = {type = "script"},
t = {item_dest = "gloss"},
gloss = {},
pos = {},
lit = {},
tr = {},
ts = {},
face = {},
nolinkinfl = {type = "boolean"},
}
local optional_headword_param_mods = {
sc = {type = "script"},
tr = {},
ts = {},
}
--[==[
Parse a single inflection or headword form or list of such forms. In either case, inline modifiers may be attached.
`data` is an object with the following fields:
* `val`: The raw value to parse. Required.
* `paramname`: The name of the parameter from which the value was taken; used in error messages. Required.
* `is_head`: We are parsing a headword parameter (a value which goes into the `heads` field of `data`). This changes
the allowed modifiers, disabling the `id` modifier and only allowing a subset of optional modifiers.
* `frob`: An optional function of one value to apply to the form after inline modifiers have been removed (i.e. to
apply to the `.term` field of the returned object).
* `include_mods`: List of extra inline modifiers to include, besides the default ones (see below). Each list item is
either a string specifying a recognized extra inline modifier (see `optional_param_mods` in the code), or a two-item
list of modifier name and modifier spec, where the spec should follow the syntax for modifier specs in
`parse_inline_modifiers` in [[Modül:parse utilities]].
* `exclude_mods`: List of default inline modifiers to not include.
* `splitchar`: If specified, the value in `val` can be a list of forms to parse, separated by the value of `splitchar`
(which is a Lua pattern, as in `parse_inline_modifiers` in [[Modül:parse utilities]]). Most commonly, `splitchar` is
a single comma and the values are comma-separated (in this case, splitting will not happen if a space follows the
comma).
* `preserve_splitchar`, `delimiter_key`, `escape_fun`, `unescape_fun`, `pre_normalize_modifiers`: As in
`parse_inline_modifiers` in [[Modül:parse utilities]].
Returns an object suitable for storing as one element of one of the lists in `headdata.inflections`, where `headdata`
is the structure passed to [[Modül:başlık başı]]. If `splitchar` is specified, howeve, the return value is a list of such
objects.
The following default inline modifiers are currently recognized:
* `q`: Left qualifier.
* `qq`: Right qualifier.
* `l`: Comma-separated list of left labels. No space should follow the comma.
* `ll`: Comma-separated list of right labels. No space should follow the comma.
* `ref`: Reference or references. See {{tl|IPA}} for the syntax.
* `id`: Sense ID, in case there are multiple senses. See {{tl|l}}.
The following are the recognized additional inline modifiers:
* `g`: Comma-separated list of genders.
* `alt`: Display text.
* `lang`: Language code of language of the form, if different from the language of the headword.
* `sc`: Script code of script of the form. Almost never needed.
* `t`: Gloss for the form.
* `gloss`: Gloss for the form (alias for `t`).
* `pos`: Part of speech of the form.
* `lit`: Literal meaning of the form.
* `tr`: Manual transliteration of the form.
* `ts`: Transcription of the form, for languages where the transliteration differs markedly from the pronunciation.
* `face`: Face to display the form in, e.g. {"hypothetical"} for a hypothetical form (unlinkable and displayed in italics).
* `nolinkinfl`: Make the form unlinkable.
]==]
function export.parse_term_with_modifiers(data)
local paramname, val, frob = data.paramname, data.val, data.frob
local function generate_obj(term, parse_err)
if frob then
term = frob(term, parse_err)
end
return {term = term}
end
-- Check for inline modifier, e.g. מרים<tr:Miryem>. But exclude top-level HTML entry with <span ...>,
-- <sup> or similar in it.
if (val:find("<", nil, true) or data.splitchar) and not term_contains_top_level_html(val) and
-- don't parse inline modifiers if is_head and the value begins with a ~ (link modifier syntax)
(not data.is_head or not val:find("^~")) then
local param_mods = param_mods
if data.is_head then
param_mods = shallow_copy(param_mods)
param_mods.id = nil
end
if data.include_mods or data.exclude_mods then
if not data.is_head then
-- already copied when data.is_head
param_mods = shallow_copy(param_mods)
end
if data.include_mods then
local optional_mods = data.is_head and optional_headword_param_mods or optional_param_mods
for _, mod in ipairs(data.include_mods) do
if type(mod) == "table" then
if #mod ~= 2 then
error(("Internal error: Modifier spec %s in `include_mods` should be of length 2"):format(
dump(mod)))
end
local modkey, modvalue = unpack(mod)
param_mods[modkey] = modvalue
elseif not optional_mods[mod] then
error(("Internal error: Unrecognized modifier spec %s in `include_mods`"):format(
dump(mod)))
else
param_mods[mod] = optional_mods[mod]
end
end
end
if data.exclude_mods then
for _, mod in ipairs(data.exclude_mods) do
if not param_mods[mod] then
error(("Internal error: Modifier spec %s in `exclude_mods` not found among existing modifiers"
):format(dump(mod)))
else
param_mods[mod] = nil
end
end
end
end
return parse_inline_modifiers(val, {
paramname = paramname,
param_mods = param_mods,
generate_obj = generate_obj,
splitchar = data.splitchar,
preserve_splitchar = data.preserve_splitchar,
delimiter_key = data.delimiter_key,
escape_fun = data.escape_fun,
unescape_fun = data.unescape_fun,
pre_normalize_modifiers = data.pre_normalize_modifiers,
})
else
local retval = generate_obj(val)
if data.splitchar then
retval = {retval}
end
return retval
end
end
--[==[
Parse a list of inflection forms that may have inline modifiers attached. `data` is an object with the following fields:
* `forms`: The list of raw values to parse. Required.
* `paramname`: The name of the first parameter from which the value was taken; used in error messages. If this is a
two-element list, the first element is the first parameter and the second element is the prefix of the remaining
parameters. Parameter names that are numbers are handled correctly, as are those with \1 in it marking where the
parameter index goes. Required.
* `qualifiers`: If specified, a possibly gappy list of left qualifiers to add to the parsed terms (for compatibility
purposes).
* `splitchar`: As in `parse_term_with_modifiers()`. The resulting per-term lists will be flattened.
* `frob`, `include_mods`, `exclude_mods`, `is_head`, `preserve_splitchar`, `delimiter_key`, `escape_fun`,
`unescape_fun`, `pre_normalize_modifiers`: As in `parse_term_with_modifiers()`.
Returns a list of objects, suitable for storing as one of the lists in `headdata.inflections` (once a label is added),
where `headdata` is the structure passed to [[Modül:başlık başı]].
]==]
function export.parse_term_list_with_modifiers(data)
local paramname, forms = data.paramname, data.forms
local qualifiers = data.qualifiers
local first, restpref
if type(paramname) == "table" then
first = paramname[1]
restpref = paramname[2]
else
first = paramname
restpref = paramname
end
local terms = {}
data = shallow_copy(data)
for i, val in ipairs(forms) do
data.paramname = i == 1 and first or type(restpref) == "number" and restpref + i - 1 or
restpref:find("\1", nil, true) and restpref:gsub("\1", tostring(i)) or restpref .. i
data.val = val
local parsed = export.parse_term_with_modifiers(data)
if qualifiers and qualifiers[i] then
if data.splitchar then
for _, term in ipairs(parsed) do
term.q = {qualifiers[i]}
end
else
parsed.q = {qualifiers[i]}
end
end
if data.splitchar then
extend(terms, parsed)
else
terms[i] = parsed
end
end
return terms
end
--[==[
Construct a link to [[Appendix:Glossary]] for `entry`. If `text` is specified, it is the display text; otherwise,
`entry` is used.
]==]
function export.glossary_link(entry, text)
text = text or entry
return "[[Appendix:Glossary#" .. entry .. "|" .. text .. "]]"
end
function export.replace_glossary_links_in_label(label)
if label:find("<<", nil, true) then
label = label:gsub("<<(.-)|(.-)>>", export.glossary_link):gsub("<<(.-)>>", export.glossary_link)
end
return label
end
function export.insert_fixed_inflection(data)
local headdata, origterm, label = data.headdata, data.originating_term, data.label
local inflobj = data.inflobj or headdata
inflobj.inflections = inflobj.inflections or {}
if not origterm then
insert(inflobj.inflections, {
label = export.replace_glossary_links_in_label(label)
})
else
if origterm.id then
error(("It doesn't make sense to pass in an ID '%s' for label '%s' in conjunction with a term value '%s'"
):format(origterm.id, label, origterm.term))
end
-- Preserve qualifiers, labels, references
origterm.term = nil
origterm.label = export.replace_glossary_links_in_label(label)
insert(inflobj.inflections, origterm)
end
end
--[==[
Insert previously-parsed terms into an `inflections` field. The `inflections` field will be initialized if needed.
`data` is an object with the following fields:
* `headdata`: The headword structure passed to [[Modül:başlık başı]]. Required.
* `inflobj`: The object whose `inflections` field the terms are inserted into. Defaults to `headdata`. Only needs
to be set for nested inflections, which are specified for an inflection object rather than the headword data
structure as a whole.
* `terms`: The list of parsed terms. If {nil} or omitted, nothing happens unless `request` is set.
* `label`: The label that the inflections are given; any parts of the label surrounded in <<...>> are linked to the
glossary. (If the contents of <<...> contain a | in them, they are a two-part link.) Required.
* `no_label`: If the term is {"-"} and there are no other terms, insert a fixed label with this value. Defaults to
{"no "} plus the label.
* `usually_no_label`: If the term is {"-"} and there are other terms, insert a fixed label with this value. Defaults to
{"usually no "} plus the label.
* `accel`: If specified, a full accelerator object to add to the inflections.
* `request`: If specified and no terms are given, insert a label with a request for inflections to be given.
* `enable_auto_translit`: If specified and terms are given, display automatic transliteration of the terms.
]==]
function export.insert_inflection(data)
local headdata, terms, label = data.headdata, data.terms, data.label
local inflobj = data.inflobj or headdata
if terms and terms[1] then
if terms[1].term == "-" then
if terms[2] then
export.insert_fixed_inflection {
headdata = headdata,
inflobj = inflobj,
originating_term = terms[1],
label = data.usually_no_label or "usually no " .. label,
}
remove(terms, 1)
else
export.insert_fixed_inflection {
headdata = headdata,
inflobj = inflobj,
originating_term = terms[1],
label = data.no_label or "no " .. label,
}
return
end
end
if data.check_missing then
error("check_missing support removed; use checkredlinks=true in [[Modül:başlık başı]]")
end
terms.label = export.replace_glossary_links_in_label(label)
if data.accel then
terms.accel = data.accel
end
terms.enable_auto_translit = data.enable_auto_translit
inflobj.inflections = inflobj.inflections or {}
insert(inflobj.inflections, terms)
elseif data.request then
inflobj.inflections = inflobj.inflections or {}
insert(inflobj.inflections, {
label = export.replace_glossary_links_in_label(label),
request = true,
})
end
end
--[==[
Parse raw arguments from `forms` for inline modifiers, and insert the resulting terms (which should not require
significant additional processing) into `headdata.inflections`. `data` is an object with the following fields:
* `forms`: The list of raw values to parse. If {nil} or omitted, nothing happens.
* `headdata`: The headword structure passed to [[Modül:başlık başı]]. Required.
* `paramname`: As in `parse_term_list_with_modifiers()`. Required.
* `label`: As in `insert_inflection()`. Required.
* `qualifiers`, `frob`, `include_mods`, `exclude_mods`, `is_head`, `splitchar`, `preserve_splitchar`, `delimiter_key`,
`escape_fun`, `unescape_fun`, `pre_normalize_modifiers`: As in `parse_term_list_with_modifiers()`.
* `accel`: As in `insert_inflection()`.
]==]
function export.parse_and_insert_inflection(data)
local forms = data.forms
if forms and forms[1] then
data = shallow_copy(data)
data.forms = forms
data.terms = export.parse_term_list_with_modifiers(data)
export.insert_inflection(data)
end
end
--[==[
Combine two sets of qualifiers or labels. If either is {nil}, just return the other, and if both are {nil}, return
{nil}.
]==]
function export.combine_qualifiers_or_labels(quals1, quals2)
if not quals1 and not quals2 then
return nil
end
if not quals1 then
return quals2
end
if not quals2 then
return quals1
end
local combined = shallow_copy(quals1)
for _, note in ipairs(quals2) do
insert_if_not(combined, note)
end
return combined
end
--[==[
Combine the qualifiers, labels, references and ID's of two term objects. `destobj` is the "destination term object" into
which the combined properties are written, and `srcobj` is the "source object" into which the properties are merged.
`destobj` is side-effected (but the lists inside of `destobj` are not); if this is undesirable, make sure to
shallow-copy `destobj` first. If both objects have values for a given qualifier, label or reference, the values of
`destobj` come first. If both objects have a value for `id`, the values must match or an error is thrown; otherwise,
the resulting value of `id` comes from whichever one is defined.
'''NOTE:''' This may not be the correct behavior when deduplicating a list of term objects. See
`insert_termobj_combining_duplicates` for a different approach.
]==]
function export.combine_termobj_qualifiers_labels(destobj, srcobj)
destobj.q = export.combine_qualifiers_or_labels(destobj.q, srcobj.q)
destobj.qq = export.combine_qualifiers_or_labels(destobj.qq, srcobj.qq)
destobj.l = export.combine_qualifiers_or_labels(destobj.l, srcobj.l)
destobj.ll = export.combine_qualifiers_or_labels(destobj.ll, srcobj.ll)
destobj.refs = export.combine_qualifiers_or_labels(destobj.refs, srcobj.refs)
if destobj.id and srcobj.id and destobj.id ~= srcobj.id then
-- FIXME: We probably want to pass in an error function
error(("Can't specify two different ID's %s and %s when combining objects"):format(srcobj.id, destobj.id))
end
destobj.id = destobj.id or srcobj.id
return destobj
end
function export.termobj_has_qualifiers_or_labels(obj)
return obj.q and obj.q[1] or obj.qq and obj.qq[1] or obj.l and obj.l[1] or obj.ll and obj.ll[1] or
obj.refs and obj.refs[1]
end
local function one_ancillary_property_equal(prop1, prop2)
local prop1_is_nil = not prop1 or not prop1[1]
local prop2_is_nil = not prop2 or not prop2[1]
if prop1_is_nil and prop2_is_nil then
return true
end
if prop1_is_nil or prop2_is_nil then
return false
end
return deepEquals(prop1, prop2)
end
function export.termobj_ancillary_properties_equal(obj1, obj2)
return one_ancillary_property_equal(obj1.q, obj2.q) and
one_ancillary_property_equal(obj1.qq, obj2.qq) and
one_ancillary_property_equal(obj1.l, obj2.l) and
one_ancillary_property_equal(obj1.ll, obj2.ll) and
one_ancillary_property_equal(obj1.refs, obj2.refs) and
obj1.id == obj2.id
end
function export.convert_termobj_to_formobj(termobj)
local formobj = {
form = termobj.term,
translit = termobj.tr,
}
local footnotes
local function mods_to_footnote(mod_prefix, mod_vals)
if mod_vals and mod_vals[1] then
footnotes = footnotes or {}
for _, val in ipairs(mod_vals) do
insert(footnotes, "[" .. mod_prefix .. ":" .. val .. "]")
end
end
end
mods_to_footnote("q", termobj.q)
mods_to_footnote("qq", termobj.qq)
mods_to_footnote("l", termobj.l)
mods_to_footnote("ll", termobj.ll)
mods_to_footnote("ref", termobj.refs)
mods_to_footnote("id", termobj.id and {termobj.id} or nil)
formobj.footnotes = footnotes
return formobj
end
local recognized_multi_mods = {
q = "q",
qq = "qq",
l = "l",
ll = "ll",
ref = "refs",
}
local recognized_single_mods = {
id = "id",
}
function export.add_footnote_to_termobj(termobj, footnote)
local stripped_footnote = footnote:match("^%[(.*)%]$")
if not stripped_footnote then
error("Internal error: Footnote should be surrounded by brackets at this stage: " .. footnote)
end
local prefix, rest = stripped_footnote:match("^([a-z]+):(.+)$")
local field, is_multi
if prefix then
if recognized_multi_mods[prefix] then
field = recognized_multi_mods[prefix]
is_multi = true
elseif recognized_single_mods[prefix] then
field = recognized_single_mods[prefix]
is_multi = false
end
end
if not field then
rest = stripped_footnote
field = "l"
is_multi = true
end
if is_multi then
if not termobj[field] then
termobj[field] = {}
end
insert(termobj[field], rest)
else
if termobj[field] and termobj[field] ~= rest then
error(("Can't set two values for '%s': '%s' and '%s'"):format(field, termobj[field], rest))
end
termobj[field] = rest
end
end
function export.convert_formobj_to_termobj(formobj)
local termobj = {
term = formobj.form,
tr = formobj.translit,
}
if formobj.footnotes then
for _, footnote in ipairs(formobj.footnotes) do
export.add_footnote_to_termobj(termobj, footnote)
end
end
return termobj
end
local function extract_termobj_field_modifiers(fieldval)
return fieldval:match("^([*+]?)(.*)$")
end
function export.remove_termobj_field_modifiers(termobj)
local function remove_field_modifiers(field)
if termobj[field] and termobj[field][1] then
local any_field_modifiers = false
for _, val in ipairs(termobj[field]) do
local field_mods, _ = extract_termobj_field_modifiers(val)
if field_mods ~= "" then
any_field_modifiers = true
break
end
end
local new_field = {}
if any_field_modifiers then
for _, val in ipairs(termobj[field]) do
local _, field_without_mods = extract_termobj_field_modifiers(val)
insert_if_not(new_field, field_without_mods)
end
termobj[field] = new_field
end
end
end
remove_field_modifiers("q")
remove_field_modifiers("qq")
remove_field_modifiers("l")
remove_field_modifiers("ll")
remove_field_modifiers("refs")
end
function export.insert_termobj_combining_duplicates(destobjs, termobj)
for _, destobj in ipairs(destobjs) do
if destobj.term == termobj.term and destobj.tr == termobj.tr then
-- Form already present; maybe combine footnotes.
local function combine_field_values(field)
if termobj[field] and termobj[field][1] then
-- Check to see if there are existing values with *; if so, remove them.
if destobj[field] and destobj[field][1] then
local any_values_with_asterisk = false
for _, val in ipairs(destobj[field]) do
local field_mods, _ = extract_termobj_field_modifiers(val)
if field_mods:find("%*") then
any_values_with_asterisk = true
break
end
end
if any_values_with_asterisk then
local filtered_values = {}
for _, val in ipairs(destobj[field]) do
local field_mods, _ = extract_termobj_field_modifiers(val)
if not val:find("%*") then
insert(filtered_values, val)
end
end
if filtered_values[1] then
destobj[field] = filtered_values
else
destobj[field] = nil
end
end
end
local any_values_with_plus = false
for _, val in ipairs(termobj[field]) do
local field_mods, _ = extract_termobj_field_modifiers(val)
if val:find("%+") then
any_footnotes_with_plus = true
break
end
end
if any_footnotes_with_plus then
if not destobj[field] then
destobj[field] = {}
else
destobj[field] = shallow_copy(destobj[field])
end
for _, val in ipairs(termobj[field]) do
local already_seen = false
local field_mods, field_without_mods = extract_termobj_field_modifiers(val)
if val:find("%+") then
for _, existing_val in ipairs(destobj[field]) do
local existing_field_mods, existing_field_without_mods =
extract_termobj_field_modifiers(existing_val)
if existing_field_without_mods == field_without_mods then
already_seen = true
break
end
end
if not already_seen then
insert(destobj[field], val)
end
end
end
end
end
end
combine_field_values("q")
combine_field_values("qq")
combine_field_values("l")
combine_field_values("ll")
combine_field_values("refs")
if destobj.id and termobj.id and destobj.id ~= termobj.id then
-- FIXME: We probably want to pass in an error function
error(("Can't specify two different ID's %s and %s when combining objects"):format(termobj.id, destobj.id))
end
destobj.id = destobj.id or termobj.id
return
end
end
insert(destobjs, termobj)
end
export.allowed_special_indicators = {
["first"] = true,
["first-second"] = true,
["first-last"] = true,
["second"] = true,
["last"] = true,
["each"] = true,
["+"] = true, -- requests the default behavior with preposition handling
}
--[==[
Check for special indicators (values such as {"+first"} or {"+first-last"} that are used in a `pl`, `f`, etc. argument
and indicate how to inflect a multiword term). If `form` is such an indicator, the return value is `form` minus
the initial `+` sign; otherwise, if form begins with a `+` sign, an error is thrown; otherwise the return value is nil.
]==]
function export.get_special_indicator(form, noerror)
if form:find("^%+") then
form = form:gsub("^%+", "")
if not export.allowed_special_indicators[form] then
if noerror then
return nil
end
local indicators = {}
for indic, _ in pairs(export.allowed_special_indicators) do
insert(indicators, "+" .. indic)
end
sort(indicators)
error("Special inflection indicator beginning with '+' can only be " ..
mw.text.listToText(indicators) .. ": +" .. form)
end
return form
end
return nil
end
local function add_endings(bases, endings)
local retval = {}
if type(bases) ~= "table" then
bases = {bases}
end
if type(endings) ~= "table" then
endings = {endings}
end
for _, base in ipairs(bases) do
for _, ending in ipairs(endings) do
insert(retval, base .. ending)
end
end
return retval
end
--[==[
Inflect a possibly multiword or hyphenated term `form` using the function `inflect`, which is a function of one argument
that is called on a single word to inflect and should return either the inflected word or a list of inflected words.
`special` indicates how to inflect the multiword term and should be e.g. {"first"} to inflect only the first word,
{"first-last"} to inflect the first and last words, {"each"} to inflect each word, etc. See `allowed_special_indicators`
above for the possibilities. If `special` is `+`, or is omitted and the term is multiword (i.e. containing a space
character), and `prepositions` is supplied, the function checks for multiword or hyphenated terms containing the
prepositions in `prepositions`, e.g. Italian [[senso di marcia]] or [[medaglia d'oro]] or Portuguese
[[tartaruga-do-mar]]. If such a term is found, only the first word is inflected. Otherwise, the default is
{"first-last"}. `prepositions` is a list of Lua patterns matching prepositions. The patterns will automatically have the
separator character (space or hyphen) added to the left side but not the right side, so they should contain a space
character (which will automatically be converted to the appropriate separator) on the right side unless the preposition
is joined on the right side with an apostrophe. Examples of preposition patterns for Italian are {"di "}, {"sull'"} and
{"d?all[oae] "} (which matches {"dallo "}, {"dalle "}, {"alla "}, etc.).
The return value is always either a list of inflected multiword or hyphenated terms, or nil if `special` is omitted
and `form` is not multiword. (If `special` is specified and `form` is not multiword or hyphenated, an error results.)
]==]
function export.handle_multiword(form, special, inflect, prepositions, sep)
sep = sep or form:find(" ") and " " or "%-"
local raw_sep = sep == " " and " " or "-"
-- Used to add regex version of separator in the replacement portion of ugsub() or :gsub()
local sep_replacement = sep == " " and " " or "%%-"
-- Given a Lua pattern, replace space with the appropriate separator.
local function hack_re(re)
if sep == " " then
return re
end
return (re:gsub(" ", sep_replacement))
end
if special == "first" then
local first, rest = form:match(hack_re("^(.-)( .*)$"))
if not first then
error("Special indicator 'first' can only be used with a multiword term: " .. form)
end
return add_endings(inflect(first), rest)
elseif special == "second" then
local first, second, rest = form:match(hack_re("^([^ ]+ )([^ ]+)( .*)$"))
if not first then
error("Special indicator 'second' can only be used with a term with three or more words: " .. form)
end
return add_endings(add_endings({first}, inflect(second)), rest)
elseif special == "first-second" then
local first, space, second, rest = form:match(hack_re("^([^ ]+)( )([^ ]+)( .*)$"))
if not first then
error("Special indicator 'first-second' can only be used with a term with three or more words: " .. form)
end
return add_endings(add_endings(add_endings(inflect(first), space), inflect(second)), rest)
elseif special == "each" then
local terms = split(form, sep)
if #terms < 2 then
error("Special indicator 'each' can only be used with a multiword term: " .. form)
end
for i, term in ipairs(terms) do
terms[i] = inflect(term)
if i > 1 then
terms[i] = add_endings(raw_sep, terms[i])
end
end
local result = ""
for _, term in ipairs(terms) do
result = add_endings(result, term)
end
return result
elseif special == "first-last" then
local first, middle, last = form:match(hack_re("^(.-)( .* )(.-)$"))
if not first then
first, middle, last = form:match(hack_re("^(.-)( )(.*)$"))
end
if not first then
error("Special indicator 'first-last' can only be used with a multiword term: " .. form)
end
return add_endings(add_endings(inflect(first), middle), inflect(last))
elseif special == "last" then
local rest, last = form:match(hack_re("^(.* )(.-)$"))
if not rest then
error("Special indicator 'last' can only be used with a multiword term: " .. form)
end
return add_endings(rest, inflect(last))
elseif special and special ~= "+" then
error("Unrecognized special=" .. special)
end
-- Only do default behavior if special indicator '+' explicitly given or separator is space; otherwise we will
-- break existing behavior with hyphenated words.
if (special == "+" or sep == " ") and form:find(sep) then
if prepositions then
-- check for prepositions in the middle of the word; do it this way so we can handle
-- more than one word before the preposition (and usually inflect each word)
for _, prep in ipairs(prepositions) do
local first, space_prep_rest = umatch(form, hack_re("^(.-)( " .. prep .. ".*)$"))
if first then
return add_endings(inflect(first), space_prep_rest)
end
end
end
-- multiword or hyphenated expressions default to first-last; we need to pass in the separator to avoid
-- problems with multiword terms containing hyphens in the individual words
return export.handle_multiword(form, "first-last", inflect, prepositions, sep)
end
return nil
end
local function link_hyphen_split_component(word, data)
if data.link_hyphen_split_component then
return data.link_hyphen_split_component(word)
else
return "[[" .. word .. "]]"
end
end
-- Default function to split a word on apostrophes. Don't split apostrophes at the beginning or end of a word (e.g.
-- [['ndrangheta]] or [[po']]). Handle multiple apostrophes correctly, e.g. [[l'altr'ieri]] -> [[l']][altr']][[ieri]].
function export.default_split_apostrophe(word, data)
local apostrophe_parts = split(word, "'", true, true)
local linked_apostrophe_parts = {}
local apostrophes_at_beginning = ""
local i = 1
-- Apostrophes at beginning get attached to the first word after (which will always exist but may
-- be blank if the word consists only of apostrophes).
while i < #apostrophe_parts do -- <, not <=, in case the word consists only of apostrophes
local apostrophe_part = apostrophe_parts[i]
i = i + 1
if apostrophe_part == "" then
apostrophes_at_beginning = apostrophes_at_beginning .. "'"
else
break
end
end
apostrophe_parts[i] = apostrophes_at_beginning .. apostrophe_parts[i]
-- Now, do the remaining parts. A blank part indicates more than one apostrophe in a row; we join
-- all of them to the preceding word.
while i <= #apostrophe_parts do
local apostrophe_part = apostrophe_parts[i]
if apostrophe_part == "" then
linked_apostrophe_parts[#linked_apostrophe_parts] =
linked_apostrophe_parts[#linked_apostrophe_parts] .. "'"
elseif i == #apostrophe_parts then
insert(linked_apostrophe_parts, apostrophe_part)
else
insert(linked_apostrophe_parts, apostrophe_part .. "'")
end
i = i + 1
end
for j, tolink in ipairs(linked_apostrophe_parts) do
linked_apostrophe_parts[j] = link_hyphen_split_component(tolink, data)
end
return concat(linked_apostrophe_parts)
end
--[=[
Auto-add links to a word that should not have spaces but may have hyphens and/or apostrophes. We split off final
punctuation, then split on hyphens if `data.split_hyphen` is given, and also split on apostrophes if
`data.split_apostrophe` is given. We only split on hyphens if they are in the middle of the word, not at the beginning
or end (hyphens at the beginning or end indicate suffixes or prefixes, respectively). `include_hyphen_prefixes`, if
given, is a set of prefixes (not including the final hyphen) where we should include the final hyphen in the prefix.
Hence, e.g. if "anti" is in the set, a Portuguese word like [[anti-herói]] "anti-hero" will be split [[anti-]][[herói]]
(whereas a word like [[código-fonte]] "source code" will be split as [[código]]-[[fonte]]).
If `data.split_apostrophe` is specified, we split on apostrophes unless `data.no_split_apostrophe_words` is given and
the word is in the specified set, such as French [[c'est]] and [[quelqu'un]]. If `data.split_apostrophe` is true, the
default algorithm applies, which splits on all apostrophes except those at the beginning and end of a word (as in
Italian [['ndrangheta]] or [[po']]), and includes the apostrophe in the link to its left (so we auto-split French
[[l'eau]] as [[l']][[eau]] and [[l'altr'ieri]] as [[l']][altr']][[ieri]]). If `data.split_apostrophe` is specified
but not `true`, it should be a function of one argument that does custom apostrophe-splitting. The argument is the word
to split, and the return value should be the split and linked word.
]=]
local function add_single_word_links(space_word, data, term_has_spaces)
local space_word_no_punct, punct
local punct_pattern = data.punctuation
if punct_pattern and is_callable(punct_pattern) then
space_word_no_punct, punct = punct_pattern(space_word)
else
if punct_pattern == nil then
punct_pattern = "[,;:?!]"
end
space_word_no_punct, punct = umatch(space_word, "^(.*)(" .. punct_pattern .. ")$")
end
space_word_no_punct = space_word_no_punct or space_word
punct = punct or ""
local words
if space_word_no_punct:sub(1, 1) == "-" or space_word_no_punct:sub(-1) == "-" then
-- don't split prefixes and suffixes
words = {space_word_no_punct}
else
local splitter
if term_has_spaces then
splitter = data.split_hyphen_when_space
else
splitter = data.split_hyphen_when_no_space
end
if is_callable(splitter) then
words = splitter(space_word_no_punct)
if type(words) == "string" then
return words .. punct
end
end
end
if not words then
local split_hyphen
if term_has_spaces then
split_hyphen = data.split_hyphen_when_space
else
split_hyphen = data.split_hyphen_when_no_space
if split_hyphen == nil then -- default to true; use `false` to avoid this
split_hyphen = true
end
end
if split_hyphen then
words = split(space_word_no_punct, "-", true, true)
else
words = {space_word_no_punct}
end
end
local linked_words = {}
for j, word in ipairs(words) do
if j < #words and data.include_hyphen_prefixes and data.include_hyphen_prefixes[word] then
word = "[[" .. word .. "-]]"
elseif j > 1 and data.include_hyphen_suffixes and data.include_hyphen_suffixes[word] then
word = "[[-" .. word .. "]]"
else
-- Don't split on apostrophes if the word is in `no_split_apostrophe_words`.
if (not data.no_split_apostrophe_words or not data.no_split_apostrophe_words[word]) and
data.split_apostrophe and word:find("'", nil, true) then
if data.split_apostrophe == true then
word = export.default_split_apostrophe(word, data)
else -- custom apostrophe splitter/linker
word = data.split_apostrophe(word)
end
elseif word ~= "" then -- avoid -[[]]- (e.g. f--k)
word = link_hyphen_split_component(word, data)
end
if j < #words then
word = word .. "-"
end
end
insert(linked_words, word)
end
return concat(linked_words) .. punct
end
--[=[
Auto-add links to a multiword term. `data` contains fields customizing how to do this. By default we proceed as follows:
(1) If the term already has embedded links in it, they are left unchanged.
(2) Otherwise, if there are spaces present, we split on spaces and link each word separately.
(3) If a given space-separated component ends in punctuation (defaulting to [,;:?!]), it is separated off, the remainder
of the algorithm run, and the punctuation pasted back on.
(4) If there are hyphens in a given space-separated component, we may link each hyphenated term separately depending
on the settings in `data`. Normally the hyphens are not included in the linked terms, but this can be overridden
for specific prefixes and/or suffixes. By default, if there are spaces in the multiword term, we do not link
hyphenated components (because of cases like "boire du petit-lait" where "petit-lait" should be linked as a whole),
but do so otherwise (e.g. for "avant-avant-hier"); this can overridden for cases like "croyez-le ou non".
Cases where only some of the hyphens should be split can always be handled by explicitly specifying the head (e.g.
"Nord-Pas-de-Calais" given as head=[[Nord]]-[[Pas-de-Calais]]).
(5) If there are apostrophes in a given component, we may link each apostrophe-separated term separately depending
on the settings in `data`, including the apostrophe in the link to its left (so we split "de l'eau" as
"[[de]] [[l']][[eau]]").
The settings in `data` are as follows:
`split_hyphen_when_no_space`: Whether to split on hyphens when the term has no spaces. Defaults to true if set to `nil`.
This can be a function of one argument, to implement a custom splitting algorithm for hyphen-separated terms. If
this returns [FIXME: FINISH ME ...]
If `data.split_apostrophe` is specified, we split on apostrophes unless `data.no_split_apostrophe_words` is given and
the word is in the specified set, such as French [[c'est]] and [[quelqu'un]]. If `data.split_apostrophe` is true, the
default algorithm applies, which splits on all apostrophes except those at the beginning and end of a word (as in
Italian [['ndrangheta]] or [[po']]), and includes the apostrophe in the link to its left (so we auto-split French
[[l'eau]] as [[l']][[eau]] and [[l'altr'ieri]] as [[l']][altr']][[ieri]]). If `data.split_apostrophe` is specified
but not `true`, it should be a function of one argument that does custom apostrophe-splitting. The argument is the word
to split, and the return value should be the split and linked word.
We don't always split on hyphens because of cases like "boire du petit-lait" where "petit-lait" should be linked as a
whole, but provide the option to do it for cases like "croyez-le ou non". If there's no space, however, then it makes
sense to split on hyphens by `no_split_apostrophe_words` and `include_hyphen_prefixes` allow for special-case handling
of particular words and are as described in the comment above add_single_word_links().
]=]
function export.add_links_to_multiword_term(term, data)
if term:match("[%[%]]") then
return term
end
local words = split(term, " ", true, true)
local term_has_spaces = #words > 1
local linked_words = {}
for _, word in ipairs(words) do
insert(linked_words, add_single_word_links(word, data, term_has_spaces))
end
local retval = concat(linked_words, " ")
-- If we ended up with a single link consisting of the entire term,
-- remove the link.
return retval:match("^%[%[([^%[%]]*)%]%]$") or retval
end
local function canonicalize_begin_end_spec(spec)
local from, to = spec:match("^(.-):(.*)$")
if not from then
from = spec
to = ""
end
return from, to
end
--[==[
Given a `linked_term` that is the output of add_links_to_multiword_term(), apply modifications as given in
`modifier_spec` to change the link destination of subterms (normally single-word non-lemma forms; sometimes
collections of adjacent words). This is usually used to link non-lemma forms to their corresponding lemma, but can
also be used to replace a span of adjacent separately-linked words to a single multiword lemma. The format of
`modifier_spec` is one or more semicolon-separated subterm specs, where each such spec is of the form
SUBTERM:DEST, where SUBTERM is one or more words in the `linked_term` but without brackets in them, and DEST is the
corresponding link destination to link the subterm to. Any occurrence of ~ in DEST is replaced with SUBTERM.
Alternatively, a single modifier spec can be of the form BEGIN[FROM:TO], which is equivalent to writing
BEGINFROM:BEGINTO (see example below).
For example, given the source phrase [[il bue che dice cornuto all'asino]] "the pot calling the kettle black"
(literally "the ox that calls the donkey horned/cuckolded"), the result of calling add_links_to_multiword_term()
is [[il]] [[bue]] [[che]] [[dice]] [[cornuto]] [[all']][[asino]]. With a modifier_spec of 'dice:dire', the result
is [[il]] [[bue]] [[che]] [[dire|dice]] [[cornuto]] [[all']][[asino]]. Here, based on the modifier spec, the
non-lemma form [[dice]] is replaced with the two-part link [[dire|dice]].
Another example: given the source phrase [[chi semina vento raccoglie tempesta]] "sow the wind, reap the whirlwind"
(literally (he) who sows wind gathers [the] tempest"). The result of calling add_links_to_multiword_term() is
[[chi]] [[semina]] [[vento]] [[raccoglie]] [[tempesta]], and with a modifier_spec of 'semina:~re; raccoglie:~re',
the result is [[chi]] [[seminare|semina]] [[vento]] [[raccogliere|raccoglie]] [[tempesta]]. Here we use the ~
notation to stand for the non-lemma form in the destination link.
A more complex example is [[se non hai altri moccoli puoi andare a letto al buio]], which becomes
[[se]] [[non]] [[hai]] [[altri]] [[moccoli]] [[puoi]] [[andare]] [[a]] [[letto]] [[al]] [[buio]] after calling
add_links_to_multiword_term(). With the following modifier_spec:
'hai:avere; altr[i:o]; moccol[i:o]; puoi: potere; andare a letto:~; al buio:~', the result of applying the spec is
[[se]] [[non]] [[avere|hai]] [[altro|altri]] [[moccolo|moccoli]] [[potere|puoi]] [[andare a letto]] [[al buio]].
Here, we rely on the alternative notation mentioned above for e.g. 'altr[i:o]', which is equivalent to 'altri:altro',
and link multiword subterms using e.g. 'andare a letto:~'. (The code knows how to handle multiword subexpressions
properly, and if the link text and destination are the same, only a single-part link is formed.)
]==]
function export.apply_link_modifiers(linked_term, modifier_spec, lang)
local split_modspecs = split(modifier_spec, "%s*;%s*")
for j, modspec in ipairs(split_modspecs) do
local id
if modspec:find("<") then
local rest
rest, id = modspec:match("^(.*)<id:(.-)>$")
if rest then
modspec = rest
end
end
local subterm, dest, otherlang
local begin_spec, rest, end_spec = modspec:match("^%[(.-)%]([^:]*)%[(.-)%]$")
if begin_spec then
local begin_from, begin_to = canonicalize_begin_end_spec(begin_spec)
local end_from, end_to = canonicalize_begin_end_spec(end_spec)
subterm = begin_from .. rest .. end_from
dest = begin_to .. rest .. end_to
end
if not subterm then
rest, end_spec = modspec:match("^([^:]*)%[(.-)%]$")
if rest then
local end_from, end_to = canonicalize_begin_end_spec(end_spec)
subterm = rest .. end_from
dest = rest .. end_to
end
end
if not subterm then
begin_spec, rest = modspec:match("^%[(.-)%]([^:]*)$")
if begin_spec then
local begin_from, begin_to = canonicalize_begin_end_spec(begin_spec)
subterm = begin_from .. rest
dest = begin_to .. rest
end
end
if not subterm then
subterm, dest = modspec:match("^(.-)%s*:%s*(.*)$")
if subterm and subterm ~= "^" and subterm ~= "$" then
local langdest
-- Parse off an initial language code (e.g. 'en:Higgs', 'la:minūtia' or 'grc:σκατός'). Also handle
-- Wikipedia prefixes ('w:Abatemarco' or 'w:it:Colle Val d'Elsa').
otherlang, langdest = dest:match("^([A-Za-z0-9._-]+):([^ ].*)$")
if otherlang == "w" then
local foreign_wikipedia, foreign_term = langdest:match("^([A-Za-z0-9._-]+):([^ ].*)$")
if foreign_wikipedia then
otherlang = otherlang .. ":" .. foreign_wikipedia
langdest = foreign_term
end
dest = ("%s:%s"):format(otherlang, langdest)
otherlang = nil
elseif otherlang then
otherlang = get_lang(otherlang, true, "allow etym")
dest = langdest
end
end
end
if not subterm then
if modspec == "?" or modspec == "!" then
subterm = "$"
dest = modspec
elseif modspec == "..." or modspec == "...?" then
subterm = "$"
dest = " " .. modspec
elseif modspec:find("^[A-Z]$") then
-- X, Y, etc. by themselves are unlinked, to help with snowclones
subterm = modspec
dest = "_"
else
subterm = modspec
dest = "~"
end
end
if subterm == "^" then
linked_term = dest:gsub("_", " ") .. linked_term
elseif subterm == "$" then
linked_term = linked_term .. dest:gsub("_", " ")
else
if subterm:find("[", nil, true) then
error(("Subterm '%s' in modifier spec '%s' cannot have brackets in it"):format(
escape_wikicode(subterm), escape_wikicode(modspec)))
end
local escaped_subterm = pattern_escape(subterm)
local subterm_re = "%[%[" .. escaped_subterm:gsub("(%%?[ ',%-])", "%%]*%1%%[*") .. "%]%]"
local expanded_dest
if dest:find("~", nil, true) then
expanded_dest = dest:gsub("~", replacement_escape(subterm))
else
expanded_dest = dest
end
if otherlang then
expanded_dest = expanded_dest .. "#" .. otherlang:getCanonicalName()
end
local subterm_replacement
if expanded_dest == "_" then
subterm_replacement = subterm
if id then
error("Can't supply <id:...> with an unlinked subterm")
end
if otherlang then
error("Can't supply prefixed language with an unlinked subterm")
end
elseif id or otherlang then
if id and expanded_dest:find("[", nil, true) then
error("Can't supply <id:...> with destination with embedded brackets")
end
subterm_replacement = require(links_module).language_link {
lang = otherlang or lang,
term = expanded_dest,
alt = subterm,
id = id,
}
elseif expanded_dest:find("[", nil, true) then
-- Use the destination directly if it has brackets in it (e.g. to put brackets around parts of a word).
subterm_replacement = expanded_dest
elseif expanded_dest == subterm then
subterm_replacement = "[[" .. subterm .. "]]"
else
subterm_replacement = "[[" .. expanded_dest .. "|" .. subterm .. "]]"
end
local escaped_subterm_replacement = replacement_escape(subterm_replacement)
local replaced_linked_term = ugsub(linked_term, subterm_re, escaped_subterm_replacement)
if replaced_linked_term == linked_term then
mw.log(("Attempted to replace %s with %s in %s"):format(subterm_re, escaped_subterm_replacement, linked_term))
error(("Subterm '%s' could not be located in %slinked expression %s, or replacement same as subterm"):format(
subterm, j > 1 and "intermediate " or "", escape_wikicode(linked_term)))
else
linked_term = replaced_linked_term
end
end
end
return linked_term
end
return export
adi8s3uo39xiyojd8a3chek0hzlgl25
аббревиировать
0
1591015
5672515
2026-06-29T18:50:00Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Eylem=== {{ru-eylem|аббревии́ровать|impf|pf=проаббревии́ровать}} # [[kısaltmak]]
5672515
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{ru-eylem|аббревии́ровать|impf|pf=проаббревии́ровать}}
# [[kısaltmak]]
ix0ip185fbbqpctegu4vhwcjoctw95f
проаббревиировать
0
1591016
5672516
2026-06-29T18:50:39Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Eylem=== {{ru-eylem|проаббревии́ровать|pf|impf=аббревии́ровать}} # [[kısaltmak]]
5672516
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{ru-eylem|проаббревии́ровать|pf|impf=аббревии́ровать}}
# [[kısaltmak]]
fyweijwxza2fqlwjmim9e6kic430g39
аблактировать
0
1591017
5672517
2026-06-29T18:51:44Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Eylem=== {{ru-eylem|аблакти́ровать|impf}} # [[sütten kesmek]]
5672517
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{ru-eylem|аблакти́ровать|impf}}
# [[sütten kesmek]]
fqi3hgq80svvrw785puq6f1g641ker7
ana mektebi
0
1591018
5672521
2026-06-29T19:04:32Z
Satirdan kahraman
37401
Yeni sayfa : ==Türkçe== ===Köken=== * {{birleşik|dil=tr|ana|mektep}} ===Söyleniş=== * {{tr-IPA}} * {{h|dil=tr||a|na|mek|te|bi}} ===Ad=== {{tr-ad|istisna=bileşik}} [[File:TR Izmir asv2020-02 img38 Löhner mansion.jpg|küçükresim|Anaokulu]] # {{t|eğitim|dil=tr}} öğrenim çağına henüz gelmemiş 2-6 yaş arasındaki çocukları okul düzenine hazırlayan eğitim kuruluşu; [[ana mektebi]] ====Çekimleme==== {{tr-ad-tablo|istisna=bileşik}} ===Kaynakça=== * {{KYK:TDK}} ===Ek ok...
5672521
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{birleşik|dil=tr|ana|mektep}}
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||a|na|mek|te|bi}}
===Ad===
{{tr-ad|istisna=bileşik}}
[[File:TR Izmir asv2020-02 img38 Löhner mansion.jpg|küçükresim|Anaokulu]]
# {{t|eğitim|dil=tr}} öğrenim çağına henüz gelmemiş 2-6 yaş arasındaki çocukları okul düzenine hazırlayan eğitim kuruluşu; [[ana mektebi]]
====Çekimleme====
{{tr-ad-tablo|istisna=bileşik}}
===Kaynakça===
* {{KYK:TDK}}
===Ek okumalar===
*{{proje bağlantısı|Vikipedi}}
100trno6s6yfdw1uh70hlgpr5w62te6
5672522
5672521
2026-06-29T19:04:46Z
Satirdan kahraman
37401
/* */ [[MediaWiki:Gadget-AjaxEdit.js|AjaxDüzenle]] kullanılarak değiştirildi
5672522
wikitext
text/x-wiki
==Türkçe==
===Köken===
* {{birleşik|dil=tr|ana|mektep}}
===Söyleniş===
* {{tr-IPA}}
* {{h|dil=tr||a|na|mek|te|bi}}
===Ad===
{{tr-ad|istisna=bileşik}}
[[File:TR Izmir asv2020-02 img38 Löhner mansion.jpg|küçükresim|Bir '''ana mektebi.''']]
# {{t|eğitim|dil=tr}} öğrenim çağına henüz gelmemiş 2-6 yaş arasındaki çocukları okul düzenine hazırlayan eğitim kuruluşu; [[ana mektebi]]
====Çekimleme====
{{tr-ad-tablo|istisna=bileşik}}
===Kaynakça===
* {{KYK:TDK}}
===Ek okumalar===
*{{proje bağlantısı|Vikipedi}}
c50tk9obhemlgfu0wcm4pui2v6ymoza
абонироваться
0
1591019
5672532
2026-06-29T19:27:57Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Eylem=== {{ru-eylem|абони́роваться|impf|c2=pf}} # {{t|dil=ru|eskimiş}} [[abone olmak]]
5672532
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{ru-eylem|абони́роваться|impf|c2=pf}}
# {{t|dil=ru|eskimiş}} [[abone olmak]]
r04zoj9sktw0z48kujqw0z5ih84g763
5672533
5672532
2026-06-29T19:28:10Z
MustafaCavlak
59368
/* Eylem */
5672533
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{ru-eylem|абони́роваться|impf-pf}}
# {{t|dil=ru|eskimiş}} [[abone olmak]]
qsrqmxb9mmysufe9k6mj7f9bdw2wr21
абсолютизировать
0
1591020
5672534
2026-06-29T19:30:25Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Eylem=== {{ru-eylem|абсолютизи́ровать|impf-pf}} # [[mutlaklaştırmak]], [[mutlak]] hâle getirmek
5672534
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{ru-eylem|абсолютизи́ровать|impf-pf}}
# [[mutlaklaştırmak]], [[mutlak]] hâle getirmek
24v4tx3ppqhnmik4bpq4quzsxhqh3kg
абсорбировать
0
1591021
5672537
2026-06-29T19:32:05Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Eylem=== {{ru-eylem|абсорби́ровать|impf-pf}} # [[soğurmak]], [[absorbe etmek]]
5672537
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{ru-eylem|абсорби́ровать|impf-pf}}
# [[soğurmak]], [[absorbe etmek]]
tjb6x89krlrmwz5m7oipapdwi7btqdo
абсорбироваться
0
1591022
5672539
2026-06-29T19:34:26Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Eylem=== {{ru-eylem|абсорби́роваться|impf-pf}} # {{çekim|dil=ru|абсорби́ровать||pass}}: [[soğrulmak]], [[absorbe]] edilmek
5672539
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{ru-eylem|абсорби́роваться|impf-pf}}
# {{çekim|dil=ru|абсорби́ровать||pass}}: [[soğrulmak]], [[absorbe]] edilmek
0l0t8ipig74iw9trz16askgvn54nvwi
yorumlatmak
0
1591023
5672540
2026-06-29T19:35:18Z
Satirdan kahraman
37401
Yeni sayfa : ==Türkçe== ===Köken=== ===Söyleniş=== *{{tr-IPA}} * {{h|dil=tr||yo|rum|lat|mak}} ===Eylem=== {{tr-eylem}} [[File:Olaus Magnus - On the Art of Prophecy.jpg|thumb|Kral, adama ölü balıkların ne anlama geldiğini '''yorumlatıyor.''']] # [[yorumlama|Yorumlama]] işini yaptırmak. ====Çekimleme==== {{tr-eylem-tablo}} ===Kaynakça=== * {{KYK:TDK}}
5672540
wikitext
text/x-wiki
==Türkçe==
===Köken===
===Söyleniş===
*{{tr-IPA}}
* {{h|dil=tr||yo|rum|lat|mak}}
===Eylem===
{{tr-eylem}}
[[File:Olaus Magnus - On the Art of Prophecy.jpg|thumb|Kral, adama ölü balıkların ne anlama geldiğini '''yorumlatıyor.''']]
# [[yorumlama|Yorumlama]] işini yaptırmak.
====Çekimleme====
{{tr-eylem-tablo}}
===Kaynakça===
* {{KYK:TDK}}
nzc303kebhdbrh8o4jhkwt8anlqa53i
абстрагировать
0
1591024
5672541
2026-06-29T19:35:39Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Eylem=== {{ru-eylem|абстраги́ровать|impf-pf}} # [[soyutlaştırmak]]
5672541
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{ru-eylem|абстраги́ровать|impf-pf}}
# [[soyutlaştırmak]]
hsiq1izurx9bb85944eenyn1d27494l
абьюзить
0
1591025
5672543
2026-06-29T19:37:59Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Eylem=== {{ru-eylem|абью́зить|impf|pf=заабью́зить}} # {{t|dil=ru|argo}} [[istismar etmek]]
5672543
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{ru-eylem|абью́зить|impf|pf=заабью́зить}}
# {{t|dil=ru|argo}} [[istismar etmek]]
970et3b41s5cc645ukpd2bahuqn97jw
Kategori:Rusça argo
14
1591026
5672544
2026-06-29T19:38:30Z
MustafaCavlak
59368
Yeni sayfa : {{kategori söz|dil=ru|söz=argo}}
5672544
wikitext
text/x-wiki
{{kategori söz|dil=ru|söz=argo}}
kj1hv0w49bh8u2f8513j0yzxt6x5gsw
заабьюзить
0
1591027
5672545
2026-06-29T19:39:51Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Eylem=== {{ru-eylem|заабью́зить|pf|impf=абью́зить}} # {{t|dil=ru|argo}} [[istismar etmek]]
5672545
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{ru-eylem|заабью́зить|pf|impf=абью́зить}}
# {{t|dil=ru|argo}} [[istismar etmek]]
c7uhr502q5fhc69xc1gulyn05y7o5ev
авансировать
0
1591028
5672546
2026-06-29T19:42:01Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Eylem=== {{ru-eylem|аванси́ровать|impf-pf}} # [[avans vermek]]
5672546
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{ru-eylem|аванси́ровать|impf-pf}}
# [[avans vermek]]
0f6s3k9jgdtex4v7hi5pq6rbbleovu5
автоматизировать
0
1591029
5672548
2026-06-29T19:44:28Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Eylem=== {{ru-eylem|автоматизи́ровать|impf-pf}} # [[otomatikleştirmek]], [[otomatik]] hâle getirmek
5672548
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{ru-eylem|автоматизи́ровать|impf-pf}}
# [[otomatikleştirmek]], [[otomatik]] hâle getirmek
0bylxohkbsyafqgbwgeb59dz06gqap4
авторизовать
0
1591030
5672549
2026-06-29T19:46:39Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Eylem=== {{ru-eylem|авторизова́ть|impf-pf|impf=авторизо́вывать}} # [[yetkilendirmek]], [[yetki vermek]]
5672549
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{ru-eylem|авторизова́ть|impf-pf|impf=авторизо́вывать}}
# [[yetkilendirmek]], [[yetki vermek]]
dd6sirs58cwtmsyva79nftw7rialf0m
Kategori:Rusçada binalar
14
1591031
5672562
2026-06-29T20:41:22Z
MustafaCavlak
59368
Yeni sayfa : {{kategori konu|dil=ru|konu=binalar}}
5672562
wikitext
text/x-wiki
{{kategori konu|dil=ru|konu=binalar}}
j89plyu4suf45kekvtxmm75yzqeqh71
театры
0
1591032
5672563
2026-06-29T20:43:32Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Ad=== {{başlık başı|ru|çekimli ad|baş=теа́тры}} # {{çekim|dil=ru|теа́тр||nom//acc|ç}}
5672563
wikitext
text/x-wiki
==Rusça==
===Ad===
{{başlık başı|ru|çekimli ad|baş=теа́тры}}
# {{çekim|dil=ru|теа́тр||nom//acc|ç}}
2fhk497vt69nmxiwmvkjq7gpt4sjszf
театра
0
1591033
5672564
2026-06-29T20:44:32Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Ad=== {{başlık başı|ru|çekimli ad|baş=теа́тра}} # {{çekim|dil=ru|теа́тр||gen|t}}
5672564
wikitext
text/x-wiki
==Rusça==
===Ad===
{{başlık başı|ru|çekimli ad|baş=теа́тра}}
# {{çekim|dil=ru|теа́тр||gen|t}}
hisy27ustzqf84kx180kl068mfdlbk2
театров
0
1591034
5672565
2026-06-29T20:45:27Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Ad=== {{başlık başı|ru|çekimli ad|baş=теа́тров}} # {{çekim|dil=ru|теа́тр||gen|ç}}
5672565
wikitext
text/x-wiki
==Rusça==
===Ad===
{{başlık başı|ru|çekimli ad|baş=теа́тров}}
# {{çekim|dil=ru|теа́тр||gen|ç}}
9u8doar847611s8oxrep5hdyudxgybs
театру
0
1591035
5672566
2026-06-29T20:46:06Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Ad=== {{başlık başı|ru|çekimli ad|baş=теа́тру}} # {{çekim|dil=ru|теа́тр||dat|t}}
5672566
wikitext
text/x-wiki
==Rusça==
===Ad===
{{başlık başı|ru|çekimli ad|baş=теа́тру}}
# {{çekim|dil=ru|теа́тр||dat|t}}
d47e9nzih3tram6ueilfnn0083763o1
театрам
0
1591036
5672567
2026-06-29T20:46:38Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Ad=== {{başlık başı|ru|çekimli ad|baş=теа́трам}} # {{çekim|dil=ru|теа́тр||dat|ç}}
5672567
wikitext
text/x-wiki
==Rusça==
===Ad===
{{başlık başı|ru|çekimli ad|baş=теа́трам}}
# {{çekim|dil=ru|теа́тр||dat|ç}}
rcbqon3o3shs71nvq6nm7u5kjzptr43
театром
0
1591037
5672568
2026-06-29T20:47:10Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Ad=== {{başlık başı|ru|çekimli ad|baş=теа́тром}} # {{çekim|dil=ru|теа́тр||araç|t}}
5672568
wikitext
text/x-wiki
==Rusça==
===Ad===
{{başlık başı|ru|çekimli ad|baş=теа́тром}}
# {{çekim|dil=ru|теа́тр||araç|t}}
87se4hs5g4e4c6qvzxfnjiml3im39wu
театрами
0
1591038
5672569
2026-06-29T20:47:44Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Ad=== {{başlık başı|ru|çekimli ad|baş=теа́трами}} # {{çekim|dil=ru|теа́тр||araç|ç}}
5672569
wikitext
text/x-wiki
==Rusça==
===Ad===
{{başlık başı|ru|çekimli ad|baş=теа́трами}}
# {{çekim|dil=ru|теа́тр||araç|ç}}
3y5oq4v8ml2pxtxlo8hprohizsb63kf
театре
0
1591039
5672571
2026-06-29T20:48:13Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Ad=== {{başlık başı|ru|çekimli ad|baş=теа́тре}} # {{çekim|dil=ru|теа́тр||ilgeç|t}}
5672571
wikitext
text/x-wiki
==Rusça==
===Ad===
{{başlık başı|ru|çekimli ad|baş=теа́тре}}
# {{çekim|dil=ru|теа́тр||ilgeç|t}}
6emtmae13ghg1jgww2pavjfnh3chsq1
театрах
0
1591040
5672573
2026-06-29T20:48:43Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Ad=== {{başlık başı|ru|çekimli ad|baş=теа́трах}} # {{çekim|dil=ru|теа́тр||ilgeç|ç}}
5672573
wikitext
text/x-wiki
==Rusça==
===Ad===
{{başlık başı|ru|çekimli ad|baş=теа́трах}}
# {{çekim|dil=ru|теа́тр||ilgeç|ç}}
9u3al3sbtpulxmrbhtogiwlrfj32vr1
театральный
0
1591041
5672577
2026-06-29T20:50:10Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Ön ad=== {{ru-ön ad|театра́льный}} # [[tiyatral]]
5672577
wikitext
text/x-wiki
==Rusça==
===Ön ad===
{{ru-ön ad|театра́льный}}
# [[tiyatral]]
lyam6jbn367yzpkkruqk1y3qeagl8b1
скорая помощь
0
1591042
5672584
2026-06-29T20:57:48Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Ad=== {{başlık başı|ru|ad|baş=[[скорый|ско́рая]] [[по́мощь]]|c=d}} # [[ambulans]]
5672584
wikitext
text/x-wiki
==Rusça==
===Ad===
{{başlık başı|ru|ad|baş=[[скорый|ско́рая]] [[по́мощь]]|c=d}}
# [[ambulans]]
f1x73tqniph0c8wv5ftuwafjz3slc0j
γλωσσοδέτης
0
1591043
5672586
2026-06-29T21:02:18Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|e|γλωσσοδέτες}} # [[tekerleme]] ====Çekimleme==== {{el-aE-ης-ες-2b|γλωσσοδέτ|γλωσσοδετ}}
5672586
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|e|γλωσσοδέτες}}
# [[tekerleme]]
====Çekimleme====
{{el-aE-ης-ες-2b|γλωσσοδέτ|γλωσσοδετ}}
jborxk1mqywu2s2ag76sqkincrkpmx3
скороговорка
0
1591044
5672589
2026-06-29T21:05:12Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Ad=== {{başlık başı|ru|ad|baş=скорогово́рка|c=d}} # [[tekerleme]] ====Çekimleme==== {{ru-ad-cansız-d-D-a|скорогово́рка}}
5672589
wikitext
text/x-wiki
==Rusça==
===Ad===
{{başlık başı|ru|ad|baş=скорогово́рка|c=d}}
# [[tekerleme]]
====Çekimleme====
{{ru-ad-cansız-d-D-a|скорогово́рка}}
4tkkctvurkndqf6ppbweoj1hqi8ll1i
говорящий
0
1591045
5672594
2026-06-29T21:16:47Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Ortaç=== {{başlık başı|ru|ortaç|baş=говоря́щий}} # {{çekim|dil=ru|говори́ть||pres|act|tamamlanmamış|part}}
5672594
wikitext
text/x-wiki
==Rusça==
===Ortaç===
{{başlık başı|ru|ortaç|baş=говоря́щий}}
# {{çekim|dil=ru|говори́ть||pres|act|tamamlanmamış|part}}
bygybvov5f19g27r42lnvz0rojv1yeb
говорю
0
1591046
5672595
2026-06-29T21:19:00Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Eylem=== {{başlık başı|ru|çekimli eylem|baş=говорю́}} # {{çekim|dil=ru|говори́ть||1t|pres|ind|tamamlanmamış}}
5672595
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{başlık başı|ru|çekimli eylem|baş=говорю́}}
# {{çekim|dil=ru|говори́ть||1t|pres|ind|tamamlanmamış}}
70xy09w2twt5mybeqiwam4skzzd5u52
говоришь
0
1591047
5672596
2026-06-29T21:21:15Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Eylem=== {{başlık başı|ru|çekimli eylem|baş=говори́шь}} # {{çekim|dil=ru|говори́ть||2t|pres|ind|tamamlanmamış}}
5672596
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{başlık başı|ru|çekimli eylem|baş=говори́шь}}
# {{çekim|dil=ru|говори́ть||2t|pres|ind|tamamlanmamış}}
66ihyhwzbvp4lmawfhkaixbohwishs4
буду
0
1591048
5672597
2026-06-29T21:32:22Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Eylem=== {{başlık başı|ru|çekimli eylem|baş=бу́ду}} # {{çekim|dil=ru|быть||1t|fut|ind|tamamlanmamış}}
5672597
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{başlık başı|ru|çekimli eylem|baş=бу́ду}}
# {{çekim|dil=ru|быть||1t|fut|ind|tamamlanmamış}}
72ui8luerk75lctz1gapikk2719gn0q
будешь
0
1591049
5672598
2026-06-29T21:33:53Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Eylem=== {{başlık başı|ru|çekimli eylem|baş=бу́дешь}} # {{çekim|dil=ru|быть||2t|fut|ind|tamamlanmamış}}
5672598
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{başlık başı|ru|çekimli eylem|baş=бу́дешь}}
# {{çekim|dil=ru|быть||2t|fut|ind|tamamlanmamış}}
b38zgc1jaenzebrbvp8r2onhksv5evl
будет
0
1591050
5672599
2026-06-29T21:35:04Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Eylem=== {{başlık başı|ru|çekimli eylem|baş=бу́дет}} # {{çekim|dil=ru|быть||3t|fut|ind|tamamlanmamış}}
5672599
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{başlık başı|ru|çekimli eylem|baş=бу́дет}}
# {{çekim|dil=ru|быть||3t|fut|ind|tamamlanmamış}}
j8v2ir9xm6qaju0d7wmosprd4mpssnz
будем
0
1591051
5672600
2026-06-29T21:36:20Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Eylem=== {{başlık başı|ru|çekimli eylem|baş=бу́дем}} # {{çekim|dil=ru|быть||1ç|fut|ind|tamamlanmamış}}
5672600
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{başlık başı|ru|çekimli eylem|baş=бу́дем}}
# {{çekim|dil=ru|быть||1ç|fut|ind|tamamlanmamış}}
1lq60grdizqqrcwl6pbuqign5ggpdfk
будете
0
1591052
5672601
2026-06-29T21:37:27Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Eylem=== {{başlık başı|ru|çekimli eylem|baş=бу́дете}} # {{çekim|dil=ru|быть||2ç|fut|ind|tamamlanmamış}}
5672601
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{başlık başı|ru|çekimli eylem|baş=бу́дете}}
# {{çekim|dil=ru|быть||2ç|fut|ind|tamamlanmamış}}
01kdk7eji69ahh4tte4juic27oxu0kv
будут
0
1591053
5672602
2026-06-29T21:38:11Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Eylem=== {{başlık başı|ru|çekimli eylem|baş=бу́дут}} # {{çekim|dil=ru|быть||3ç|fut|ind|tamamlanmamış}}
5672602
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{başlık başı|ru|çekimli eylem|baş=бу́дут}}
# {{çekim|dil=ru|быть||3ç|fut|ind|tamamlanmamış}}
sjol79wetewma24hux9etvseie8y4js
мыслить
0
1591054
5672603
2026-06-29T21:43:30Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Eylem=== {{ru-eylem|мы́слить|impf}} # [[düşünmek]]
5672603
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{ru-eylem|мы́слить|impf}}
# [[düşünmek]]
glkt52rzwpztu07w91fsw07kojfa2mm
существовать
0
1591055
5672604
2026-06-29T21:45:37Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== ===Eylem=== {{ru-eylem|существова́ть|impf|pf=просуществова́ть}} # [[var olmak]]
5672604
wikitext
text/x-wiki
==Rusça==
===Eylem===
{{ru-eylem|существова́ть|impf|pf=просуществова́ть}}
# [[var olmak]]
bgh5f1mvitaasink5sxvbe90czc9lmw
ekzisti
0
1591056
5672605
2026-06-29T21:50:37Z
MustafaCavlak
59368
Yeni sayfa : ==Esperanto dili== ===Eylem=== {{eo-eylem}} # {{t|dil=eo|geçişsiz}} [[var olmak]] ====Çekimleme==== {{eo-eylem-tablo|geçişsiz=1}} ===Ek okumalar=== * {{R:eo:PIV 2020}}
5672605
wikitext
text/x-wiki
==Esperanto dili==
===Eylem===
{{eo-eylem}}
# {{t|dil=eo|geçişsiz}} [[var olmak]]
====Çekimleme====
{{eo-eylem-tablo|geçişsiz=1}}
===Ek okumalar===
* {{R:eo:PIV 2020}}
jktci6ed19l7bzpxbgvs200zkbiowe4
ekzistinta
0
1591057
5672606
2026-06-29T21:52:02Z
MustafaCavlak
59368
Yeni sayfa : ==Esperanto dili== ===Ortaç=== {{eo-ortaç}} # {{eo-çekim|ekzist|anta}}
5672606
wikitext
text/x-wiki
==Esperanto dili==
===Ortaç===
{{eo-ortaç}}
# {{eo-çekim|ekzist|anta}}
737bjhdtw6ubglbbqvef8xjom3vl5cx
5672607
5672606
2026-06-29T21:52:52Z
MustafaCavlak
59368
5672607
wikitext
text/x-wiki
==Esperanto dili==
===Ortaç===
{{eo-ortaç}}
# {{eo-çekim|ekzist|inta}}
skqy8q33172fkxq7cds28t5d45u0i8d
ekzistanta
0
1591058
5672608
2026-06-29T21:53:04Z
MustafaCavlak
59368
Yeni sayfa : ==Esperanto dili== ===Ortaç=== {{eo-ortaç}} # {{eo-çekim|ekzist|anta}}
5672608
wikitext
text/x-wiki
==Esperanto dili==
===Ortaç===
{{eo-ortaç}}
# {{eo-çekim|ekzist|anta}}
737bjhdtw6ubglbbqvef8xjom3vl5cx
ekzistonta
0
1591059
5672609
2026-06-29T21:53:20Z
MustafaCavlak
59368
Yeni sayfa : ==Esperanto dili== ===Ortaç=== {{eo-ortaç}} # {{eo-çekim|ekzist|onta}}
5672609
wikitext
text/x-wiki
==Esperanto dili==
===Ortaç===
{{eo-ortaç}}
# {{eo-çekim|ekzist|onta}}
7ef4m3ba2kpwpctw3zzuxmk1vh0lyx5
ekzistinto
0
1591060
5672610
2026-06-29T21:53:54Z
MustafaCavlak
59368
Yeni sayfa : ==Esperanto dili== ===Mastar=== {{eo-mastar}} # {{eo-çekim|ekzist|into}}
5672610
wikitext
text/x-wiki
==Esperanto dili==
===Mastar===
{{eo-mastar}}
# {{eo-çekim|ekzist|into}}
5roq9f8sfrk6a8ta1xbgmel66xk41xl
ekzistanto
0
1591061
5672611
2026-06-29T21:54:12Z
MustafaCavlak
59368
Yeni sayfa : ==Esperanto dili== ===Mastar=== {{eo-mastar}} # {{eo-çekim|ekzist|anto}}
5672611
wikitext
text/x-wiki
==Esperanto dili==
===Mastar===
{{eo-mastar}}
# {{eo-çekim|ekzist|anto}}
habef4qhpj9oh8uvogzu6ra4z3k5ln3
ekzistonto
0
1591062
5672612
2026-06-29T21:54:30Z
MustafaCavlak
59368
Yeni sayfa : ==Esperanto dili== ===Mastar=== {{eo-mastar}} # {{eo-çekim|ekzist|onto}}
5672612
wikitext
text/x-wiki
==Esperanto dili==
===Mastar===
{{eo-mastar}}
# {{eo-çekim|ekzist|onto}}
8qk64vh6s8gmwbz1sxh18n1aa7zqoad
ekzistinte
0
1591063
5672613
2026-06-29T21:55:08Z
MustafaCavlak
59368
Yeni sayfa : ==Esperanto dili== ===Ulaç=== {{başlık başı|eo|ulaç}} # {{eo-çekim|ekzist|inte}}
5672613
wikitext
text/x-wiki
==Esperanto dili==
===Ulaç===
{{başlık başı|eo|ulaç}}
# {{eo-çekim|ekzist|inte}}
8p8u1oztgi8x71iog1gm1s4jv0xi547
ekzistante
0
1591064
5672614
2026-06-29T21:55:25Z
MustafaCavlak
59368
Yeni sayfa : ==Esperanto dili== ===Ulaç=== {{başlık başı|eo|ulaç}} # {{eo-çekim|ekzist|ante}}
5672614
wikitext
text/x-wiki
==Esperanto dili==
===Ulaç===
{{başlık başı|eo|ulaç}}
# {{eo-çekim|ekzist|ante}}
pl055fqrjo64zgl4gvu3w6jm101n7bn
ekzistonte
0
1591065
5672615
2026-06-29T21:55:43Z
MustafaCavlak
59368
Yeni sayfa : ==Esperanto dili== ===Ulaç=== {{başlık başı|eo|ulaç}} # {{eo-çekim|ekzist|onte}}
5672615
wikitext
text/x-wiki
==Esperanto dili==
===Ulaç===
{{başlık başı|eo|ulaç}}
# {{eo-çekim|ekzist|onte}}
sjikae1nw9xwl1gutcfo7hb6l3kbr0h
ekzistintan
0
1591066
5672616
2026-06-29T21:56:54Z
MustafaCavlak
59368
Yeni sayfa : ==Esperanto dili== ===Ortaç=== {{başlık başı|eo|çekimli ortaç}} # {{eo-çekim|ekzist|intan}}
5672616
wikitext
text/x-wiki
==Esperanto dili==
===Ortaç===
{{başlık başı|eo|çekimli ortaç}}
# {{eo-çekim|ekzist|intan}}
qzeqwoy2if4zco54e5rrckhmyhg3mix
ekzistintaj
0
1591067
5672617
2026-06-29T21:57:20Z
MustafaCavlak
59368
Yeni sayfa : ==Esperanto dili== ===Ortaç=== {{başlık başı|eo|çekimli ortaç}} # {{eo-çekim|ekzist|intaj}}
5672617
wikitext
text/x-wiki
==Esperanto dili==
===Ortaç===
{{başlık başı|eo|çekimli ortaç}}
# {{eo-çekim|ekzist|intaj}}
m9hhag9uhey23lxyq6x98kn700xwg8p
ekzistintajn
0
1591068
5672618
2026-06-29T21:57:42Z
MustafaCavlak
59368
Yeni sayfa : ==Esperanto dili== ===Ortaç=== {{başlık başı|eo|çekimli ortaç}} # {{eo-çekim|ekzist|intajn}}
5672618
wikitext
text/x-wiki
==Esperanto dili==
===Ortaç===
{{başlık başı|eo|çekimli ortaç}}
# {{eo-çekim|ekzist|intajn}}
tk64czzmxjsuczdxm1irsogihqvkf11
ekzistantan
0
1591069
5672619
2026-06-29T21:58:01Z
MustafaCavlak
59368
Yeni sayfa : ==Esperanto dili== ===Ortaç=== {{başlık başı|eo|çekimli ortaç}} # {{eo-çekim|ekzist|antan}}
5672619
wikitext
text/x-wiki
==Esperanto dili==
===Ortaç===
{{başlık başı|eo|çekimli ortaç}}
# {{eo-çekim|ekzist|antan}}
sukqh7d7bh90lzyqx7i8d3nacpahzdx
ekzistantaj
0
1591070
5672620
2026-06-29T21:58:22Z
MustafaCavlak
59368
Yeni sayfa : ==Esperanto dili== ===Ortaç=== {{başlık başı|eo|çekimli ortaç}} # {{eo-çekim|ekzist|antaj}}
5672620
wikitext
text/x-wiki
==Esperanto dili==
===Ortaç===
{{başlık başı|eo|çekimli ortaç}}
# {{eo-çekim|ekzist|antaj}}
t11sa36ualufslq98zqj0fbjqsq781j
ekzistantajn
0
1591071
5672621
2026-06-29T21:58:46Z
MustafaCavlak
59368
Yeni sayfa : ==Esperanto dili== ===Ortaç=== {{başlık başı|eo|çekimli ortaç}} # {{eo-çekim|ekzist|antajn}}
5672621
wikitext
text/x-wiki
==Esperanto dili==
===Ortaç===
{{başlık başı|eo|çekimli ortaç}}
# {{eo-çekim|ekzist|antajn}}
b9nkry4wx086gr6omy0jymjmepqraqm
ekzistontan
0
1591072
5672622
2026-06-29T21:59:18Z
MustafaCavlak
59368
Yeni sayfa : ==Esperanto dili== ===Ortaç=== {{başlık başı|eo|çekimli ortaç}} # {{eo-çekim|ekzist|ontan}}
5672622
wikitext
text/x-wiki
==Esperanto dili==
===Ortaç===
{{başlık başı|eo|çekimli ortaç}}
# {{eo-çekim|ekzist|ontan}}
e9ry9d0rkkebjm2anda7wp1uwgx4ioy
ekzistontaj
0
1591073
5672623
2026-06-29T21:59:39Z
MustafaCavlak
59368
Yeni sayfa : ==Esperanto dili== ===Ortaç=== {{başlık başı|eo|çekimli ortaç}} # {{eo-çekim|ekzist|ontaj}}
5672623
wikitext
text/x-wiki
==Esperanto dili==
===Ortaç===
{{başlık başı|eo|çekimli ortaç}}
# {{eo-çekim|ekzist|ontaj}}
anm845ptz1s6pvzmp2s7qj9xinp4afw
ekzistontajn
0
1591074
5672624
2026-06-29T22:00:00Z
MustafaCavlak
59368
Yeni sayfa : ==Esperanto dili== ===Ortaç=== {{başlık başı|eo|çekimli ortaç}} # {{eo-çekim|ekzist|ontajn}}
5672624
wikitext
text/x-wiki
==Esperanto dili==
===Ortaç===
{{başlık başı|eo|çekimli ortaç}}
# {{eo-çekim|ekzist|ontajn}}
52xj5sfzgifx90kxktcx1w1thosjts9
λεωφόροι
0
1591075
5672632
2026-06-29T22:18:29Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|λεωφόρος||nom//voc|ç}}
5672632
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|λεωφόρος||nom//voc|ç}}
f42n7sofc1brtfmwlhqn4rlxjs7bmf3
λεωφόρου
0
1591076
5672633
2026-06-29T22:18:50Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|λεωφόρος||gen|t}}
5672633
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|λεωφόρος||gen|t}}
igx0dylk0vb23o59vhi16rorfxi5xkp
λεωφόρων
0
1591077
5672634
2026-06-29T22:19:12Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|λεωφόρος||gen|ç}}
5672634
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|λεωφόρος||gen|ç}}
005eaus1e4jf07ezo9pfq4h7le9a2ap
λεωφόρο
0
1591078
5672635
2026-06-29T22:19:24Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|λεωφόρος||acc|t}}
5672635
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|λεωφόρος||acc|t}}
n87fo0huqn5z797pu0rr3chcopdni1j
λεωφόρους
0
1591079
5672636
2026-06-29T22:19:40Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|λεωφόρος||acc|ç}}
5672636
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|λεωφόρος||acc|ç}}
k5krn7bldn8x2xgxz5jqpy8pssvokkg
λεωφόρε
0
1591080
5672637
2026-06-29T22:19:53Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|λεωφόρος||voc|t}}
5672637
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|λεωφόρος||voc|t}}
3rxc1mxvfnfk523d53zsgoamk71qzxh
αερολιμένα
0
1591081
5672638
2026-06-29T22:20:45Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|αερολιμένας||gen//acc//voc|t}}
5672638
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|αερολιμένας||gen//acc//voc|t}}
hd0y9javoctgucbpidqz17sqvbw138p
αερολιμένων
0
1591082
5672640
2026-06-29T22:21:18Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|αερολιμένας||gen|ç}}
5672640
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|αερολιμένας||gen|ç}}
50hf3y3rkp2xq3l2gc0d3kqbfbe8b2t
-τήρες
0
1591083
5672641
2026-06-29T22:22:16Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Son ek=== {{başlık başı|el|çekimli son ek}} # {{çekim|dil=el|-τήρας||nom//acc//voc|ç}}
5672641
wikitext
text/x-wiki
==Yunanca==
===Son ek===
{{başlık başı|el|çekimli son ek}}
# {{çekim|dil=el|-τήρας||nom//acc//voc|ç}}
fanfs5pu3he07uax11oh48mo1lb1chd
σωλήνες
0
1591084
5672642
2026-06-29T22:24:40Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|σωλήνας||nom//acc//voc|ç}}
5672642
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|σωλήνας||nom//acc//voc|ç}}
hqnppu8scpvy8389w53tjo3g45suzjq
σωλήνα
0
1591085
5672643
2026-06-29T22:25:07Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|σωλήνας||gen//acc//voc|t}}
5672643
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|σωλήνας||gen//acc//voc|t}}
9lle8v11b1m66ermqif4guus2b973r4
σωλήνων
0
1591086
5672644
2026-06-29T22:25:21Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|σωλήνας||gen|ç}}
5672644
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|σωλήνας||gen|ç}}
0wmblw4iztuk9cah072b54paz3uymru
αδαμαντοπωλεία
0
1591087
5672646
2026-06-29T22:30:17Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|αδαμαντοπωλείο||nom//acc//voc|ç}}
5672646
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|αδαμαντοπωλείο||nom//acc//voc|ç}}
4izzyyaenivpqh18u9hliwc1fu5i4sr
αδαμαντοπωλείου
0
1591088
5672647
2026-06-29T22:30:35Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|αδαμαντοπωλείο||gen|t}}
5672647
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|αδαμαντοπωλείο||gen|t}}
00soa78okb2fnublt53aggpmpmb4mnc
αδαμαντοπωλείων
0
1591089
5672648
2026-06-29T22:30:51Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|αδαμαντοπωλείο||gen|ç}}
5672648
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|αδαμαντοπωλείο||gen|ç}}
r2thwfc0dlruabuxl7xio8v8i0m78av
ψυχιατρεία
0
1591090
5672649
2026-06-29T22:32:12Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|ψυχιατρείο||nom//acc//voc|ç}}
5672649
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|ψυχιατρείο||nom//acc//voc|ç}}
14j4yt3y1o49b7zfgo82m8vmn54cwis
ψυχιατρείου
0
1591091
5672650
2026-06-29T22:32:32Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|ψυχιατρείο||gen|t}}
5672650
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|ψυχιατρείο||gen|t}}
d62en9y3eaw9wm7a1pvf72kpgu3573l
ψυχιατρείων
0
1591092
5672651
2026-06-29T22:32:49Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|ψυχιατρείο||gen|ç}}
5672651
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|ψυχιατρείο||gen|ç}}
275d62neqan4gka94euh6m7n5syp2nn
χόρτου
0
1591093
5672652
2026-06-29T22:33:29Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|χόρτος||gen|t}}
5672652
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|χόρτος||gen|t}}
q8k4rc75m4lwgo4rims1l9h3ffyoxn1
5672653
5672652
2026-06-29T22:33:38Z
MustafaCavlak
59368
5672653
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|χόρτο||gen|t}}
d42p8wnmnq1icg62a6npoixjggtdgbd
χόρτων
0
1591094
5672654
2026-06-29T22:33:58Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|χόρτο||gen|ç}}
5672654
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|χόρτο||gen|ç}}
3vhsrilkvb3j4fbx0spzohcl7rxboiu
φαρμακεία
0
1591095
5672655
2026-06-29T22:34:39Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|φαρμακείο||nom//acc//voc|ç}}
5672655
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|φαρμακείο||nom//acc//voc|ç}}
35ib5cuyxao2r0hls8i8yu89t6vvksv
φαρμακείου
0
1591096
5672656
2026-06-29T22:34:54Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|φαρμακείο||gen|t}}
5672656
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|φαρμακείο||gen|t}}
6nmkipzrwjliltfdivqwyx0b0dypsja
φαρμακείων
0
1591097
5672657
2026-06-29T22:35:08Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|φαρμακείο||gen|ç}}
5672657
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|φαρμακείο||gen|ç}}
q1k6t9z2tlueo5oltpmxtbmp9caae3f
στηθοσκόπια
0
1591098
5672658
2026-06-29T22:36:53Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|στηθοσκόπιο||nom//acc//voc|ç}}
5672658
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|στηθοσκόπιο||nom//acc//voc|ç}}
lxde0uh53rawk7hqhqtvpsi4xpdzlcq
στηθοσκόπιου
0
1591099
5672660
2026-06-29T22:37:08Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|στηθοσκόπιο||gen|t}}
5672660
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|στηθοσκόπιο||gen|t}}
hssqs7f1izngnvwk2p5hrrwqhl8wpgy
στηθοσκόπιων
0
1591100
5672661
2026-06-29T22:37:20Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|στηθοσκόπιο||gen|ç}}
5672661
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|στηθοσκόπιο||gen|ç}}
don0dr6gvodgt61iuamqb3iri6ua6dm
ρόπτρου
0
1591101
5672662
2026-06-29T22:38:14Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|ρόπτρο||gen|t}}
5672662
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|ρόπτρο||gen|t}}
1a8h77qncbfxw5oe19nxil790xkerpz
ρόπτρων
0
1591102
5672663
2026-06-29T22:38:35Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{başlık başı|el|çekimli ad}} # {{çekim|dil=el|ρόπτρο||gen|ç}}
5672663
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{başlık başı|el|çekimli ad}}
# {{çekim|dil=el|ρόπτρο||gen|ç}}
cfi0mw9q33xckhjy363h23p2nxbw64x
фара
0
1591103
5672664
2026-06-29T23:23:24Z
MustafaCavlak
59368
Yeni sayfa : ==Rusça== {{vikipedi|dil=ru}} [[Dosya:Car detail 1.jpg|küçükresim|'''фара''']] ===Köken=== {{nakledilen|ru|fr|phare}}, {{kökenli|ru|la|pharus}}, {{kökenli|ru|grc|Φάρος}}. ===Söyleniş=== * {{IPA|dil=ru|[ˈfarə]}} * {{ses|dil=ru|Ru-фара.ogg}} ===Ad=== {{başlık başı|ru|ad|baş=фа́ра|c=d}} # [[far]] ====Çekimleme==== {{ru-ad-cansız-s-D-a|фа́ра}} ===Kaynakça=== * {{R:ru:BTS}} * {{R:ru:Zarva}}
5672664
wikitext
text/x-wiki
==Rusça==
{{vikipedi|dil=ru}}
[[Dosya:Car detail 1.jpg|küçükresim|'''фара''']]
===Köken===
{{nakledilen|ru|fr|phare}}, {{kökenli|ru|la|pharus}}, {{kökenli|ru|grc|Φάρος}}.
===Söyleniş===
* {{IPA|dil=ru|[ˈfarə]}}
* {{ses|dil=ru|Ru-фара.ogg}}
===Ad===
{{başlık başı|ru|ad|baş=фа́ра|c=d}}
# [[far]]
====Çekimleme====
{{ru-ad-cansız-s-D-a|фа́ра}}
===Kaynakça===
* {{R:ru:BTS}}
* {{R:ru:Zarva}}
atm35n87vydgx6oa82aboud132dleag
ξεκαρφώνω
0
1591104
5672665
2026-06-30T00:36:01Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Eylem=== {{el-eylem}} # [[çivi]]yle sabitlenmiş bir nesneyi yerinden çıkarmak, çivisini [[sökmek]], çivilerini [[çıkarmak]]
5672665
wikitext
text/x-wiki
==Yunanca==
===Eylem===
{{el-eylem}}
# [[çivi]]yle sabitlenmiş bir nesneyi yerinden çıkarmak, çivisini [[sökmek]], çivilerini [[çıkarmak]]
37gr1jw3j32t2kpkykggqo1eosbk0lm
κάρφωμα
0
1591105
5672666
2026-06-30T00:38:20Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|n}} # [[çivileme]] # {{t|dil=el|spor}} [[smaç]]
5672666
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|n}}
# [[çivileme]]
# {{t|dil=el|spor}} [[smaç]]
n5yfxpz1nj698km7oivkf1ini6dcas1
αποκαλύπτω
0
1591106
5672667
2026-06-30T00:44:17Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Eylem=== {{el-eylem}} # [[ortaya çıkarmak]], [[ortaya koymak]]
5672667
wikitext
text/x-wiki
==Yunanca==
===Eylem===
{{el-eylem}}
# [[ortaya çıkarmak]], [[ortaya koymak]]
jh556bu2r1quz0twjlmysa0lbggb9h3
κάλυψη
0
1591107
5672668
2026-06-30T00:49:01Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|d}} # [[örtme]], [[kaplama]] # [[kapsama]]
5672668
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|d}}
# [[örtme]], [[kaplama]]
# [[kapsama]]
6chmdut6m5ty2j91bkk19k8kyopm957
καλύπτομαι
0
1591108
5672669
2026-06-30T00:50:08Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Eylem=== {{el-eylem|tip=edilgen}} # {{çekim|dil=el|καλύπτω||pass}}
5672669
wikitext
text/x-wiki
==Yunanca==
===Eylem===
{{el-eylem|tip=edilgen}}
# {{çekim|dil=el|καλύπτω||pass}}
psswycb4orf8hvmxpyjd2nrdfzwcsa5
χιονοκάλυψη
0
1591109
5672670
2026-06-30T00:52:15Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|d}} # [[kar]] [[örtü]]sü, karla kaplanma
5672670
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|d}}
# [[kar]] [[örtü]]sü, karla kaplanma
hduwu6bjkz98gcm7egd6znpclqxyptk
χιονόπτωση
0
1591110
5672671
2026-06-30T00:54:06Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|d}} # [[kar]] [[yağış]]ı, kar düşmesi
5672671
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|d}}
# [[kar]] [[yağış]]ı, kar düşmesi
1bt8n93vxtr9zjwzac0wseakwkf5szm
αξιολόγηση
0
1591111
5672672
2026-06-30T00:56:28Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|d}} # [[değerlendirme]]
5672672
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|d}}
# [[değerlendirme]]
6cp76smll1nvrfl27z9xfiq9g9nvv2d
αξιολογώ
0
1591112
5672673
2026-06-30T00:57:53Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Eylem=== {{el-eylem}} # [[değerlendirmek]]
5672673
wikitext
text/x-wiki
==Yunanca==
===Eylem===
{{el-eylem}}
# [[değerlendirmek]]
4r5sg4dbybxf7qypzzh9se01z418z23
αποτιμώ
0
1591113
5672674
2026-06-30T01:00:00Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Eylem=== {{el-eylem}} # [[değer biçmek]], [[değerlendirmek]]
5672674
wikitext
text/x-wiki
==Yunanca==
===Eylem===
{{el-eylem}}
# [[değer biçmek]], [[değerlendirmek]]
tkrdux0zev325iysy6ohgdebeuoz67e
εκτιμώ
0
1591114
5672675
2026-06-30T01:01:51Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Eylem=== {{el-eylem}} # [[takdir etmek]] # [[değerlendirmek]], [[tahmin etmek]], [[değer biçmek]]
5672675
wikitext
text/x-wiki
==Yunanca==
===Eylem===
{{el-eylem}}
# [[takdir etmek]]
# [[değerlendirmek]], [[tahmin etmek]], [[değer biçmek]]
qyqqgm0qu2512vohjscdda7oaiyaeqp
εκτίμηση
0
1591115
5672676
2026-06-30T01:03:28Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|d}} # [[değerlendirme]], [[tahmin]] # [[takdir]], takdir etme
5672676
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|d}}
# [[değerlendirme]], [[tahmin]]
# [[takdir]], takdir etme
ewc4upwqt2g2cndmla7tak9m7o8dxcm
υπολογισμός
0
1591116
5672677
2026-06-30T01:08:02Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|e}} # [[hesap]], [[hesaplama]]
5672677
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|e}}
# [[hesap]], [[hesaplama]]
3vb7pznwunhgxcdkt5bkdvolf1yqt46
κομπιουτεράκι
0
1591117
5672678
2026-06-30T01:10:16Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|n}} # [[hesap makinesi]]
5672678
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|n}}
# [[hesap makinesi]]
8cib4965hs3jzs5oqidvzol6e6vcs0f
φυλή
0
1591118
5672679
2026-06-30T01:12:26Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|d}} # [[ırk]] # [[kabile]]
5672679
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|d}}
# [[ırk]]
# [[kabile]]
tprnlnk5d2l2s6e9ezfo7nvzew3qsdy
φυλετικός
0
1591119
5672680
2026-06-30T01:14:14Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ön ad=== {{el-ön ad}} # [[ırksal]] # [[kabilesel]]
5672680
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[ırksal]]
# [[kabilesel]]
2ibj03mbwbm72cuvgtqdxj70xxa10wj
ırksal
0
1591120
5672681
2026-06-30T01:16:30Z
MustafaCavlak
59368
Yeni sayfa : ==Türkçe== ===Köken=== {{ek|dil=tr|ırk|sel|alt2=-sal}} ===Ön ad=== {{tr-ön ad|d=-}} # Irk ile ilgili. #: {{eş anlamlılar|tr|ırki}} ===Ek okumalar=== * {{KYK:TDK}}
5672681
wikitext
text/x-wiki
==Türkçe==
===Köken===
{{ek|dil=tr|ırk|sel|alt2=-sal}}
===Ön ad===
{{tr-ön ad|d=-}}
# Irk ile ilgili.
#: {{eş anlamlılar|tr|ırki}}
===Ek okumalar===
* {{KYK:TDK}}
9gozh15xjq8k6oze3y9db7m1j59edt5
ευρύς
0
1591121
5672683
2026-06-30T01:20:32Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ön ad=== {{el-ön ad}} # [[geniş]]
5672683
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[geniş]]
lf2hvjniqkmibz2zqe5ob7wub0vsjlt
ısrarcı
0
1591122
5672685
2026-06-30T01:26:05Z
MustafaCavlak
59368
Yeni sayfa : ==Türkçe== ===Köken=== {{ek|dil=tr|ısrar|ci|alt2=-cı}} ===Ön ad=== {{tr-ön ad}} # Israr eden. #: {{ux|tr|'''Israrcı''' insanlar yorucu olabilir.}}
5672685
wikitext
text/x-wiki
==Türkçe==
===Köken===
{{ek|dil=tr|ısrar|ci|alt2=-cı}}
===Ön ad===
{{tr-ön ad}}
# Israr eden.
#: {{ux|tr|'''Israrcı''' insanlar yorucu olabilir.}}
oe47s91dp4516lo1g438sazwqigpogq
εμμένω
0
1591123
5672686
2026-06-30T01:28:02Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Eylem=== {{el-eylem}} # [[ısrar etmek]]
5672686
wikitext
text/x-wiki
==Yunanca==
===Eylem===
{{el-eylem}}
# [[ısrar etmek]]
9ledvge2qdchcr3a0bnl3suzszqq1rg
τηλεχειριστήριο
0
1591124
5672687
2026-06-30T01:30:36Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|n}} # [[kumanda]]
5672687
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|n}}
# [[kumanda]]
jofca4wo0rv3dct2mju5eccrgto1bff
τηλεκοντρόλ
0
1591125
5672688
2026-06-30T01:31:24Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|n|inv}} # [[kumanda]]
5672688
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|n|inv}}
# [[kumanda]]
e161o7m7xpb8z17s9qpm1nunas4t53m
αυτοφωτογράφιση
0
1591126
5672689
2026-06-30T01:32:49Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|d}} # [[özçekim]]
5672689
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|d}}
# [[özçekim]]
m1z9jlb0ko6r9ze86ly5y89yhlgwn3n
αυτοφωτογραφία
0
1591127
5672690
2026-06-30T01:34:16Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|d}} # [[özçekim]]
5672690
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|d}}
# [[özçekim]]
m1z9jlb0ko6r9ze86ly5y89yhlgwn3n
αυτοφωτογραφίζομαι
0
1591128
5672691
2026-06-30T01:35:12Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Eylem=== {{el-eylem}} # [[özçekim yapmak]]
5672691
wikitext
text/x-wiki
==Yunanca==
===Eylem===
{{el-eylem}}
# [[özçekim yapmak]]
huxy99vvqetl6pt1u93f6lfrhyj9a80
αυτοπροσωπογραφία
0
1591129
5672692
2026-06-30T01:37:01Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|d}} # [[otoportre]]
5672692
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|d}}
# [[otoportre]]
eyttp5il8lscgh11pfgzvgdplwh1547
προσωπογραφία
0
1591130
5672693
2026-06-30T01:39:44Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|d}} # [[portre]]
5672693
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|d}}
# [[portre]]
59b7fvok9g755lhl7nwhjsf85w7l90h
συνάρτηση
0
1591131
5672694
2026-06-30T01:41:51Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|d}} # [[fonksiyon]]
5672694
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|d}}
# [[fonksiyon]]
qcvyf8fda8bjfnlrzbhos3ygpw98gpd
ορολογία
0
1591132
5672695
2026-06-30T01:43:27Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|d}} # [[terminoloji]]
5672695
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|d}}
# [[terminoloji]]
s84glykf7blu560qjcfvob78no58a30
μελάνι
0
1591133
5672696
2026-06-30T01:46:20Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|n}} # [[mürekkep]]
5672696
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|n}}
# [[mürekkep]]
dw84du08z1q7yqlzyxqnlj451e2q083
μελανοδοχείο
0
1591134
5672697
2026-06-30T01:47:26Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|n}} # [[mürekkeplik]], [[hokka]]
5672697
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|n}}
# [[mürekkeplik]], [[hokka]]
p8cr3vtpab6d07et1y01hcxewlqahy8
μελανώνω
0
1591135
5672698
2026-06-30T01:48:52Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Eylem=== {{el-eylem}} # [[mürekkeplemek]]
5672698
wikitext
text/x-wiki
==Yunanca==
===Eylem===
{{el-eylem}}
# [[mürekkeplemek]]
lgsetag21mmq2k8ws3fnns2i94v0ed9
μαλάκιο
0
1591136
5672699
2026-06-30T01:50:30Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|n}} # [[yumuşakça]]
5672699
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|n}}
# [[yumuşakça]]
4udici004fziy5ahbxvs90efh7r4fao
ομοταξία
0
1591137
5672700
2026-06-30T01:52:18Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|d}} # {{t|dil=el|taksonomi}} [[sınıf]]
5672700
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|d}}
# {{t|dil=el|taksonomi}} [[sınıf]]
ln8yb2n0nstugjqp8qqpl7abuhm8hk8
εγχώριος
0
1591138
5672701
2026-06-30T01:56:14Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ön ad=== {{el-ön ad}} # [[yerli]], [[yerel]], [[yurt içi]]
5672701
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[yerli]], [[yerel]], [[yurt içi]]
7r2nm8wtx9gpi1lvhtn4dyo41vz9m1q
οικιακός
0
1591139
5672702
2026-06-30T01:59:12Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ön ad=== {{el-ön ad}} # [[ev]]le ilgili, [[evsel]]
5672702
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[ev]]le ilgili, [[evsel]]
d4cypq6shbq1aewrpnaye2g8t9qqxau
ενδοοικογενειακός
0
1591140
5672703
2026-06-30T02:01:45Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ön ad=== {{el-ön ad}} # [[aile]] [[iç]]i #: {{ux|el|'''ενδοοικογενειακή''' βία|aile içi şiddet}}
5672703
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[aile]] [[iç]]i
#: {{ux|el|'''ενδοοικογενειακή''' βία|aile içi şiddet}}
1gc2bf0sgxiie00ex5621j95g13sev6
θερμικός
0
1591141
5672704
2026-06-30T02:06:43Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ön ad=== {{el-ön ad}} # [[ısıl]], [[termik]]
5672704
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad}}
# [[ısıl]], [[termik]]
b07je1a1o0rk7m0i668s66musd5lwh4
θόλος
0
1591142
5672705
2026-06-30T02:08:50Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|e}} # [[kubbe]]
5672705
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|e}}
# [[kubbe]]
kxh8h1hqqumpxlk4shnrmbua0vcu7i6
πλήττω
0
1591143
5672706
2026-06-30T02:12:02Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Eylem=== {{el-eylem}} # [[sıkılmak]] ===Eylem=== {{el-eylem}} # [[vurmak]], [[darbe indirmek]]
5672706
wikitext
text/x-wiki
==Yunanca==
===Eylem===
{{el-eylem}}
# [[sıkılmak]]
===Eylem===
{{el-eylem}}
# [[vurmak]], [[darbe indirmek]]
kxairhwn9w9hwuz6vo8p8bgwkfl62v6
καύσωνας
0
1591144
5672707
2026-06-30T02:15:15Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|e}} # [[sıcak]] [[hava]] [[dalga]]sı, [[yakıcı]] sıcak
5672707
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|e}}
# [[sıcak]] [[hava]] [[dalga]]sı, [[yakıcı]] sıcak
8wu3cz50j4kk5v1rj8qarn83xd30a5b
αντιμετωπίζω
0
1591145
5672708
2026-06-30T02:19:21Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Eylem=== {{el-eylem}} # [[yüzleşmek]] # [[başa çıkmak]], üstesinden gelmeye çalışmak # [[muamele etmek]]
5672708
wikitext
text/x-wiki
==Yunanca==
===Eylem===
{{el-eylem}}
# [[yüzleşmek]]
# [[başa çıkmak]], üstesinden gelmeye çalışmak
# [[muamele etmek]]
3vc4l4pn3u7g6v6914n0dsnauqmedyx
ολιγαρχία
0
1591146
5672709
2026-06-30T02:20:41Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|d}} # [[oligarşi]]
5672709
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|d}}
# [[oligarşi]]
q90dwq7mi9m9nkhpf4107zc4vetetiv
ολιγάρχης
0
1591147
5672710
2026-06-30T02:21:49Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|e}} # [[oligark]]
5672710
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|e}}
# [[oligark]]
qkecl6h27p3wly9lca03jtkyf2odw3g
çizgi film
0
1591148
5672718
2026-06-30T06:24:19Z
Satirdan kahraman
37401
Yeni sayfa : ==Türkçe== ===Köken=== *{{birleşik|dil=tr|çizgi|film}} ===Söyleniş=== *{{tr-IPA}} * {{h|dil=tr||çiz|gi|film}} ===Ad=== {{tr-ad}} [[File:Race Riot (1929 Cartoon).webm|küçükresim|Bir çizgi film örneği.]] #{{t|dil=tr|sinema}} Bir konuyla ilgili olarak karakterlerinin hareketlerini belirtecek biçimde art arda çizilmiş resimlerden oluşan sinema filmi. #* "Çizgi film izlemeyi çok seviyordu. Bıraksalar saatlerce, bıkmadan, çizgi film izleyebilirdi." - A...
5672718
wikitext
text/x-wiki
==Türkçe==
===Köken===
*{{birleşik|dil=tr|çizgi|film}}
===Söyleniş===
*{{tr-IPA}}
* {{h|dil=tr||çiz|gi|film}}
===Ad===
{{tr-ad}}
[[File:Race Riot (1929 Cartoon).webm|küçükresim|Bir çizgi film örneği.]]
#{{t|dil=tr|sinema}} Bir konuyla ilgili olarak karakterlerinin hareketlerini belirtecek biçimde art arda çizilmiş resimlerden oluşan sinema filmi.
#* "Çizgi film izlemeyi çok seviyordu. Bıraksalar saatlerce, bıkmadan, çizgi film izleyebilirdi." - Ali Çankırılı
====Çekimleme====
{{tr-ad-tablo}}
===Kaynakça===
* {{KYK:TDK}}
===Ek okumalar===
*{{proje bağlantısı|Vikipedi}}
ggv2006zi28i4m8x64cl8b13p6fiifz
Epiphyllum oxypetalum
0
1591149
5672723
2026-06-30T07:27:38Z
Turgut46
26665
/* */
5672723
wikitext
text/x-wiki
== Dillerarası ==
===Köken===
{{kökenli|mul|grc|ἐπιφύλλον ὀξυπέταλον}} alıntıdır.
===Özel ad===
{{başlık başı|mul|özel ad}}
[[Dosya:Día de apertura.jpg|Epiphyllum oxypetalum|küçükresim|250px]]
# {{t|kaktüsgiller|dil=mul}} ''[[Cactaceae]]'' (kaktüsgiller) familyasına ait, [[diken]] taşımayan epifitik veya litofitik bir [[sukulent]] [[kaktüs]] türü olup, [[Meksika]]'dan Orta Amerika'ya kadar uzanan tropikal ormanlarda doğal olarak yetişen, yassı ve yaprak benzeri gövdeleri sayesinde ağaç dallarında veya kayalarda tutunan ve beyaz çiçekleri sadece geceleri açan bir [[bitki]] türü.
5ny2f4rpfs06dnhwit3is2cgnem11u7
τσιγκούνης
0
1591150
5672726
2026-06-30T07:54:18Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ön ad=== {{el-ön ad|d=τσιγκούνα|n=τσιγκούνικο}} # [[cimri]] ====Çekimleme==== {{el-çekim-öa|çekim=ης-α-ικο|kök=τσιγκούν}}
5672726
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad|d=τσιγκούνα|n=τσιγκούνικο}}
# [[cimri]]
====Çekimleme====
{{el-çekim-öa|çekim=ης-α-ικο|kök=τσιγκούν}}
h2sk8rym8baiynzn0vrk9h9vmevujda
τσιγγούνης
0
1591151
5672727
2026-06-30T07:56:22Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ön ad=== {{el-ön ad|d=τσιγγούνα|n=τσιγγούνικο}} # {{farklı|dil=el|τσιγκούνης}} ====Çekimleme==== {{el-çekim-öa|çekim=ης-α-ικο|kök=τσιγγούν}}
5672727
wikitext
text/x-wiki
==Yunanca==
===Ön ad===
{{el-ön ad|d=τσιγγούνα|n=τσιγγούνικο}}
# {{farklı|dil=el|τσιγκούνης}}
====Çekimleme====
{{el-çekim-öa|çekim=ης-α-ικο|kök=τσιγγούν}}
o93mfkjb5rfm72xpzoar55xkdoztjl5
à nouveau
0
1591152
5672734
2026-06-30T08:40:27Z
MustafaCavlak
59368
Yeni sayfa : ==Fransızca== ===Söyleniş=== * {{fr-IPA}} ===Belirteç=== {{başlık başı|fr|belirteç}} # [[yeniden]]
5672734
wikitext
text/x-wiki
==Fransızca==
===Söyleniş===
* {{fr-IPA}}
===Belirteç===
{{başlık başı|fr|belirteç}}
# [[yeniden]]
q8iapj9l1p7u0f2yxs20ms4qnuux3h2
de nouveau
0
1591153
5672735
2026-06-30T08:42:08Z
MustafaCavlak
59368
Yeni sayfa : ==Fransızca== ===Söyleniş=== * {{fr-IPA}} ===Belirteç=== {{başlık başı|fr|belirteç}} # [[tekrar]], [[bir daha]]
5672735
wikitext
text/x-wiki
==Fransızca==
===Söyleniş===
* {{fr-IPA}}
===Belirteç===
{{başlık başı|fr|belirteç}}
# [[tekrar]], [[bir daha]]
febomxg750uo7vy14xeizazgfosv7xr
αναμένω
0
1591154
5672764
2026-06-30T09:38:46Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Eylem=== {{el-eylem}} # [[beklemek]], [[öngörmek]]
5672764
wikitext
text/x-wiki
==Yunanca==
===Eylem===
{{el-eylem}}
# [[beklemek]], [[öngörmek]]
oucrdp8fzngqiyhsowwangoorrpk14l
αφήγημα
0
1591155
5672765
2026-06-30T09:40:22Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|n}} # [[anlatı]]
5672765
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|n}}
# [[anlatı]]
k4mztndhrli95k860xykv2m6y9btpef
αφήγηση
0
1591156
5672766
2026-06-30T09:41:12Z
MustafaCavlak
59368
Yeni sayfa : ==Yunanca== ===Ad=== {{el-ad|d}} # [[anlatma]], [[anlatım]]
5672766
wikitext
text/x-wiki
==Yunanca==
===Ad===
{{el-ad|d}}
# [[anlatma]], [[anlatım]]
8f8alh45gjfas1fqdw6hyryetao7ixd