From 1e581fbd10e5fb646eef91cb8df444788f50d444 Mon Sep 17 00:00:00 2001 From: Krasimir Angelov Date: Wed, 10 Jun 2026 10:48:57 +0200 Subject: [PATCH] first draft of Ukrainian grammar --- src/ukrainian/AdjectiveUkr.gf | 22 +++++- src/ukrainian/AdverbUkr.gf | 17 ++++ src/ukrainian/CatUkr.gf | 34 +++++++- src/ukrainian/ConjunctionUkr.gf | 82 +++++++++++++++++++ src/ukrainian/ConstructionUkr.gf | 102 ++++++++++++++++++++++++ src/ukrainian/GrammarUkr.gf | 11 ++- src/ukrainian/IdiomUkr.gf | 46 +++++++++++ src/ukrainian/LangUkr.gf | 3 +- src/ukrainian/MorphoUkr.gf | 44 +++++------ src/ukrainian/NamesUkr.gf | 14 ++++ src/ukrainian/NounUkr.gf | 108 ++++++++++++++++++++++++- src/ukrainian/NumeralUkr.gf | 66 ++++++++++++++++ src/ukrainian/ParadigmsUkr.gf | 49 +++++++++--- src/ukrainian/PhraseUkr.gf | 16 +++- src/ukrainian/QuestionUkr.gf | 54 +++++++++++++ src/ukrainian/RelativeUkr.gf | 46 +++++++++++ src/ukrainian/ResUkr.gf | 79 ++++++++++++++++++- src/ukrainian/SentenceUkr.gf | 54 +++++++++++++ src/ukrainian/VerbUkr.gf | 131 +++++++++++++++++++++++++++++++ 19 files changed, 939 insertions(+), 39 deletions(-) create mode 100644 src/ukrainian/AdverbUkr.gf create mode 100644 src/ukrainian/ConjunctionUkr.gf create mode 100644 src/ukrainian/ConstructionUkr.gf create mode 100644 src/ukrainian/IdiomUkr.gf create mode 100644 src/ukrainian/NamesUkr.gf create mode 100644 src/ukrainian/NumeralUkr.gf create mode 100644 src/ukrainian/QuestionUkr.gf create mode 100644 src/ukrainian/RelativeUkr.gf create mode 100644 src/ukrainian/SentenceUkr.gf create mode 100644 src/ukrainian/VerbUkr.gf diff --git a/src/ukrainian/AdjectiveUkr.gf b/src/ukrainian/AdjectiveUkr.gf index c92be58b..6e375801 100644 --- a/src/ukrainian/AdjectiveUkr.gf +++ b/src/ukrainian/AdjectiveUkr.gf @@ -1,4 +1,24 @@ -concrete AdjectiveUkr of Adjective = CatUkr ** { +concrete AdjectiveUkr of Adjective = CatUkr ** open ResUkr in { lin PositA a = a ; + ComparA a np = {s=\\c,gn => "більш" ++ a.s ! c ! gn ++ "ніж" ++ np.s ! Nom} ; + ComplA2 a np = a ** { + s = \\c,gn => a.s ! c ! gn ++ prepNP a.c2 np + } ; + ReflA2 a = a ** { + s = \\c,gn => a.s ! c ! gn ++ a.c2.s ++ "себе" + } ; + UseA2 a = a ; + UseComparA a = {s=\\c,gn => "більш" ++ a.s ! c ! gn} ; + CAdvAP cadv ap np = {s=\\c,gn => cadv.s ++ ap.s ! c ! gn ++ cadv.p ++ np.s ! Nom} ; + AdjOrd ord = ord ; + SentAP ap sc = ap ** { + s = \\c,gn => ap.s ! c ! gn ++ sc.s + } ; + AdAP ada ap = ap ** { + s = \\c,gn => ada.s ++ ap.s ! c ! gn + } ; + AdvAP ap adv = ap ** { + s = \\c,gn => ap.s ! c ! gn ++ adv.s + } ; } diff --git a/src/ukrainian/AdverbUkr.gf b/src/ukrainian/AdverbUkr.gf new file mode 100644 index 00000000..b6d90c15 --- /dev/null +++ b/src/ukrainian/AdverbUkr.gf @@ -0,0 +1,17 @@ +concrete AdverbUkr of Adverb = CatUkr ** open ResUkr, (R = ParamX) in { + +lin + PositAdvAdj a = {s = a.s ! Nom ! GSg Neuter} ; + PrepNP prep np = {s = prepNP prep np} ; + + ComparAdvAdj cadv a np = { + s = cadv.s ++ a.s ! Nom ! GSg Neuter ++ cadv.p ++ np.s ! Nom + } ; + ComparAdvAdjS cadv a s = { + s = cadv.s ++ a.s ! Nom ! GSg Neuter ++ cadv.p ++ s.s + } ; + AdAdv ada adv = {s = ada.s ++ adv.s} ; + PositAdAAdj a = {s = a.s ! Nom ! GSg Neuter} ; + SubjS subj s = {s = subj.s ++ s.s} ; + AdnCAdv cadv = {s = cadv.s ++ cadv.p} ; +} diff --git a/src/ukrainian/CatUkr.gf b/src/ukrainian/CatUkr.gf index 9e6c87d6..971c3ef1 100644 --- a/src/ukrainian/CatUkr.gf +++ b/src/ukrainian/CatUkr.gf @@ -1,4 +1,4 @@ -concrete CatUkr of Cat = CommonX ** open ResUkr in { +concrete CatUkr of Cat = CommonX ** open ResUkr, (R = ParamX) in { lincat N = N ; lincat N2 = N ** {c2 : Compl} ; @@ -14,9 +14,41 @@ lincat Prep = Compl ; lincat CN = CommonNoun ; lincat AP = AdjPhrase ; lincat S = {s : Str} ; +lincat QS = {s : Str} ; +lincat RS = {s : Gender => Number => Str} ; +lincat Cl = {s : R.Tense => R.Polarity => Str} ; +lincat ClSlash = {s : R.Tense => R.Polarity => Str; c : Compl} ; +lincat SSlash = {s : Str; c : Compl} ; +lincat RCl = {s : Gender => Number => Str} ; +lincat QCl = {s : R.Tense => R.Polarity => Str} ; +lincat RP = {s : Gender => Number => Case => Str} ; +lincat IP = {s : Case => Str; g : Gender; n : Number; p : Person} ; +lincat IComp = {s : Str} ; +lincat IDet = {s : Case => Gender => Str; n : Number} ; +lincat IQuant = {s : Case => Gender => Number => Str} ; +lincat VP = {s : R.Tense => R.Polarity => Gender => Number => Person => Str; inf : Str; imp : R.Polarity => Number => Str} ; +lincat VPSlash = {s : R.Tense => R.Polarity => Gender => Number => Person => Str; inf : Str; imp : R.Polarity => Number => Str; c : Compl; post : Str} ; +lincat Comp = {s : Gender => Number => Str} ; +lincat NP = {s : Case => Str; g : Gender; n : Number; p : Person} ; +lincat Det = {s : Case => Gender => Str; n : Number} ; +lincat Predet = {s : Case => Gender => Number => Str} ; +lincat Quant = {s : Case => Gender => Number => Str} ; +lincat Num = {s : Str; n : Number} ; +lincat Card = {s : Str; n : Number} ; +lincat ACard = {s : Str; n : Number} ; +lincat Ord = A ; +lincat DAP = {s : Case => Gender => Str; n : Number} ; +lincat Imp = {s : R.Polarity => Number => Str} ; +lincat Conj = {s1,s2 : Str; n : Number} ; +lincat Subj = {s : Str} ; +lincat Numeral = {s : Str} ; +lincat Digits = {s : Str} ; +lincat Decimal = {s : Str} ; lincat LN,SN,GN,PN = {s : Str} ; linref V,VV,V2,V3,V2A,V2S,V2Q,V2V = \v -> v.infinitive ; +linref NP = \np -> np.s ! Nom ; +linref CN = \cn -> cn.s ! Nom ! Sg ; } diff --git a/src/ukrainian/ConjunctionUkr.gf b/src/ukrainian/ConjunctionUkr.gf new file mode 100644 index 00000000..d5ff0a46 --- /dev/null +++ b/src/ukrainian/ConjunctionUkr.gf @@ -0,0 +1,82 @@ +concrete ConjunctionUkr of Conjunction = CatUkr ** open ResUkr in { + +lincat + [S] = {s1,s2 : Str} ; + [RS] = {s1,s2 : Gender => Number => Str} ; + [Adv] = {s1,s2 : Str} ; + [AdV] = {s1,s2 : Str} ; + [IAdv] = {s1,s2 : Str} ; + [NP] = {s1,s2 : Case => Str; g : Gender; n : Number; p : Person} ; + [AP] = {s1,s2 : Case => GenNum => Str} ; + [CN] = {s1,s2 : Case => Number => Str; g : Gender} ; + [DAP] = {s1,s2 : Case => Gender => Str; n : Number} ; + +lin + BaseS x y = {s1=x.s; s2=y.s} ; + ConsS x xs = {s1=x.s ++ "," ++ xs.s1; s2=xs.s2} ; + ConjS conj xs = {s = conj.s1 ++ xs.s1 ++ conj.s2 ++ xs.s2} ; + + BaseRS x y = {s1=x.s; s2=y.s} ; + ConsRS x xs = {s1=\\g,n => x.s ! g ! n ++ "," ++ xs.s1 ! g ! n; s2=xs.s2} ; + ConjRS conj xs = {s = \\g,n => conj.s1 ++ xs.s1 ! g ! n ++ conj.s2 ++ xs.s2 ! g ! n} ; + + BaseAdv x y = {s1=x.s; s2=y.s} ; + ConsAdv x xs = {s1=x.s ++ "," ++ xs.s1; s2=xs.s2} ; + ConjAdv conj xs = {s = conj.s1 ++ xs.s1 ++ conj.s2 ++ xs.s2} ; + + BaseAdV x y = {s1=x.s; s2=y.s} ; + ConsAdV x xs = {s1=x.s ++ "," ++ xs.s1; s2=xs.s2} ; + ConjAdV conj xs = {s = conj.s1 ++ xs.s1 ++ conj.s2 ++ xs.s2} ; + + BaseIAdv x y = {s1=x.s; s2=y.s} ; + ConsIAdv x xs = {s1=x.s ++ "," ++ xs.s1; s2=xs.s2} ; + ConjIAdv conj xs = {s = conj.s1 ++ xs.s1 ++ conj.s2 ++ xs.s2} ; + + BaseAP x y = {s1=x.s; s2=y.s} ; + ConsAP x xs = {s1=\\c,gn => x.s ! c ! gn ++ "," ++ xs.s1 ! c ! gn; s2=xs.s2} ; + ConjAP conj xs = { + s = \\c,gn => conj.s1 ++ xs.s1 ! c ! gn ++ conj.s2 ++ xs.s2 ! c ! gn + } ; + + BaseNP x y = {s1=x.s; s2=y.s; g=y.g; n=Pl; p=y.p} ; + ConsNP x xs = { + s1=\\c => x.s ! c ++ "," ++ xs.s1 ! c ; + s2=xs.s2 ; + g=xs.g ; + n=Pl ; + p=xs.p + } ; + ConjNP conj xs = { + s = \\c => conj.s1 ++ xs.s1 ! c ++ conj.s2 ++ xs.s2 ! c ; + g = xs.g ; + n = case conj.n of {Sg => xs.n ; Pl => Pl} ; + p = xs.p + } ; + + BaseCN x y = {s1=x.s; s2=y.s; g=y.g} ; + ConsCN x xs = { + s1=\\c,n => x.s ! c ! n ++ "," ++ xs.s1 ! c ! n ; + s2=xs.s2 ; + g=xs.g + } ; + ConjCN conj xs = { + s = \\c,n => conj.s1 ++ xs.s1 ! c ! n ++ conj.s2 ++ xs.s2 ! c ! n ; + g = xs.g ; + voc = \\n => conj.s1 ++ xs.s1 ! Nom ! n ++ conj.s2 ++ xs.s2 ! Nom ! n + } ; + + BaseDAP x y = { + s1=x.s ; + s2=y.s ; + n=Pl + } ; + ConsDAP x xs = { + s1=\\c,g => x.s ! c ! g ++ "," ++ xs.s1 ! c ! g ; + s2=xs.s2 ; + n=Pl + } ; + ConjDet conj xs = { + s = \\c,g => conj.s1 ++ xs.s1 ! c ! g ++ conj.s2 ++ xs.s2 ! c ! g ; + n = case conj.n of {Sg => xs.n ; Pl => Pl} + } ; +} diff --git a/src/ukrainian/ConstructionUkr.gf b/src/ukrainian/ConstructionUkr.gf new file mode 100644 index 00000000..7304d6c0 --- /dev/null +++ b/src/ukrainian/ConstructionUkr.gf @@ -0,0 +1,102 @@ +concrete ConstructionUkr of Construction = CatUkr ** open ResUkr, (R = ParamX), ParadigmsUkr in { + +lincat + Timeunit, Hour, Weekday, Month, Monthday, Year, Language = {s : Str} ; + +oper + stateVP : Str -> VP = \s -> lin VP { + s = \\t,pol,g,n,p => copula t pol g n p ++ s ; + inf = "бути" ++ s ; + imp = \\pol,n => neg pol ++ "будь" ++ s + } ; + +lin + hungry_VP = stateVP "голодний" ; + thirsty_VP = stateVP "спраглий" ; + tired_VP = stateVP "втомлений" ; + scared_VP = stateVP "наляканий" ; + ill_VP = stateVP "хворий" ; + ready_VP = stateVP "готовий" ; + has_age_VP card = { + s = \\t,pol,g,n,p => copula t pol g n p ++ card.s ++ "років" ; + inf = "мати" ++ card.s ++ "років" ; + imp = \\pol,n => neg pol ++ "май" ++ card.s ++ "років" + } ; + have_name_Cl np name = {s = \\t,pol => np.s ! Gen ++ "ім'я" ++ name.s ! Nom} ; + married_Cl x y = {s = \\t,pol => x.s ! Nom ++ copula t pol x.g x.n x.p ++ "одружений з" ++ y.s ! Instr} ; + what_name_QCl np = {s = \\t,pol => "як звати" ++ np.s ! Acc} ; + how_old_QCl np = {s = \\t,pol => "скільки років" ++ np.s ! Dat} ; + how_far_QCl np = {s = \\t,pol => "як далеко" ++ np.s ! Nom} ; + weather_adjCl ap = {s = \\t,pol => copula t pol Neuter Sg P3 ++ ap.s ! Nom ! GSg Neuter} ; + is_right_VP = stateVP "правий" ; + is_wrong_VP = stateVP "неправий" ; + n_units_AP card cn a = {s=\\c,gn => card.s ++ cn.s ! Gen ! Pl ++ a.s ! c ! gn} ; + n_units_of_NP card cn np = {s=\\c=>card.s ++ cn.s ! Gen ! Pl ++ np.s ! Gen; g=np.g; n=np.n; p=np.p} ; + n_unit_CN card unit cn = cn ** {s=\\c,n=>card.s ++ unit.s ! Gen ! Pl ++ cn.s ! c ! n} ; + bottle_of_CN np = constN ("пляшка" ++ np.s ! Gen) Fem ; + cup_of_CN np = constN ("чашка" ++ np.s ! Gen) Fem ; + glass_of_CN np = constN ("склянка" ++ np.s ! Gen) Fem ; + few_X_short_of_Y np x y = {s = np.s ! Dat ++ "бракує кількох" ++ x.s ! Gen ! Pl ++ "до" ++ y.s ! Gen ! Sg} ; + + timeunitAdv card unit = {s = card.s ++ unit.s} ; + timeunitRange c1 c2 unit = {s = c1.s ++ "-" ++ c2.s ++ unit.s} ; + timeHour h = {s = "о" ++ h.s} ; + timeHourMinute h m = {s = "о" ++ h.s ++ m.s} ; + weekdayPunctualAdv d = {s = "у" ++ d.s} ; + weekdayHabitualAdv d = {s = "щопонеділка" ++ d.s} ; + weekdayLastAdv d = {s = "минулого" ++ d.s} ; + weekdayNextAdv d = {s = "наступного" ++ d.s} ; + monthAdv m = {s = "у" ++ m.s} ; + yearAdv y = {s = "у" ++ y.s} ; + dayMonthAdv d m = {s = d.s ++ m.s} ; + monthYearAdv m y = {s = m.s ++ y.s} ; + dayMonthYearAdv d m y = {s = d.s ++ m.s ++ y.s} ; + intYear i = {s = i.s} ; + intMonthday i = {s = i.s} ; + InLanguage l = {s = "українською" ++ l.s} ; + weekdayN d = constN d.s Masc ; + monthN m = constN m.s Masc ; + weekdayPN d = {s=d.s} ; + monthPN m = {s=m.s} ; + languageNP l = {s=\\_=>l.s; g=Fem; n=Sg; p=P3} ; + languageCN l = constN l.s Fem ; + + oneHour = {s="одна"} ; + twoHour = {s="дві"} ; + threeHour = {s="три"} ; + fourHour = {s="чотири"} ; + fiveHour = {s="п'ять"} ; + sixHour = {s="шість"} ; + sevenHour = {s="сім"} ; + eightHour = {s="вісім"} ; + nineHour = {s="дев'ять"} ; + tenHour = {s="десять"} ; + elevenHour = {s="одинадцять"} ; + twelveHour = {s="дванадцять"} ; + second_Timeunit = {s="секунд"} ; + minute_Timeunit = {s="хвилин"} ; + hour_Timeunit = {s="годин"} ; + day_Timeunit = {s="днів"} ; + week_Timeunit = {s="тижнів"} ; + month_Timeunit = {s="місяців"} ; + year_Timeunit = {s="років"} ; + monday_Weekday = {s="понеділок"} ; + tuesday_Weekday = {s="вівторок"} ; + wednesday_Weekday = {s="середу"} ; + thursday_Weekday = {s="четвер"} ; + friday_Weekday = {s="п'ятницю"} ; + saturday_Weekday = {s="суботу"} ; + sunday_Weekday = {s="неділю"} ; + january_Month = {s="січні"} ; + february_Month = {s="лютому"} ; + march_Month = {s="березні"} ; + april_Month = {s="квітні"} ; + may_Month = {s="травні"} ; + june_Month = {s="червні"} ; + july_Month = {s="липні"} ; + august_Month = {s="серпні"} ; + september_Month = {s="вересні"} ; + october_Month = {s="жовтні"} ; + november_Month = {s="листопаді"} ; + december_Month = {s="грудні"} ; +} diff --git a/src/ukrainian/GrammarUkr.gf b/src/ukrainian/GrammarUkr.gf index a6293ab2..e3ae0882 100644 --- a/src/ukrainian/GrammarUkr.gf +++ b/src/ukrainian/GrammarUkr.gf @@ -2,6 +2,15 @@ concrete GrammarUkr of Grammar = TenseX, PhraseUkr, NounUkr, + VerbUkr, AdjectiveUkr, - StructuralUkr ** { + AdverbUkr, + NumeralUkr, + SentenceUkr, + QuestionUkr, + RelativeUkr, + ConjunctionUkr, + IdiomUkr, + StructuralUkr, + NamesUkr ** { } diff --git a/src/ukrainian/IdiomUkr.gf b/src/ukrainian/IdiomUkr.gf new file mode 100644 index 00000000..1e10e494 --- /dev/null +++ b/src/ukrainian/IdiomUkr.gf @@ -0,0 +1,46 @@ +concrete IdiomUkr of Idiom = CatUkr ** open ResUkr, (R = ParamX) in { + +lin + ImpersCl vp = { + s = \\t,pol => vp.s ! t ! pol ! Neuter ! Sg ! P3 + } ; + GenericCl vp = { + s = \\t,pol => "люди" ++ vp.s ! t ! pol ! Masc ! Pl ! P3 + } ; + CleftNP np rs = { + s = \\t,pol => "це" ++ np.s ! Nom ++ rs.s ! np.g ! np.n + } ; + CleftAdv adv s = { + s = \\t,pol => "це" ++ adv.s ++ s.s + } ; + ExistNP np = { + s = \\t,pol => case pol of { + R.Pos => "є" ++ np.s ! Nom ; + R.Neg => "немає" ++ np.s ! Gen + } + } ; + ExistIP ip = { + s = \\t,pol => "що є" ++ ip.s ! Nom + } ; + ExistNPAdv np adv = { + s = \\t,pol => case pol of { + R.Pos => adv.s ++ "є" ++ np.s ! Nom ; + R.Neg => adv.s ++ "немає" ++ np.s ! Gen + } + } ; + ExistIPAdv ip adv = { + s = \\t,pol => adv.s ++ "що є" ++ ip.s ! Nom + } ; + ProgrVP vp = vp ; + ImpPl1 vp = {s = "давайте" ++ vp.inf} ; + ImpP3 np vp = {s = "нехай" ++ np.s ! Nom ++ vp.s ! R.Pres ! R.Pos ! np.g ! np.n ! np.p} ; + SelfAdvVP vp = vp ** { + s = \\t,pol,g,n,p => vp.s ! t ! pol ! g ! n ! p ++ "сам" + } ; + SelfAdVVP vp = vp ** { + s = \\t,pol,g,n,p => "сам" ++ vp.s ! t ! pol ! g ! n ! p + } ; + SelfNP np = np ** { + s = \\c => np.s ! c ++ "сам" + } ; +} diff --git a/src/ukrainian/LangUkr.gf b/src/ukrainian/LangUkr.gf index 14d8e1ee..3aa94255 100644 --- a/src/ukrainian/LangUkr.gf +++ b/src/ukrainian/LangUkr.gf @@ -2,9 +2,10 @@ concrete LangUkr of Lang = GrammarUkr, LexiconUkr + ,ConstructionUkr ,DocumentationUkr --# notpresent ** { flags startcat = Phr ; -} \ No newline at end of file +} diff --git a/src/ukrainian/MorphoUkr.gf b/src/ukrainian/MorphoUkr.gf index 8ad74e17..d6660bfe 100644 --- a/src/ukrainian/MorphoUkr.gf +++ b/src/ukrainian/MorphoUkr.gf @@ -22072,32 +22072,32 @@ mkV068 base = Imperf => { past = nonExist ; pres = table { P1 => table { - Sg => base_1+base_2+"яти" ; - Pl => nonExist + Sg => base_1+"і"+base_2+"ьму" ; + Pl => base_1+"і"+base_2+"ьмемо" } ; P2 => table { - Sg => nonExist ; - Pl => nonExist + Sg => base_1+"і"+base_2+"ьмеш" ; + Pl => base_1+"і"+base_2+"ьмете" } ; P3 => table { - Sg => nonExist ; - Pl => nonExist + Sg => base_1+"і"+base_2+"ьме" ; + Pl => base_1+"і"+base_2+"ьмуть" } } } ; Perf => { past = nonExist ; pres = table { P1 => table { - Sg => base_1+base_2+"яти" ; - Pl => nonExist + Sg => base_1+"і"+base_2+"ьму" ; + Pl => base_1+"і"+base_2+"ьмемо" } ; P2 => table { - Sg => nonExist ; - Pl => nonExist + Sg => base_1+"і"+base_2+"ьмеш" ; + Pl => base_1+"і"+base_2+"ьмете" } ; P3 => table { - Sg => nonExist ; - Pl => nonExist + Sg => base_1+"і"+base_2+"ьме" ; + Pl => base_1+"і"+base_2+"ьмуть" } } } @@ -26249,15 +26249,15 @@ mkV126 base = pres = table { P1 => table { Sg => base_1+"няти" ; - Pl => nonExist + Pl => base_1+"мемо" } ; P2 => table { - Sg => nonExist ; - Pl => nonExist + Sg => base_1+"меш" ; + Pl => base_1+"мете" } ; P3 => table { - Sg => nonExist ; - Pl => nonExist + Sg => base_1+"ме" ; + Pl => base_1+"муть" } } } ; @@ -26265,15 +26265,15 @@ mkV126 base = pres = table { P1 => table { Sg => base_1+"няти" ; - Pl => nonExist + Pl => base_1+"мемо" } ; P2 => table { - Sg => nonExist ; - Pl => nonExist + Sg => base_1+"меш" ; + Pl => base_1+"мете" } ; P3 => table { - Sg => nonExist ; - Pl => nonExist + Sg => base_1+"ме" ; + Pl => base_1+"муть" } } } diff --git a/src/ukrainian/NamesUkr.gf b/src/ukrainian/NamesUkr.gf new file mode 100644 index 00000000..1a14be1f --- /dev/null +++ b/src/ukrainian/NamesUkr.gf @@ -0,0 +1,14 @@ +concrete NamesUkr of Names = CatUkr ** open ResUkr in { + +lin + GivenName gn = {s = \\_ => gn.s ; g = Masc ; n = Sg ; p = P3} ; + MaleSurname sn = {s = \\_ => sn.s ; g = Masc ; n = Sg ; p = P3} ; + FemaleSurname sn = {s = \\_ => sn.s ; g = Fem ; n = Sg ; p = P3} ; + PlSurname sn = {s = \\_ => sn.s ; g = Masc ; n = Pl ; p = P3} ; + FullName gn sn = {s = \\_ => gn.s ++ sn.s ; g = Masc ; n = Sg ; p = P3} ; + + UseLN ln = {s = \\_ => ln.s ; g = Fem ; n = Sg ; p = P3} ; + PlainLN ln = UseLN ln ; + InLN ln = {s = "у" ++ ln.s} ; + AdjLN ap ln = {s = ap.s ! Nom ! (GSg Fem) ++ ln.s} ; +} diff --git a/src/ukrainian/NounUkr.gf b/src/ukrainian/NounUkr.gf index 370f1a1d..7ea655c2 100644 --- a/src/ukrainian/NounUkr.gf +++ b/src/ukrainian/NounUkr.gf @@ -1,4 +1,110 @@ -concrete NounUkr of Noun = CatUkr ** { +concrete NounUkr of Noun = CatUkr ** open ResUkr, Prelude in { lin UseN n = n ; + + DetCN det cn = { + s = \\c => det.s ! c ! cn.g ++ cn.s ! Nom ! Sg ; + g = cn.g ; + n = det.n ; + p = P3 + } ; + UsePN pn = {s = \\_ => pn.s ; g = Masc ; n = Sg ; p = P3} ; + UsePron p = p ; + + PredetNP pred np = np ** { + s = \\c => pred.s ! c ! np.g ! np.n ++ np.s ! c + } ; + AdvNP np adv = np ** {s = \\c => np.s ! c ++ adv.s} ; + ExtAdvNP np adv = np ** {s = \\c => np.s ! c ++ "," ++ adv.s} ; + DetNP det = { + s = \\c => det.s ! c ! Masc ; + g = Masc ; + n = det.n ; + p = P3 + } ; + + DetQuant q num = { + s = \\c,g => q.s ! c ! g ! num.n ++ num.s ; + n = num.n + } ; + DetQuantOrd q num ord = { + s = \\c,g => q.s ! c ! g ! num.n ++ num.s ++ ord.s ! c ! genNum g num.n ; + n = num.n + } ; + NumSg = {s = [] ; n = Sg} ; + NumPl = {s = [] ; n = Pl} ; + NumCard card = card ; + NumDigits digits = {s = digits.s ; n = Pl} ; + NumDecimal dec = {s = dec.s ; n = Pl} ; + NumNumeral numeral = {s = numeral.s ; n = Pl} ; + AdNum adn card = card ** {s = adn.s ++ card.s} ; + OrdDigits digits = {s=\\_,_ => digits.s} ; + OrdNumeral numeral = {s=\\_,_ => numeral.s} ; + OrdSuperl a = {s=\\c,gn => "най" ++ a.s ! c ! gn} ; + OrdNumeralSuperl numeral a = {s=\\c,gn => numeral.s ++ "най" ++ a.s ! c ! gn} ; + + IndefArt = {s = \\_,_,_ => []} ; + DefArt = {s = \\_,_,_ => []} ; + MassNP cn = { + s = \\_ => cn.s ! Nom ! Sg ; + g = cn.g ; + n = Sg ; + p = P3 + } ; + PossPron p = { + s = \\_,g,n => possPron p.p p.g p.n g n + } ; + + ComplN2 n2 np = n2 ** { + s = \\c,num => n2.s ! c ! num ++ prepNP n2.c2 np + } ; + ComplN3 n3 np = n3 ** { + c2 = n3.c2 ; + s = \\c,num => n3.s ! c ! num ++ prepNP n3.c3 np + } ; + UseN2 n2 = n2 ; + Use2N3 n3 = n3 ** {c2 = n3.c2} ; + Use3N3 n3 = n3 ** {c2 = n3.c3} ; + + AdjCN ap cn = cn ** { + s = \\c,num => ap.s ! c ! genNum cn.g num ++ cn.s ! c ! num + } ; + RelCN cn rs = cn ** { + s = \\c,n => cn.s ! c ! n ++ rs.s ! cn.g ! n + } ; + AdvCN cn adv = cn ** { + s = \\c,n => cn.s ! c ! n ++ adv.s + } ; + SentCN cn sc = cn ** { + s = \\c,n => cn.s ! c ! n ++ sc.s + } ; + ApposCN cn np = cn ** { + s = \\c,n => cn.s ! c ! n ++ np.s ! Nom + } ; + PossNP cn np = cn ** { + s = \\c,n => cn.s ! c ! n ++ np.s ! Gen + } ; + PartNP cn np = cn ** { + s = \\c,n => cn.s ! c ! n ++ np.s ! Gen + } ; + CountNP det np = { + s = \\c => det.s ! c ! np.g ++ "з" ++ np.s ! Gen ; + g = np.g ; + n = det.n ; + p = P3 + } ; + QuantityNP decimal mu = { + s = \\_ => case mu.isPre of { + True => mu.s ++ decimal.s ; + False => decimal.s ++ mu.s + } ; + g = Masc ; + n = Pl ; + p = P3 + } ; + + AdjDAP dap ap = dap ** { + s = \\c,g => dap.s ! c ! g ++ ap.s ! c ! genNum g dap.n + } ; + DetDAP det = det ; } diff --git a/src/ukrainian/NumeralUkr.gf b/src/ukrainian/NumeralUkr.gf new file mode 100644 index 00000000..2e9d4fb4 --- /dev/null +++ b/src/ukrainian/NumeralUkr.gf @@ -0,0 +1,66 @@ +concrete NumeralUkr of Numeral = CatUkr [Numeral,Digits,Decimal] ** open Prelude,ParamX,ResUkr in { + flags + coding = "UTF-8" ; + +lincat + Digit = {s,teen,ten,hundred : Str} ; + Sub10 = {s,hundred : Str} ; + Sub100, Sub1000, Sub1000000, Sub1000000000, Sub1000000000000 = {s : Str} ; + Dig = {s : Str} ; + +lin + num n = n ; + + n2 = {s = "два"; teen = "дванадцять"; ten = "двадцять"; hundred = "двісті"} ; + n3 = {s = "три"; teen = "тринадцять"; ten = "тридцять"; hundred = "триста"} ; + n4 = {s = "чотири"; teen = "чотирнадцять"; ten = "сорок"; hundred = "чотириста"} ; + n5 = {s = "п'ять"; teen = "п'ятнадцять"; ten = "п'ятдесят"; hundred = "п'ятсот"} ; + n6 = {s = "шість"; teen = "шістнадцять"; ten = "шістдесят"; hundred = "шістсот"} ; + n7 = {s = "сім"; teen = "сімнадцять"; ten = "сімдесят"; hundred = "сімсот"} ; + n8 = {s = "вісім"; teen = "вісімнадцять"; ten = "вісімдесят"; hundred = "вісімсот"} ; + n9 = {s = "дев'ять"; teen = "дев'ятнадцять"; ten = "дев'яносто"; hundred = "дев'ятсот"} ; + + pot01 = {s = "один"; hundred = "сто"} ; + pot0 d = {s = d.s; hundred = d.hundred} ; + pot0as1 n = n ; + pot110 = {s = "десять"} ; + pot111 = {s = "одинадцять"} ; + pot1to19 d = {s = d.teen} ; + pot1 d = {s = d.ten} ; + pot1plus d n = {s = (pot1 d).s ++ n.s} ; + pot1as2 n = n ; + pot21 = {s = "сто"} ; + pot2 n = {s = n.hundred} ; + pot2plus n m = {s = (pot2 n).s ++ m.s} ; + pot2as3 n = n ; + pot31 = {s = "тисяча"} ; + pot3 n = {s = n.s ++ "тисяч"} ; + pot3plus n m = {s = (pot3 n).s ++ m.s} ; + pot3as4 n = n ; + pot3decimal d = {s = d.s ++ "тисяч"} ; + pot41 = {s = "мільйон"} ; + pot4 n = {s = n.s ++ "мільйонів"} ; + pot4plus n m = {s = (pot4 n).s ++ m.s} ; + pot4as5 n = n ; + pot4decimal d = {s = d.s ++ "мільйонів"} ; + pot51 = {s = "мільярд"} ; + pot5 n = {s = n.s ++ "мільярдів"} ; + pot5plus n m = {s = (pot5 n).s ++ m.s} ; + pot5decimal d = {s = d.s ++ "мільярдів"} ; + + D_0 = {s = "0"} ; + D_1 = {s = "1"} ; + D_2 = {s = "2"} ; + D_3 = {s = "3"} ; + D_4 = {s = "4"} ; + D_5 = {s = "5"} ; + D_6 = {s = "6"} ; + D_7 = {s = "7"} ; + D_8 = {s = "8"} ; + D_9 = {s = "9"} ; + IDig d = d ; + IIDig d ds = {s = d.s ++ BIND ++ ds.s} ; + PosDecimal ds = ds ; + NegDecimal ds = {s = "-" ++ BIND ++ ds.s} ; + IFrac d dig = {s = d.s ++ "." ++ BIND ++ dig.s} ; +} diff --git a/src/ukrainian/ParadigmsUkr.gf b/src/ukrainian/ParadigmsUkr.gf index 2aa7ee93..a45322f8 100644 --- a/src/ukrainian/ParadigmsUkr.gf +++ b/src/ukrainian/ParadigmsUkr.gf @@ -1352,6 +1352,25 @@ oper mkA2 : A -> Prep -> A2 = \a,p -> lin A2 (a ** {c2 = p}) ; } ; + invarN : Str -> N = \s -> lin N {s=\\_,_=>s; voc=\\_=>s; g=Masc} ; + invarA : Str -> A = \s -> lin A {s=\\_,_=>s} ; + invarV : Str -> V = \s -> lin V { + active = table { + Imperf => {past=s; pres=\\_,_=>s} ; + Perf => {past=s; pres=\\_,_=>s} + } ; + imperative1 = s ; + imperative2 = \\_=>s ; + infinitive = s ; + participle = \\_,_=>s ; + passive = \\_,_=>s + } ; + invarVP : Str -> VP = \s -> lin VP { + s = \\_,_,_,_,_=>s ; + inf = s ; + imp = \\_,_=>s + } ; + mkAdv : Str -> Adv = \s -> lin Adv {s=s} ; mkAdV : Str -> AdV = \s -> lin AdV {s=s} ; mkAdA : Str -> AdA = \s -> lin AdA {s=s} ; @@ -1360,18 +1379,30 @@ oper mkInterj : Str -> Interj = \s -> lin Interj {s=s} ; mkMU : Str -> MU = \s -> lin MU {s=s; isPre=False} ; - mkPrep : Str -> Prep = \s -> lin Prep {s=s; c=Acc} ; + nominative : Case = Nom ; + accusative : Case = Acc ; + dative : Case = Dat ; + genitive : Case = Gen ; + locative : Case = Loc ; + instrumental : Case = Instr ; + + mkPrep = overload { + mkPrep : Str -> Prep = \s -> lin Prep {s=s; c=Acc} ; + mkPrep : Case -> Prep = \c -> lin Prep {s=[]; c=c} ; + mkPrep : Str -> Case -> Prep = \s,c -> lin Prep {s=s; c=c} + } ; mkIAdv : Str -> IAdv = \s -> lin IAdv {s=s} ; - mkIP : Str -> IP = \s -> lin IP {s=s} ; - mkIQuant : Str -> IQuant = \s -> lin IQuant {s=s} ; - mkIDet : Str -> IDet = \s -> lin IDet {s=s} ; + mkIP : Str -> IP = \s -> lin IP {s=\\_=>s; g=Masc; n=Sg; p=P3} ; + mkIQuant : Str -> IQuant = \s -> lin IQuant {s=\\_,_,_=>s} ; + mkIDet : Str -> IDet = \s -> lin IDet {s=\\_,_=>s; n=Sg} ; mkSubj : Str -> Subj = \s -> lin Subj {s=s} ; - mkQuant : Str -> Quant = \s -> lin Quant {s=s} ; - mkPredet : Str -> Predet = \s -> lin Predet {s=s} ; - mkDet : Str -> Det = \s -> lin Det {s=s} ; - mkCard : Str -> Card = \s -> lin Card {s=s} ; - mkConj : Str -> Conj = \s -> lin Conj {s=s} ; + mkQuant : Str -> Quant = \s -> lin Quant {s=\\_,_,_=>s} ; + mkPredet : Str -> Predet = \s -> lin Predet {s=\\_,_,_=>s} ; + mkDet : Str -> Det = \s -> lin Det {s=\\_,_=>s; n=Sg} ; + mkCard : Str -> Card = \s -> lin Card {s=s; n=Pl} ; + mkACard : Str -> ACard = \s -> lin ACard {s=s; n=Pl} ; + mkConj : Str -> Conj = \s -> lin Conj {s1=""; s2=s; n=Pl} ; mkPConj : Str -> PConj = \s -> lin PConj {s=s} ; mkVoc : Str -> Voc = \s -> lin Voc {s=s} ; diff --git a/src/ukrainian/PhraseUkr.gf b/src/ukrainian/PhraseUkr.gf index 9b2a8bb9..7cb5a969 100644 --- a/src/ukrainian/PhraseUkr.gf +++ b/src/ukrainian/PhraseUkr.gf @@ -1,11 +1,25 @@ -concrete PhraseUkr of Phrase = CatUkr ** { +concrete PhraseUkr of Phrase = CatUkr ** open ResUkr, (R = ParamX) in { lin PhrUtt pconj utt voc = {s = pconj.s ++ utt.s ++ voc.s} ; UttS s = s ; + UttQS qs = qs ; + UttImpSg pol imp = {s = imp.s ! pol.p ! Sg} ; + UttImpPl pol imp = {s = imp.s ! pol.p ! Pl} ; + UttImpPol pol imp = {s = imp.s ! pol.p ! Pl} ; + UttIP ip = {s = ip.s ! Nom} ; + UttIAdv iadv = iadv ; + UttNP np = {s = np.s ! Nom} ; + UttAdv adv = adv ; + UttVP vp = {s = vp.inf} ; + UttCN cn = {s = cn.s ! Nom ! Sg} ; + UttCard card = {s = card.s} ; + UttAP ap = {s = ap.s ! Nom ! GSg Masc} ; UttInterj i = i ; NoPConj = {s = []} ; + PConjConj conj = {s = conj.s2} ; NoVoc = {s = []} ; + VocNP np = {s = np.s ! Nom} ; } diff --git a/src/ukrainian/QuestionUkr.gf b/src/ukrainian/QuestionUkr.gf new file mode 100644 index 00000000..13715e94 --- /dev/null +++ b/src/ukrainian/QuestionUkr.gf @@ -0,0 +1,54 @@ +concrete QuestionUkr of Question = CatUkr ** open ResUkr, (R = ParamX) in { + +lincat QVP = {s : R.Tense => R.Polarity => Gender => Number => Person => Str} ; + +lin + QuestCl cl = cl ; + QuestVP ip vp = { + s = \\t,pol => ip.s ! Nom ++ vp.s ! t ! pol ! ip.g ! ip.n ! ip.p + } ; + QuestSlash ip cls = { + s = \\t,pol => ip.s ! cls.c.c ++ cls.s ! t ! pol + } ; + QuestIAdv iadv cl = { + s = \\t,pol => iadv.s ++ cl.s ! t ! pol + } ; + QuestIComp icomp np = { + s = \\t,pol => icomp.s ++ np.s ! Nom + } ; + + IdetCN idet cn = { + s = \\c => idet.s ! c ! cn.g ++ cn.s ! c ! idet.n ; + g = cn.g ; + n = idet.n ; + p = P3 + } ; + IdetIP idet = { + s = \\c => idet.s ! c ! Masc ; + g = Masc ; + n = idet.n ; + p = P3 + } ; + AdvIP ip adv = ip ** {s = \\c => ip.s ! c ++ adv.s} ; + IdetQuant iquant num = { + s = \\c,g => iquant.s ! c ! g ! num.n ++ num.s ; + n = num.n + } ; + PrepIP prep ip = {s = prepNP prep ip} ; + AdvIAdv iadv adv = {s = iadv.s ++ adv.s} ; + CompIAdv iadv = iadv ; + CompIP ip = {s = ip.s ! Nom} ; + + ComplSlashIP slash ip = { + s = \\t,pol,g,n,p => slash.s ! t ! pol ! g ! n ! p ++ ip.s ! slash.c.c ++ slash.post + } ; + AdvQVP vp iadv = { + s = \\t,pol,g,n,p => vp.s ! t ! pol ! g ! n ! p ++ iadv.s + } ; + AddAdvQVP qvp iadv = { + s = \\t,pol,g,n,p => qvp.s ! t ! pol ! g ! n ! p ++ iadv.s + } ; + QuestQVP ip qvp = { + s = \\t,pol => ip.s ! Nom ++ qvp.s ! t ! pol ! ip.g ! ip.n ! ip.p + } ; +} diff --git a/src/ukrainian/RelativeUkr.gf b/src/ukrainian/RelativeUkr.gf new file mode 100644 index 00000000..48939f47 --- /dev/null +++ b/src/ukrainian/RelativeUkr.gf @@ -0,0 +1,46 @@ +concrete RelativeUkr of Relative = CatUkr ** open ResUkr, (R = ParamX) in { + +oper + relPron : Gender -> Number -> Case -> Str = + \g,n,c -> case of { + => "які" ; + => "яких" ; + => "яким" ; + => "яких" ; + => "яких" ; + => "якими" ; + => "який" ; + => "якого" ; + => "якому" ; + => "якого" ; + => "якому" ; + => "яким" ; + => "яка" ; + => "яку" ; + => "якій" ; + => "якої" ; + => "якій" ; + => "якою" ; + => "яке" ; + => "яке" ; + => "якому" ; + => "якого" ; + => "якому" ; + => "яким" + } ; + +lin + RelCl cl = { + s = \\_,_ => "що" ++ cl.s ! R.Pres ! R.Pos + } ; + RelVP rp vp = { + s = \\g,n => rp.s ! g ! n ! Nom ++ vp.s ! R.Pres ! R.Pos ! g ! n ! P3 + } ; + RelSlash rp cls = { + s = \\g,n => rp.s ! g ! n ! cls.c.c ++ cls.s ! R.Pres ! R.Pos + } ; + IdRP = {s = \\g,n,c => relPron g n c} ; + FunRP prep np rp = { + s = \\g,n,c => prepNP prep np ++ rp.s ! g ! n ! c + } ; +} diff --git a/src/ukrainian/ResUkr.gf b/src/ukrainian/ResUkr.gf index ba379a55..a0635caa 100644 --- a/src/ukrainian/ResUkr.gf +++ b/src/ukrainian/ResUkr.gf @@ -1,4 +1,4 @@ -resource ResUkr = { +resource ResUkr = open (R = ParamX), Prelude in { param Case = Nom | Acc | Dat | Gen | Loc | Instr ; param Number = Sg | Pl ; @@ -164,9 +164,84 @@ oper mkA : (_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ : Str) -> A = oper Compl = {s : Str; c : Case} ; -oper noPrep : Compl = {s=""; c=Acc} ; +oper noPrep : Compl = {s=""; c=Nom} ; oper CommonNoun = N ; oper AdjPhrase = A ; +oper Agr = {g : Gender; n : Number; p : Person} ; +oper agrP3 : Gender -> Number -> Agr = \g,n -> {g=g; n=n; p=P3} ; +oper defaultAgr : Agr = agrP3 Masc Sg ; + +oper neg : R.Polarity -> Str = \p -> case p of { + R.Pos => [] ; + R.Neg => "не" + } ; + +oper auxBe : R.Tense -> Number -> Person -> Str = + \t,n,p -> case t of { + R.Pres => [] ; + R.Past => case n of { + Sg => "був" ; + Pl => "були" + } ; + R.Fut => case of { + => "буду" ; + => "будеш" ; + => "буде" ; + => "будемо" ; + => "будете" ; + => "будуть" + } ; + R.Cond => case n of { + Sg => "був би" ; + Pl => "були б" + } + } ; + +oper finiteVerb : V -> R.Tense -> R.Polarity -> Gender -> Number -> Person -> Str = + \v,t,pol,g,n,p -> neg pol ++ case t of { + R.Pres => (v.active ! Imperf).pres ! p ! n ; + R.Past => (v.active ! Imperf).pres ! p ! n ; + R.Fut => auxBe R.Fut n p ++ v.infinitive ; + R.Cond => (v.active ! Imperf).pres ! p ! n ++ "би" + } ; + +oper copula : R.Tense -> R.Polarity -> Gender -> Number -> Person -> Str = + \t,pol,g,n,p -> neg pol ++ auxBe t n p ; + +oper prepNP : Compl -> {s : Case => Str} -> Str = + \prep,np -> prep.s ++ np.s ! prep.c ; + +oper constN : Str -> Gender -> N = + \s,g -> { + s = \\_,_ => s ; + voc = \\_ => s ; + g = g + } ; + +oper possPron : Person -> Gender -> Number -> Gender -> Number -> Str = + \p,pg,pn,g,n -> case of { + => "мій" ; + => "моя" ; + => "моє" ; + => "мої" ; + => "наш" ; + => "наша" ; + => "наше" ; + => "наші" ; + => "твій" ; + => "твоя" ; + => "твоє" ; + => "твої" ; + => "ваш" ; + => "ваша" ; + => "ваше" ; + => "ваші" ; + => "його" ; + => "її" ; + => "їхній" ; + _ => "свій" + } ; + } diff --git a/src/ukrainian/SentenceUkr.gf b/src/ukrainian/SentenceUkr.gf new file mode 100644 index 00000000..7bb4d353 --- /dev/null +++ b/src/ukrainian/SentenceUkr.gf @@ -0,0 +1,54 @@ +concrete SentenceUkr of Sentence = CatUkr ** open ResUkr, (R = ParamX) in { + +lin + PredVP np vp = { + s = \\t,pol => np.s ! Nom ++ vp.s ! t ! pol ! np.g ! np.n ! np.p + } ; + PredSCVP sc vp = { + s = \\t,pol => sc.s ++ vp.s ! t ! pol ! Masc ! Sg ! P3 + } ; + + SlashVP np slash = { + s = \\t,pol => np.s ! Nom ++ slash.s ! t ! pol ! np.g ! np.n ! np.p ++ slash.post ; + c = slash.c + } ; + AdvSlash cls adv = cls ** { + s = \\t,pol => cls.s ! t ! pol ++ adv.s + } ; + SlashPrep cl prep = { + s = cl.s ; + c = prep + } ; + SlashVS np vs sslash = { + s = \\t,pol => np.s ! Nom ++ finiteVerb vs t pol np.g np.n np.p ++ sslash.s ; + c = sslash.c + } ; + + ImpVP vp = {s = vp.imp} ; + AdvImp adv imp = { + s = \\pol,n => adv.s ++ imp.s ! pol ! n + } ; + + EmbedS s = {s = "що" ++ s.s} ; + EmbedQS qs = {s = qs.s} ; + EmbedVP vp = {s = vp.inf} ; + + UseCl temp pol cl = { + s = temp.s ++ pol.s ++ cl.s ! temp.t ! pol.p + } ; + UseQCl temp pol qcl = { + s = temp.s ++ pol.s ++ qcl.s ! temp.t ! pol.p + } ; + UseRCl temp pol rcl = { + s = \\g,n => temp.s ++ pol.s ++ rcl.s ! g ! n + } ; + UseSlash temp pol cls = { + s = temp.s ++ pol.s ++ cls.s ! temp.t ! pol.p ; + c = cls.c + } ; + + AdvS adv s = {s = adv.s ++ s.s} ; + ExtAdvS adv s = {s = adv.s ++ "," ++ s.s} ; + SSubjS s1 subj s2 = {s = s1.s ++ subj.s ++ s2.s} ; + RelS s rs = {s = s.s ++ "," ++ rs.s ! Masc ! Sg} ; +} diff --git a/src/ukrainian/VerbUkr.gf b/src/ukrainian/VerbUkr.gf new file mode 100644 index 00000000..f177ed5a --- /dev/null +++ b/src/ukrainian/VerbUkr.gf @@ -0,0 +1,131 @@ +concrete VerbUkr of Verb = CatUkr ** open ResUkr, (R = ParamX) in { + +oper + mkVP : V -> VP = \v -> lin VP { + s = \\t,pol,g,n,p => finiteVerb v t pol g n p ; + inf = v.infinitive ; + imp = \\pol,n => neg pol ++ v.imperative2 ! n + } ; + + mkSlash : V -> Compl -> VPSlash = \v,c -> lin VPSlash { + s = \\t,pol,g,n,p => finiteVerb v t pol g n p ; + inf = v.infinitive ; + imp = \\pol,n => neg pol ++ v.imperative2 ! n ; + c = c ; + post = [] + } ; + +lin + UseV v = mkVP v ; + + ComplVV vv vp = { + s = \\t,pol,g,n,p => finiteVerb vv t pol g n p ++ vp.inf ; + inf = vv.infinitive ++ vp.inf ; + imp = \\pol,n => neg pol ++ vv.imperative2 ! n ++ vp.inf + } ; + ComplVS vs s = { + s = \\t,pol,g,n,p => finiteVerb vs t pol g n p ++ s.s ; + inf = vs.infinitive ++ s.s ; + imp = \\pol,n => neg pol ++ vs.imperative2 ! n ++ s.s + } ; + ComplVQ vq qs = { + s = \\t,pol,g,n,p => finiteVerb vq t pol g n p ++ qs.s ; + inf = vq.infinitive ++ qs.s ; + imp = \\pol,n => neg pol ++ vq.imperative2 ! n ++ qs.s + } ; + ComplVA va ap = { + s = \\t,pol,g,n,p => finiteVerb va t pol g n p ++ ap.s ! Nom ! genNum g n ; + inf = va.infinitive ++ ap.s ! Nom ! GSg Masc ; + imp = \\pol,n => neg pol ++ va.imperative2 ! n ++ ap.s ! Nom ! genNum Masc n + } ; + + SlashV2a v = mkSlash v v.c2 ; + Slash2V3 v np = (mkSlash v v.c3) ** { + s = \\t,pol,g,n,p => finiteVerb v t pol g n p ++ prepNP v.c2 np ; + inf = v.infinitive ++ prepNP v.c2 np ; + imp = \\pol,n => neg pol ++ v.imperative2 ! n ++ prepNP v.c2 np + } ; + Slash3V3 v np = (mkSlash v v.c2) ** { + s = \\t,pol,g,n,p => finiteVerb v t pol g n p ++ prepNP v.c3 np ; + inf = v.infinitive ++ prepNP v.c3 np ; + imp = \\pol,n => neg pol ++ v.imperative2 ! n ++ prepNP v.c3 np + } ; + SlashV2V v vp = (mkSlash v v.c2) ** { + post = vp.inf + } ; + SlashV2S v s = (mkSlash v v.c2) ** { + post = s.s + } ; + SlashV2Q v qs = (mkSlash v v.c2) ** { + post = qs.s + } ; + SlashV2A v ap = (mkSlash v v.c2) ** { + post = ap.s ! Nom ! GSg Masc + } ; + + ComplSlash slash np = { + s = \\t,pol,g,n,p => slash.s ! t ! pol ! g ! n ! p ++ prepNP slash.c np ++ slash.post ; + inf = slash.inf ++ prepNP slash.c np ++ slash.post ; + imp = \\pol,n => slash.imp ! pol ! n ++ prepNP slash.c np ++ slash.post + } ; + SlashVV vv slash = slash ** { + s = \\t,pol,g,n,p => finiteVerb vv t pol g n p ++ slash.inf ; + inf = vv.infinitive ++ slash.inf ; + imp = \\pol,n => neg pol ++ vv.imperative2 ! n ++ slash.inf + } ; + SlashV2VNP v np slash = slash ** { + s = \\t,pol,g,n,p => finiteVerb v t pol g n p ++ prepNP v.c2 np ++ slash.inf ; + inf = v.infinitive ++ prepNP v.c2 np ++ slash.inf ; + imp = \\pol,n => neg pol ++ v.imperative2 ! n ++ prepNP v.c2 np ++ slash.inf + } ; + + ReflVP slash = { + s = \\t,pol,g,n,p => slash.s ! t ! pol ! g ! n ! p ++ "себе" ++ slash.post ; + inf = slash.inf ++ "себе" ++ slash.post ; + imp = \\pol,n => slash.imp ! pol ! n ++ "себе" ++ slash.post + } ; + UseComp comp = { + s = \\t,pol,g,n,p => copula t pol g n p ++ comp.s ! g ! n ; + inf = "бути" ++ comp.s ! Masc ! Sg ; + imp = \\pol,n => neg pol ++ "будь" ++ comp.s ! Masc ! n + } ; + + AdvVP vp adv = vp ** { + s = \\t,pol,g,n,p => vp.s ! t ! pol ! g ! n ! p ++ adv.s ; + inf = vp.inf ++ adv.s ; + imp = \\pol,n => vp.imp ! pol ! n ++ adv.s + } ; + ExtAdvVP vp adv = AdvVP vp adv ; + AdVVP adv vp = vp ** { + s = \\t,pol,g,n,p => adv.s ++ vp.s ! t ! pol ! g ! n ! p ; + inf = adv.s ++ vp.inf ; + imp = \\pol,n => adv.s ++ vp.imp ! pol ! n + } ; + AdvVPSlash slash adv = slash ** { + s = \\t,pol,g,n,p => slash.s ! t ! pol ! g ! n ! p ++ adv.s ; + inf = slash.inf ++ adv.s ; + imp = \\pol,n => slash.imp ! pol ! n ++ adv.s + } ; + AdVVPSlash adv slash = slash ** { + s = \\t,pol,g,n,p => adv.s ++ slash.s ! t ! pol ! g ! n ! p ; + inf = adv.s ++ slash.inf ; + imp = \\pol,n => adv.s ++ slash.imp ! pol ! n + } ; + VPSlashPrep vp prep = { + s = vp.s ; + inf = vp.inf ; + imp = vp.imp ; + c = prep ; + post = [] + } ; + + CompAP ap = {s = \\g,n => ap.s ! Nom ! genNum g n} ; + CompNP np = {s = \\_,_ => np.s ! Nom} ; + CompAdv adv = {s = \\_,_ => adv.s} ; + CompCN cn = {s = \\_,n => cn.s ! Nom ! n} ; + UseCopula = { + s = \\t,pol,g,n,p => copula t pol g n p ; + inf = "бути" ; + imp = \\pol,n => neg pol ++ "будь" + } ; +}