From 7de7d780b26a247c315ba77c32eaa017b15ccdba Mon Sep 17 00:00:00 2001 From: Krasimir Angelov Date: Fri, 2 Oct 2026 13:28:10 +0200 Subject: [PATCH] extensions by Codex --- src/api/TryPol.gf | 2 +- src/polish/AdjectiveMorphoPol.gf | 62 +++++++++++--- src/polish/AdjectivePol.gf | 7 +- src/polish/AdverbPol.gf | 4 + src/polish/ConjunctionPol.gf | 25 ++++++ src/polish/ConstructionPol.gf | 113 +++++++++++++++++++++++++ src/polish/ExtendPol.gf | 140 ++++++++++++++++++++++++++++++- src/polish/IdiomPol.gf | 11 ++- src/polish/LangPol.gf | 1 + src/polish/NamesPol.gf | 12 ++- src/polish/NounPol.gf | 40 +++++++++ src/polish/NumeralPol.gf | 91 ++++++++++++++++++++ src/polish/ParadigmsPol.gf | 46 ++++++++++ src/polish/QuestionPol.gf | 3 +- src/polish/ResPol.gf | 4 +- src/polish/SentencePol.gf | 4 + src/polish/VerbMorphoPol.gf | 60 +++++++++++-- src/polish/VerbPol.gf | 31 +++++-- 18 files changed, 621 insertions(+), 35 deletions(-) create mode 100644 src/polish/ConstructionPol.gf diff --git a/src/api/TryPol.gf b/src/api/TryPol.gf index f448f65b..33c5602f 100644 --- a/src/api/TryPol.gf +++ b/src/api/TryPol.gf @@ -1,6 +1,6 @@ --# -path=.:../polish:../common:../abstract:../prelude -resource TryPol = SyntaxPol, LexiconPol, ParadigmsPol - [mkAdv] ** +resource TryPol = SyntaxPol, LexiconPol, ParadigmsPol - [mkAdv,mkAdN,mkIAdv,mkCard,mkDet,mkIDet,mkQuant,mkPConj] ** open (P = ParadigmsPol) in { --oper diff --git a/src/polish/AdjectiveMorphoPol.gf b/src/polish/AdjectiveMorphoPol.gf index 4cf89b94..928f7720 100644 --- a/src/polish/AdjectiveMorphoPol.gf +++ b/src/polish/AdjectiveMorphoPol.gf @@ -121,14 +121,52 @@ resource AdjectiveMorphoPol = open CatPol, ResPol, Prelude, (Predef=Predef) in { pos = pos; comp = model_comp comp; super = model_comp ("naj"+comp) ; - advpos = nonExist; - advcomp = nonExist; - advsuper = nonExist; + advpos = guess_adverb pos.s1; + advcomp = "bardziej" ++ guess_adverb pos.s1; + advsuper = "najbardziej" ++ guess_adverb pos.s1; }; + -- Analytic degree markers do not inflect, but the adjective following them + -- does: "bardziej interesująca", "najbardziej interesujące". + oper analytic_forms : Str -> adj11forms -> adj11forms = \degree, forms -> { + s1 = degree ++ forms.s1; + s2 = degree ++ forms.s2; + s3 = degree ++ forms.s3; + s4 = degree ++ forms.s4; + s5 = degree ++ forms.s5; + s6 = degree ++ forms.s6; + s7 = degree ++ forms.s7; + s8 = degree ++ forms.s8; + s9 = degree ++ forms.s9; + s10 = degree ++ forms.s10; + s11 = degree ++ forms.s11 + }; + + -- Productive adverb formation. Irregular adjectives can still use the + -- fuller constructors below, but the default adjective constructor must + -- not make ordinary adverbial uses disappear from linearization. + oper guess_adverb : Str -> Str = \form -> case form of { + stem + "ny" => stem + "nie"; + stem + "ry" => stem + "rze"; + stem + "ki" => stem + "ko"; + stem + "gi" => stem + "go"; + stem + "ty" => stem + "cie"; + stem + "ły" => stem + "le"; + stem + "y" => stem + "o"; + stem + "i" => stem + "io"; + _ => form + }; + oper mkA = overload { mkA : adj11forms -> A = - \pos -> mkAForms pos ("bardziej" ++ pos.s1) ; + \pos -> lin A { + pos = pos; + comp = analytic_forms "bardziej" pos; + super = analytic_forms "najbardziej" pos; + advpos = guess_adverb pos.s1; + advcomp = "bardziej" ++ guess_adverb pos.s1; + advsuper = "najbardziej" ++ guess_adverb pos.s1 + }; mkA : adj11forms -> Str -> A = mkAForms ; } ; @@ -189,19 +227,19 @@ resource AdjectiveMorphoPol = open CatPol, ResPol, Prelude, (Predef=Predef) in { oper mkCompAdj = overload { mkCompAdj : Str -> Str -> A = - \pos, advpos -> lin A { - pos = guess_model pos; - comp = guess_model ("bardziej" ++ pos); - super = guess_model ("najbardziej" ++ pos); + \pos, advpos -> let forms = guess_model pos in lin A { + pos = forms; + comp = analytic_forms "bardziej" forms; + super = analytic_forms "najbardziej" forms; advpos = advpos; advcomp = ("bardziej" ++ advpos); advsuper = ("najbardziej" ++ advpos); }; mkCompAdj : Str -> A = - \pos -> lin A { - pos = guess_model pos; - comp = guess_model ("bardziej" ++ pos); - super = guess_model ("najbardziej" ++ pos); + \pos -> let forms = guess_model pos in lin A { + pos = forms; + comp = analytic_forms "bardziej" forms; + super = analytic_forms "najbardziej" forms; advpos = "["++pos ++ [": the adverb positive form does not exist]"]; advcomp = "["++pos ++ [": the adverb comparative form does not exist]"]; advsuper = "["++pos ++ [": the adverb superlative form does not exist]"] diff --git a/src/polish/AdjectivePol.gf b/src/polish/AdjectivePol.gf index 989ba5ef..ab7083b3 100644 --- a/src/polish/AdjectivePol.gf +++ b/src/polish/AdjectivePol.gf @@ -44,7 +44,10 @@ flags coding=utf8 ; UseA2 a = { s = mkAtable a.pos; adv=a.advpos ; isPost = False}; -- SentAP : AP -> SC -> AP ; -- good that she is here -- I have bad feelling about this function - SentAP a s = {s=\\_=>a.adv ++ s.s; adv=a.adv ++ s.s ; isPost = True}; + SentAP a sc = { + s = \\af => a.s ! af ++ sc.s; + adv = a.adv ++ sc.s; + isPost = False + }; }; - diff --git a/src/polish/AdverbPol.gf b/src/polish/AdverbPol.gf index 18af7e6e..b74cc1e1 100644 --- a/src/polish/AdverbPol.gf +++ b/src/polish/AdverbPol.gf @@ -7,6 +7,10 @@ concrete AdverbPol of Adverb = CatPol ** open ResPol, Prelude in { lin PositAdvAdj a = {s = a.advpos } ; + +-- AdA is the adverbial modifier form of an adjective. Polish uses the +-- ordinary adverbial form here as well ("wyjątkowo dobrze"). + PositAdAAdj a = {s = a.advpos} ; -- ComparAdvAdj : CAdv -> A -> NP -> Adv ; -- more warmly than John ComparAdvAdj c a n = { diff --git a/src/polish/ConjunctionPol.gf b/src/polish/ConjunctionPol.gf index 773aabbf..8fc2ddd3 100644 --- a/src/polish/ConjunctionPol.gf +++ b/src/polish/ConjunctionPol.gf @@ -41,6 +41,11 @@ concrete ConjunctionPol of Conjunction = s = \\af=>conj.s1 ++ list.ap1.s!af ++ conj.s2 ++ list.ap2.s!af; isPost = list.ap2.isPost --- }; + + ConjCN conj list = { + s = \\n,c => conj.s1 ++ list.cn1 ! n ! c ++ conj.s2 ++ list.cn2 ! n ! c; + g = list.g + }; ConjRS = conjunctDistrTable GenNum; @@ -78,6 +83,17 @@ concrete ConjunctionPol of Conjunction = s = \\af=> ap.s!af ++ "," ++ apl.ap1.s!af; adv = ap.adv ++ "," ++ apl.ap1.adv ; isPost = apl.isPost } ; isPost = apl.isPost}; + + BaseCN cn1 cn2 = { + cn1 = cn1.s; + cn2 = cn2.s; + g = conjGender cn1.g cn2.g + }; + ConsCN cn cns = { + cn1 = \\n,k => cn.s ! n ! k ++ "," ++ cns.cn1 ! n ! k; + cn2 = cns.cn2; + g = conjGender cn.g cns.g + }; lincat @@ -85,6 +101,15 @@ concrete ConjunctionPol of Conjunction = [Adv] = {s1,s2 : Str} ; [NP] = {np1,np2 : NounPhrase} ; [AP] = {ap1,ap2 : AdjPhrase ; isPost : Bool} ; + [CN] = {cn1,cn2 : Number => Case => Str; g : Gender} ; [RS] = {s1,s2 : GenNum => Str} ; + oper + conjGender : Gender -> Gender -> Gender ; + conjGender x y = case of { + <(Masc Personal),_> => Masc Personal; + <_,(Masc Personal)> => Masc Personal; + <_,_> => Plur + }; + } diff --git a/src/polish/ConstructionPol.gf b/src/polish/ConstructionPol.gf new file mode 100644 index 00000000..ee92ba4f --- /dev/null +++ b/src/polish/ConstructionPol.gf @@ -0,0 +1,113 @@ +--# -path=.:../abstract:../common:../prelude + +-- Idiomatic constructions and calendar expressions for Polish. +concrete ConstructionPol of Construction = CatPol ** + open ResPol, MorphoPol, Prelude, (G = GrammarPol), (P = ParadigmsPol), + (S = StructuralPol) in { + +flags coding=utf8 ; + +lincat + Timeunit = N ; + Hour = {s : Str} ; + Weekday = N ; + Month = N ; + Monthday, Year = {s : Str} ; + Language = {s : Str} ; + +lin + ready_VP = G.UseComp (G.CompAP (G.PositA (mkA (guess_model "gotowy")))) ; + + -- Polish expresses age with mieć: "ma trzydzieści lat". + has_age_VP card = G.ComplSlash (G.SlashV2a S.have_V2) (ageNP card) ; + + n_units_AP card unit adj = { + s = \\af => card.s ! Nom ! unit.g ++ unit.s ! Pl ! Gen ++ + (mkAtable adj.pos) ! af; + adv = card.s ! Nom ! unit.g ++ unit.s ! Pl ! Gen ++ adj.advpos; + isPost = False + } ; + + n_units_of_NP card unit np = { + nom = card.s ! Nom ! unit.g ++ unit.s ! Pl ! Gen ++ np.dep ! GenNoPrep; + voc = card.s ! VocP ! unit.g ++ unit.s ! Pl ! Gen ++ np.dep ! GenNoPrep; + dep = \\cc => let c = extract_case ! cc in + card.s ! c ! unit.g ++ unit.s ! Pl ! Gen ++ np.dep ! GenNoPrep; + gn = accom_gennum ! ; + p = P3 + } ; + + cup_of_CN np = containerCN (P.mkN "filiżanka" Fem) np ; + + weekdayPunctualAdv w = {s = "w" ++ w.s ! SF Sg Acc} ; + weekdayHabitualAdv w = {s = "w" ++ w.s ! SF Pl Acc} ; + yearAdv y = {s = "w" ++ y.s ++ "roku"} ; + intYear i = {s = i.s} ; + + weekdayN w = w ; + monthN m = m ; + + monday_Weekday = P.mkN "poniedziałek" (Masc Inanimate) ; + tuesday_Weekday = P.mkN "wtorek" (Masc Inanimate) ; + wednesday_Weekday = P.mkN "środa" Fem ; + thursday_Weekday = P.mkN "czwartek" (Masc Inanimate) ; + friday_Weekday = P.mkN "piątek" (Masc Inanimate) ; + saturday_Weekday = P.mkN "sobota" Fem ; + sunday_Weekday = P.mkN "niedziela" Fem ; + + january_Month = P.mkN "styczeń" (Masc Inanimate) ; + february_Month = P.mkN "luty" (Masc Inanimate) ; + march_Month = P.mkN "marzec" (Masc Inanimate) ; + april_Month = P.mkN "kwiecień" (Masc Inanimate) ; + may_Month = P.mkN "maj" (Masc Inanimate) ; + june_Month = P.mkN "czerwiec" (Masc Inanimate) ; + july_Month = P.mkN "lipiec" (Masc Inanimate) ; + august_Month = P.mkN "sierpień" (Masc Inanimate) ; + september_Month = P.mkN "wrzesień" (Masc Inanimate) ; + october_Month = P.mkN "październik" (Masc Inanimate) ; + november_Month = P.mkN "listopad" (Masc Inanimate) ; + december_Month = P.mkN "grudzień" (Masc Inanimate) ; + +oper + yearN : N = P.mkN "rok" (Masc Inanimate) ; + + ageNP : Card -> NP ; + ageNP card = lin NP { + nom = ageForm card Nom; + voc = ageForm card VocP; + dep = \\cc => ageForm card (extract_case ! cc); + gn = NeutSg; + p = P3 + } ; + + ageForm : Card -> Case -> Str ; + ageForm card c = card.s ! c ! (Masc Inanimate) ++ case of { + => case c of { + Gen => "roku"; Dat => "rokowi"; Instr => "rokiem"; + Loc => "roku"; VocP => "roku"; _ => "rok" + }; + <_,DwaA> => case c of { + Gen|Loc => "lat"; Dat => "latom"; Instr => "latami"; _ => "lata" + }; + <_,_> => "lat" + } ; + + cardinalUnitNP : Card -> N -> NP ; + cardinalUnitNP card unit = lin NP { + nom = card.s ! Nom ! unit.g ++ unit.s ! SF card.n + (accom_case ! ); + voc = card.s ! VocP ! unit.g ++ unit.s ! SF card.n + (accom_case ! ); + dep = \\cc => let c = extract_case ! cc in + card.s ! c ! unit.g ++ unit.s ! SF card.n + (accom_case ! ); + gn = accom_gennum ! ; + p = P3 + } ; + + containerCN : N -> NP -> CN ; + containerCN container np = lin CN { + s = \\n,c => container.s ! SF n c ++ np.dep ! GenNoPrep; + g = container.g + } ; +} diff --git a/src/polish/ExtendPol.gf b/src/polish/ExtendPol.gf index a1f13458..1d291969 100644 --- a/src/polish/ExtendPol.gf +++ b/src/polish/ExtendPol.gf @@ -2,12 +2,25 @@ concrete ExtendPol of Extend = CatPol ** ExtendFunctor - [ - iFem_Pron, youFem_Pron, theyFem_Pron, ProDrop, PassVPSlash, ExistsNP + iFem_Pron, youFem_Pron, theyFem_Pron, ProDrop, PassVPSlash, ExistsNP, + VPS, BaseVPS, ConsVPS, MkVPS, ConjVPS, PredVPS, + VPI, BaseVPI, ConsVPI, MkVPI, ConjVPI, ComplVPIVV, + PresPartAP, PastPartAP, PastPartAgentAP, PassAgentVPSlash, + ProgrVPSlash, CompoundN, CompoundAP, GerundCN, GerundNP, + GerundAdv, ByVP, InOrderToVP, ApposNP, PositAdVAdj, + ReflRNP, ReflPron, ReflPoss, PredetRNP, AdvRNP, AdvRVP, + AdvRAP, ReflA2RNP, PossPronRNP, ReflPossPron ] with (Grammar = GrammarPol) ** open PronounMorphoPol, ResPol, VerbMorphoPol, Prelude in { +lincat + VPS = {s : GenNum => Person => Str} ; + [VPS] = {s1,s2 : GenNum => Person => Str} ; + VPI = {s : GenNum => Str} ; + [VPI] = {s1,s2 : GenNum => Str} ; + -- ExtendFunctor defaults ExistsNP to ExistNP, which gives "jest macierz". -- Polish distinguishes the two: "there is" is jest/są, but "there exists" is -- istnieć, which is the form mathematical prose uses. @@ -37,6 +50,131 @@ lin UseDAPMasc = dap2np (Masc Personal) ; UseDAPFem = dap2np Fem ; +lin + MkVPS temp pol vp = { + s = \\gn,p => temp.s ++ pol.s ++ vp.prefix ++ + (indicative_form vp.verb vp.imienne pol.p ! ) ++ + vp.sufix ! pol.p ! gn + } ; + + BaseVPS x y = {s1=x.s; s2=y.s} ; + ConsVPS x xs = { + s1 = \\gn,p => x.s ! gn ! p ++ "," ++ xs.s1 ! gn ! p; + s2 = xs.s2 + } ; + ConjVPS conj xs = { + s = \\gn,p => conj.s1 ++ xs.s1 ! gn ! p ++ conj.s2 ++ xs.s2 ! gn ! p + } ; + PredVPS np vps = {s = np.nom ++ vps.s ! np.gn ! np.p} ; + + MkVPI vp = { + s = \\gn => vp.prefix ++ infinitive_form vp.verb vp.imienne Pos gn ++ + vp.sufix ! Pos ! gn + } ; + BaseVPI x y = {s1=x.s; s2=y.s} ; + ConsVPI x xs = { + s1 = \\gn => x.s ! gn ++ "," ++ xs.s1 ! gn; + s2 = xs.s2 + } ; + ConjVPI conj xs = { + s = \\gn => conj.s1 ++ xs.s1 ! gn ++ conj.s2 ++ xs.s2 ! gn + } ; + ComplVPIVV vv vpi = setSufix (defVP vv) (\\_,gn => vpi.s ! gn) ; + + PresPartAP vp = { + s = \\af => case af of { + AF gn _ => (mkAtable (table2record vp.verb.apart)) ! af ++ + vp.sufix ! Pos ! gn + }; + adv = vp.verb.si ! VInfM ++ vp.sufix ! Pos ! MascPersSg; + isPost = False + } ; + + PastPartAP vps = { + s = \\af => case af of { + AF gn _ => (mkAtable (table2record vps.verb.ppartp)) ! af ++ + vps.sufix ! Pos ! gn ++ vps.postfix ! Pos ! gn + }; + adv = vps.verb.si ! VInfM; + isPost = False + } ; + + PastPartAgentAP vps np = { + s = \\af => case af of { + AF gn _ => (mkAtable (table2record vps.verb.ppartp)) ! af ++ + vps.sufix ! Pos ! gn ++ vps.postfix ! Pos ! gn ++ + "przez" ++ np.dep ! AccPrep + }; + adv = vps.verb.si ! VInfM ++ "przez" ++ np.dep ! AccPrep; + isPost = False + } ; + + PassAgentVPSlash vps np = setSufix (setImienne vps True) + (\\p,gn => vps.sufix ! p ! gn ++ vps.postfix ! p ! gn ++ + "przez" ++ np.dep ! AccPrep) ; + + ProgrVPSlash vps = vps ; + + CompoundN modifier head = { + s = \\sf => case sf of { + SF n c => head.s ! sf ++ modifier.s ! SF Sg Gen + }; + g = head.g + } ; + + CompoundAP noun adj = { + s = \\af => noun.s ! SF Sg Instr ++ (mkAtable adj.pos) ! af; + adv = noun.s ! SF Sg Instr ++ adj.advpos; + isPost = False + } ; + + GerundCN vp = { + s = \\n,c => vp.prefix ++ vp.verb.ger ! SF n c ++ + vp.sufix ! Pos ! NeutSg; + g = Neut + } ; + GerundNP vp = { + nom = vp.prefix ++ vp.verb.ger ! SF Sg Nom ++ + vp.sufix ! Pos ! NeutSg; + voc = vp.prefix ++ vp.verb.ger ! SF Sg VocP ++ + vp.sufix ! Pos ! NeutSg; + dep = \\cc => vp.prefix ++ vp.verb.ger ! SF Sg (extract_case ! cc) ++ + vp.sufix ! Pos ! NeutSg; + gn = NeutSg; p = P3 + } ; + GerundAdv vp = { + s = "podczas" ++ vp.prefix ++ vp.verb.ger ! SF Sg Gen ++ + vp.sufix ! Pos ! NeutSg + } ; + ByVP vp = { + s = "przez" ++ vp.prefix ++ vp.verb.ger ! SF Sg Acc ++ + vp.sufix ! Pos ! NeutSg + } ; + InOrderToVP vp = { + s = "aby" ++ vp.prefix ++ infinitive_form vp.verb vp.imienne Pos NeutSg ++ + vp.sufix ! Pos ! NeutSg + } ; + + ApposNP a b = { + nom = a.nom ++ "," ++ b.nom; + voc = a.voc ++ "," ++ b.voc; + dep = \\c => a.dep ! c ++ "," ++ b.dep ! c; + gn = a.gn; p = a.p + } ; + PositAdVAdj a = {s = a.advpos} ; + + ReflPron = lin RNP (lin NP (pronRefl NeutSg)) ; + ReflPoss num cn = lin RNP (DetCN (DetQuant (PossPron (pronRefl NeutSg)) num) cn) ; + PredetRNP pred rnp = lin RNP (PredetNP pred (lin NP rnp)) ; + AdvRNP np prep rnp = lin RNP (AdvNP np (PrepNP prep (lin NP rnp))) ; + AdvRVP vp prep rnp = AdvVP vp (PrepNP prep rnp) ; + AdvRAP ap prep rnp = AdvAP ap (PrepNP prep rnp) ; + ReflRNP vps rnp = ComplSlash vps (lin NP rnp) ; + ReflA2RNP a rnp = ComplA2 a (lin NP rnp) ; + PossPronRNP pron num cn rnp = + DetCN (DetQuant (PossPron pron) num) (PossNP cn (lin NP rnp)) ; + ReflPossPron = PossPron (pronRefl NeutSg) ; + oper dap2np : Gender -> DAP -> NP ; dap2np g dap = lin NP { diff --git a/src/polish/IdiomPol.gf b/src/polish/IdiomPol.gf index b94e462f..2d169eda 100644 --- a/src/polish/IdiomPol.gf +++ b/src/polish/IdiomPol.gf @@ -55,6 +55,13 @@ concrete IdiomPol of Idiom = CatPol ** open Prelude, ResPol, VerbMorphoPol in { ExistNP np = {s=\\pol,anter,tense => case pol of { Pos=> jest_op ! ++ np.nom; Neg=> niema_op! ++ np.dep!GenNoPrep } }; + + ExistNPAdv np adv = { + s = \\pol,anter,tense => case pol of { + Pos => jest_op ! ++ np.nom ++ adv.s; + Neg => niema_op ! ++ np.dep ! GenNoPrep ++ adv.s + } + }; -- ExistIP : IP -> QCl ; -- which houses are there ExistIP ip = {s=\\pol,anter,tense => case pol of { @@ -69,6 +76,8 @@ concrete IdiomPol of Idiom = CatPol ** open Prelude, ResPol, VerbMorphoPol in { refl=vp.verb.refl; asp=vp.verb.asp; ppartp=vp.verb.pparti; - pparti=vp.verb.pparti} + pparti=vp.verb.pparti; + apart=vp.verb.apart; + ger=vp.verb.ger} }; } ; diff --git a/src/polish/LangPol.gf b/src/polish/LangPol.gf index d04c6261..0ec7aa01 100644 --- a/src/polish/LangPol.gf +++ b/src/polish/LangPol.gf @@ -5,5 +5,6 @@ concrete LangPol of Lang = GrammarPol, LexiconPol, + ConstructionPol, DocumentationPol --# notpresent ** { flags startcat = Phr ; unlexer = text ; lexer = text; } ; diff --git a/src/polish/NamesPol.gf b/src/polish/NamesPol.gf index a8d060db..117305eb 100644 --- a/src/polish/NamesPol.gf +++ b/src/polish/NamesPol.gf @@ -1,4 +1,4 @@ -concrete NamesPol of Names = CatPol ** { +concrete NamesPol of Names = CatPol ** open ResPol in { lin GivenName, MaleSurname, FemaleSurname = \n -> n ; lin FullName gn sn = { @@ -11,4 +11,14 @@ lin FullName gn sn = { lin UseLN n = n; +lin InLN n = {s = "w" ++ n.dep ! LocPrep} ; + +lin AdjLN ap n = { + nom = ap.s ! AF n.gn Nom ++ n.nom ; + voc = ap.s ! AF n.gn VocP ++ n.voc ; + dep = \\cc => ap.s ! AF n.gn (extract_case ! cc) ++ n.dep ! cc ; + gn = n.gn ; + p = n.p + } ; + } diff --git a/src/polish/NounPol.gf b/src/polish/NounPol.gf index 36c82e92..5c35ded4 100644 --- a/src/polish/NounPol.gf +++ b/src/polish/NounPol.gf @@ -67,6 +67,37 @@ concrete NounPol of Noun = CatPol ** open ResPol, Prelude, PronounMorphoPol, Mor p = np.p }; + ExtAdvNP np a = { + nom = np.nom ++ "," ++ a.s; + voc = np.voc ++ "," ++ a.s; + dep = \\c => np.dep ! c ++ "," ++ a.s; + gn = np.gn; + p = np.p + }; + +-- PossNP : CN -> NP -> CN ; -- house of Paris +-- Polish nominal possessors follow the head noun and are genitive. + PossNP cn np = { + s = \\n,c => cn.s ! n ! c ++ np.dep ! GenNoPrep; + g = cn.g + }; + +-- Partitives have a genitive complement: "szklanka wody", "kromka chleba". + PartNP cn np = { + s = \\n,c => cn.s ! n ! c ++ np.dep ! GenNoPrep; + g = cn.g + }; + +-- Determiner-headed partitives: "kilku z nich", "niektórzy z uczniów". + CountNP det np = { + nom = det.s ! Nom ! (genGenNum np.gn) ++ "z" ++ np.dep ! GenPrep; + voc = det.s ! VocP ! (genGenNum np.gn) ++ "z" ++ np.dep ! GenPrep; + dep = \\cc => let c = extract_case ! cc in + det.s ! c ! (genGenNum np.gn) ++ "z" ++ np.dep ! GenPrep; + gn = accom_gennum ! ; + p = P3 + }; + -- surface structures of NP formed with MassNP, DefArt and IndefArt are identical DefArt = {s = \\_=>[] ; sp = (demPronTen "ten").sp }; IndefArt = {s = \\_=>[] ; sp = jaki }; @@ -210,6 +241,15 @@ concrete NounPol of Noun = CatPol ** open ResPol, Prelude, PronounMorphoPol, Mor DetDAP d = d ; +-- In the pronominal use of a determiner the adjective supplies the lexical +-- material: "ten obecny", "trzej mniejsi". + AdjDAP dap ap = dap ** { + s = \\c,g => dap.s ! c ! g ++ + ap.s ! AF (cast_gennum ! ) (accom_case ! ); + sp = \\c,g => dap.sp ! c ! g ++ + ap.s ! AF (cast_gennum ! ) (accom_case ! ) + }; + QuantityNP n m = { nom,voc = preOrPost m.isPre m.s n.s; dep = \\cc => preOrPost m.isPre m.s n.s ; diff --git a/src/polish/NumeralPol.gf b/src/polish/NumeralPol.gf index 60ec8784..d5fd4ca9 100644 --- a/src/polish/NumeralPol.gf +++ b/src/polish/NumeralPol.gf @@ -468,6 +468,13 @@ n9 = { unit = table { }; -- pot2 : Sub10 -> Sub1000 ; -- m * 100 + pot21 = { + s = \\_ => "sto"; + o = mkAtable (guess_model "setny"); + a = StoA; + n = Pl + }; + pot2 s = { s = s.hundred; o = s.ohundred; @@ -493,6 +500,13 @@ n9 = { unit = table { }; -- pot3 : Sub1000 -> Sub1000000 ; -- m * 1000 + pot31 = { + s = \\x => tysiac ! ; + o = mkAtable (guess_model "tysięczny"); + a = TysiacA; + n = Pl + }; + pot3 s = { s = \\x => case s.n of { Sg => ""; Pl => s.s! } ++ tysiac!<(accom_case! ),s.n>; @@ -515,8 +529,59 @@ n9 = { unit = table { }; pot3as4 n = n ; + + pot41 = { + s = \\x => milion ! ; + o = mkAtable (guess_model "milionowy"); + a = TysiacA; + n = Pl + }; + + pot4 n = { + s = \\x => n.s ! ++ + milion ! <(accom_case ! ),n.n>; + o = \\af => n.s ! ++ + (mkAtable (guess_model "milionowy")) ! af; + a = TysiacA; + n = Pl + }; + + pot4plus n rest = { + s = \\x => n.s ! ++ + milion ! <(accom_case ! ),n.n> ++ + rest.s ! x; + o = \\af => n.s ! ++ "milion" ++ rest.o ! af; + a = rest.a; + n = Pl + }; + pot4as5 n = n ; + pot51 = { + s = \\x => miliard ! ; + o = mkAtable (guess_model "miliardowy"); + a = TysiacA; + n = Pl + }; + + pot5 n = { + s = \\x => n.s ! ++ + miliard ! <(accom_case ! ),n.n>; + o = \\af => n.s ! ++ + (mkAtable (guess_model "miliardowy")) ! af; + a = TysiacA; + n = Pl + }; + + pot5plus n rest = { + s = \\x => n.s ! ++ + miliard ! <(accom_case ! ),n.n> ++ + rest.s ! x; + o = \\af => n.s ! ++ "miliard" ++ rest.o ! af; + a = rest.a; + n = Pl + }; + oper tysiac = table { <(Nom|Acc), Sg> => "tysiąc"; => "tysiąca"; @@ -530,6 +595,32 @@ oper tysiac = table { => "tysiącach" }; + milion = table { + <(Nom|Acc), Sg> => "milion"; + => "miliona"; + => "milionowi"; + => "milionem"; + <(Loc|VocP),Sg> => "milionie"; + <(Nom|Acc|VocP), Pl> => "miliony"; + => "milionów"; + => "milionom"; + => "milionami"; + => "milionach" + }; + + miliard = table { + <(Nom|Acc), Sg> => "miliard"; + => "miliarda"; + => "miliardowi"; + => "miliardem"; + <(Loc|VocP),Sg> => "miliardzie"; + <(Nom|Acc|VocP), Pl> => "miliardy"; + => "miliardów"; + => "miliardom"; + => "miliardami"; + => "miliardach" + }; + -- -- Numerals as sequences of digits have a separate, simpler grammar lincat diff --git a/src/polish/ParadigmsPol.gf b/src/polish/ParadigmsPol.gf index 6131f8e5..1d1705c4 100644 --- a/src/polish/ParadigmsPol.gf +++ b/src/polish/ParadigmsPol.gf @@ -26,6 +26,29 @@ mkA2 : A -> Str -> ComplCase -> A2 ; + mkVS : V -> VS ; + mkVA : V -> VA ; + mkVV : V -> VV ; + mkVQ : V -> VQ ; + mkV2V : V -> Complement -> V2V ; + mkV2S : V -> Complement -> V2S ; + mkV2A : V -> Complement -> V2A ; + + mkAdA : Str -> AdA ; + mkAdN : Str -> AdN ; + mkAdV : Str -> AdV ; + mkIAdv : Str -> IAdv ; + mkPConj : Str -> PConj ; + mkSubj : Str -> Subj ; + mkCard : Str -> Card ; + mkACard : Str -> ACard ; + mkDet : Str -> Det ; + mkIDet : Str -> IDet ; + mkQuant : Str -> Quant ; + mkIQuant : Str -> IQuant ; + mkPredet : Str -> Predet ; + mkCAdv : Str -> CAdv ; + mkAdv : Str -> Adv ; -- an adverb from a string @@ -57,6 +80,29 @@ mkA2 adj s c = lin A2 (adj ** { c={s=s; c=c} }); + mkVS v = lin VS v ; + mkVA v = lin VA (v ** {c={s=""; adv=False; c=Nom}}) ; + mkVV v = lin VV v ; + mkVQ v = lin VQ v ; + mkV2V v p = lin V2V (v ** {c=p}) ; + mkV2S v p = lin V2S (v ** {c=p}) ; + mkV2A v p = lin V2A (v ** {c={s=""; adv=False; c=Nom}; c2=p}) ; + + mkAdA s = lin AdA {s=s} ; + mkAdN s = lin AdN {s=s} ; + mkAdV s = lin AdV {s=s} ; + mkIAdv s = lin IAdv {s=s} ; + mkPConj s = lin PConj {s=s} ; + mkSubj s = lin Subj {s=s} ; + mkCard s = lin Card {s=\\_,_ => s; a=NoA; n=Pl} ; + mkACard s = lin ACard {s=s} ; + mkDet s = lin Det {s,sp=\\_,_ => s; n=Sg; a=NoA} ; + mkIDet s = lin IDet {s=\\_,_ => s; n=Pl; a=NoA} ; + mkQuant s = lin Quant {s,sp=\\_ => s} ; + mkIQuant s = lin IQuant {s=\\_ => s} ; + mkPredet s = lin Predet {s=\\_ => s; np=wszystko; adj=True} ; + mkCAdv s = lin CAdv {s,sn=s; p,pn="niż"} ; + mkN = overload { mkN : Str -> N = mkNGuessGender ; mkN : Str -> Gender -> N = mkNGender ; diff --git a/src/polish/QuestionPol.gf b/src/polish/QuestionPol.gf index 1bb7123e..8837593f 100644 --- a/src/polish/QuestionPol.gf +++ b/src/polish/QuestionPol.gf @@ -29,7 +29,8 @@ lin -- QuestIComp : IComp -> NP -> QCl ; -- where is John QuestIComp ic np = { s = \\p,a,t => ic.s ++ - (imienne_form (lin V {si = \\_=>[]; sp = \\_=>[]; asp = Dual; refl = ""; pparti,ppartp=\\_=>""}) p ! ) ++ np.nom + (imienne_form (lin V {si = \\_=>[]; sp = \\_=>[]; asp = Dual; refl = ""; + pparti,ppartp,apart=\\_=>""; ger=\\_=>""}) p ! ) ++ np.nom }; -- IdetCN : IDet -> CN -> IP ; -- which five songs diff --git a/src/polish/ResPol.gf b/src/polish/ResPol.gf index dda7c57f..3ef49f71 100644 --- a/src/polish/ResPol.gf +++ b/src/polish/ResPol.gf @@ -85,7 +85,9 @@ refl : Str; asp : Aspect; ppartp : adj11table; --AForm=>Str; - pparti : adj11table --AForm=>Str + pparti : adj11table; --AForm=>Str + apart : adj11table; + ger : SubstForm => Str }; oper VerbPhrase : Type = { diff --git a/src/polish/SentencePol.gf b/src/polish/SentencePol.gf index ee8ed4e6..a42dec54 100644 --- a/src/polish/SentencePol.gf +++ b/src/polish/SentencePol.gf @@ -71,6 +71,10 @@ lin (imperative_form vp.verb vp.imienne pol (cast_gennum!) P2) ++ vp.sufix !pol !MascAniSg }; + + AdvImp adv imp = { + s = \\pol,num => adv.s ++ imp.s ! pol ! num + }; -- AdvS : Adv -> S -> S ; -- today, I will go home AdvS adv s = { s = adv.s ++ s.s }; diff --git a/src/polish/VerbMorphoPol.gf b/src/polish/VerbMorphoPol.gf index ba8b9e4a..ce278a5a 100644 --- a/src/polish/VerbMorphoPol.gf +++ b/src/polish/VerbMorphoPol.gf @@ -5,7 +5,8 @@ -- -- Adam Slaski, 2009 -- -resource VerbMorphoPol = open CatPol, ResPol, Prelude, (Predef=Predef), (Adj=AdjectiveMorphoPol) in { +resource VerbMorphoPol = open CatPol, ResPol, Prelude, (Predef=Predef), + (Adj=AdjectiveMorphoPol), (NM=NounMorphoPol) in { flags coding=utf8; @@ -345,7 +346,9 @@ resource VerbMorphoPol = open CatPol, ResPol, Prelude, (Predef=Predef), (Adj=Adj refl = "się"; asp = v.asp; ppartp = v.ppartp; - pparti = v.pparti + pparti = v.pparti; + apart = v.apart; + ger = \\f => v.ger ! f ++ "się" }; -- intransitive verbs @@ -357,7 +360,9 @@ resource VerbMorphoPol = open CatPol, ResPol, Prelude, (Predef=Predef), (Adj=Adj refl = v.refl; asp = v.asp; ppartp = record2table { s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11 = nonExist }; - pparti = record2table { s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11 = nonExist } + pparti = record2table { s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11 = nonExist }; + apart = v.apart; + ger = v.ger }; -- monoaspective verbs @@ -369,7 +374,9 @@ resource VerbMorphoPol = open CatPol, ResPol, Prelude, (Predef=Predef), (Adj=Adj refl = ""; asp = a; ppartp = tmp.p; - pparti = tmp.p + pparti = tmp.p; + apart = mkActivePart tmp.s; + ger = mkGerund tmp.p }; -- normal verbs @@ -381,7 +388,9 @@ resource VerbMorphoPol = open CatPol, ResPol, Prelude, (Predef=Predef), (Adj=Adj refl = ""; asp = Dual; ppartp = tmpp.p; - pparti = tmpi.p + pparti = tmpi.p; + apart = mkActivePart tmpi.s; + ger = mkGerund tmpp.p }; -- Comlicated verbs @@ -392,12 +401,45 @@ resource VerbMorphoPol = open CatPol, ResPol, Prelude, (Predef=Predef), (Adj=Adj oper mkComplicatedVerb : V -> Str -> V = \v,s -> lin V {si = \\form => v.si !form ++ s; - sp = \\form => v.sp !form ++ s; - refl = v.refl; asp = v.asp; - ppartp = record2table { s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11 = nonExist}; - pparti = record2table { s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11 = nonExist} + sp = \\form => v.sp !form ++ s; + refl = v.refl; asp = v.asp; + -- Multiword verbs retain the participles of their verbal head: + -- "wprowadzony w błąd", "idący na emeryturę". Dropping them + -- made every passive and participial use of such a verb disappear. + ppartp = \\f => v.ppartp ! f ++ s; + pparti = \\f => v.pparti ! f ++ s; + apart = \\f => v.apart ! f ++ s; + ger = \\f => v.ger ! f ++ s }; + oper mkActivePart : (VFormM => Str) -> adj11table = \forms -> + case forms ! VFinM Pl P3 of { + stem + "ą" => record2table { + s1 = stem + "ący"; s2 = stem + "ącego"; + s3 = stem + "ącemu"; s4 = stem + "ącym"; + s5 = stem + "ące"; s6 = stem + "ąca"; + s7 = stem + "ącej"; s8 = stem + "ącą"; + s9 = stem + "ący"; s10 = stem + "ących"; + s11 = stem + "ącymi" + }; + form => record2table { + s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11 = form + } + }; + + oper mkGerund : adj11table -> SubstForm => Str = \part -> + let lemma = case part ! X1 of { + stem + "iany" => stem + "ianie"; + stem + "iony" => stem + "ienie"; + stem + "any" => stem + "anie"; + stem + "ony" => stem + "enie"; + stem + "nięty" => stem + "nięcie"; + stem + "ęty" => stem + "ęcie"; + stem + "ty" => stem + "cie"; + form => form + } + in NM.mkNTable0402 lemma ; + -- Two-place verbs -- Two-place verbs, and the special case with a direct object. Note that diff --git a/src/polish/VerbPol.gf b/src/polish/VerbPol.gf index 5479ce11..149974b3 100644 --- a/src/polish/VerbPol.gf +++ b/src/polish/VerbPol.gf @@ -34,6 +34,24 @@ lin -- an Adv, and *"π zbiór pusty przecina" is marked at best. AdvVP vp adv = setSufix vp (\\p,gn => vp.sufix ! p ! gn ++ adv.s); +-- Variants of adverb attachment used by the extended grammar. Keep the +-- missing object slot of VPSlash intact while changing only word order. + ExtAdvVP vp adv = setSufix vp + (\\p,gn => vp.sufix ! p ! gn ++ "," ++ adv.s); + + AdvVPSlash vps adv = vps ** { + sufix = \\p,gn => vps.sufix ! p ! gn ++ adv.s + }; + + AdVVPSlash adv vps = vps ** { + prefix = adv.s ++ vps.prefix + }; + + VPSlashPrep vp prep = vp ** { + c = prep; + postfix = \\_,_ => "" + }; + -- AdVVP : AdV -> VP -> VP ; -- always sleep AdVVP adV vp = setPrefix vp (vp.prefix ++ adV.s); @@ -56,7 +74,9 @@ lin -- UseComp : Comp -> VP ; -- be warm UseComp c = setImienne (setSufix (defVP {si = \\_=>[]; sp = \\_=>[]; - asp = Imperfective; refl = ""; ppartp,pparti= record2table empty11forms + asp = Imperfective; refl = ""; + ppartp,pparti,apart = record2table empty11forms; + ger = \\_ => "" }) (\\_,gn => c.s!gn)) True; @@ -110,13 +130,13 @@ lin oper - castv2 : (Verb ** { c:Complement }) -> Verb = \v2 -> {si=v2.si;sp=v2.sp;asp=v2.asp;refl=v2.refl; ppartp=v2.ppartp; pparti=v2.pparti}; + castv2 : (Verb ** { c:Complement }) -> Verb = \v2 -> {si=v2.si;sp=v2.sp;asp=v2.asp;refl=v2.refl; ppartp=v2.ppartp; pparti=v2.pparti; apart=v2.apart; ger=v2.ger}; - castv3 : (Verb ** { c,c2:Complement }) -> Verb = \v2 -> {si=v2.si;sp=v2.sp;asp=v2.asp;refl=v2.refl; ppartp=v2.ppartp; pparti=v2.pparti}; + castv3 : (Verb ** { c,c2:Complement }) -> Verb = \v2 -> {si=v2.si;sp=v2.sp;asp=v2.asp;refl=v2.refl; ppartp=v2.ppartp; pparti=v2.pparti; apart=v2.apart; ger=v2.ger}; - castva : (Verb ** { c:{c:Case; s:Str}}) -> Verb = \v2 -> {si=v2.si;sp=v2.sp;asp=v2.asp;refl=v2.refl; ppartp=v2.ppartp; pparti=v2.pparti}; + castva : (Verb ** { c:{c:Case; s:Str}}) -> Verb = \v2 -> {si=v2.si;sp=v2.sp;asp=v2.asp;refl=v2.refl; ppartp=v2.ppartp; pparti=v2.pparti; apart=v2.apart; ger=v2.ger}; - castv2a : (Verb ** { c:{c:Case; s:Str}; c2:Complement}) -> Verb = \v2 -> {si=v2.si;sp=v2.sp;asp=v2.asp;refl=v2.refl; ppartp=v2.ppartp; pparti=v2.pparti}; + castv2a : (Verb ** { c:{c:Case; s:Str}; c2:Complement}) -> Verb = \v2 -> {si=v2.si;sp=v2.sp;asp=v2.asp;refl=v2.refl; ppartp=v2.ppartp; pparti=v2.pparti; apart=v2.apart; ger=v2.ger}; defVP : Verb -> VerbPhrase = \v -> { prefix = ""; @@ -187,4 +207,3 @@ oper }; } ; -