From 0196d3006f5ecc783515cc54aa62de818c68931a Mon Sep 17 00:00:00 2001 From: Krasimir Angelov Date: Sun, 20 Sep 2026 17:55:32 +0200 Subject: [PATCH] extensions from Codex --- src/arabic/AdverbAra.gf | 1 + src/arabic/ConstructionAra.gf | 10 +++ src/arabic/ExtendAra.gf | 119 +++++++++++++++++++++++++++++++++- src/arabic/IdiomAra.gf | 12 +++- src/arabic/NamesAra.gf | 6 ++ src/arabic/NounAra.gf | 18 +++++ src/arabic/NumeralAra.gf | 40 ++++++++++++ src/arabic/ParadigmsAra.gf | 11 ++-- src/arabic/PhraseAra.gf | 2 + src/arabic/ResAra.gf | 10 ++- src/arabic/SentenceAra.gf | 15 ++++- src/arabic/VerbAra.gf | 8 +++ 12 files changed, 240 insertions(+), 12 deletions(-) diff --git a/src/arabic/AdverbAra.gf b/src/arabic/AdverbAra.gf index 2e5630b2..1b49d6e9 100644 --- a/src/arabic/AdverbAra.gf +++ b/src/arabic/AdverbAra.gf @@ -4,6 +4,7 @@ concrete AdverbAra of Adverb = CatAra ** open ResAra, Prelude in { lin PositAdvAdj a = {s = a.s ! APosit Masc Sg Indef Acc} ; + PositAdAAdj a = {s = a.s ! APosit Masc Sg Indef Acc} ; -- ComparAdvAdj cadv a np = { -- s = cadv.s ++ a.s ! AAdv ++ "مِنْ" ++ np.s ! Gen -- } ; diff --git a/src/arabic/ConstructionAra.gf b/src/arabic/ConstructionAra.gf index bd762048..7d0b8953 100644 --- a/src/arabic/ConstructionAra.gf +++ b/src/arabic/ConstructionAra.gf @@ -17,6 +17,16 @@ lincat lin + ready_VP = mkVP (mascA "مُسْتَعِدّ") ; + + has_age_VP card = mkVP (mkNP card (mkN "سَنَة" "سَنَوَات" fem nohum)) ; + + cup_of_CN np = mkCN (mkN "كُوب" "أَكْوَاب" masc nohum) + (SyntaxAra.mkAdv possess_Prep np) ; + + n_units_of_NP card cn np = + mkNP card (mkCN cn (SyntaxAra.mkAdv possess_Prep np)) ; + timeunitAdv n time = let n_card : Card = n ; n_hours_NP : NP = mkNP n_card time ; diff --git a/src/arabic/ExtendAra.gf b/src/arabic/ExtendAra.gf index 5ae5527f..3b93b9f7 100644 --- a/src/arabic/ExtendAra.gf +++ b/src/arabic/ExtendAra.gf @@ -6,14 +6,21 @@ concrete ExtendAra of Extend = EmptyRelSlash, PredAPVP, ComplDirectVS, ComplDirectVQ, UttAdV, -- because of Utt VPS, MkVPS, PredVPS, BaseVPS, ConsVPS, ConjVPS, + VPI, MkVPI, BaseVPI, ConsVPI, ConjVPI, ComplVPIVV, + BaseComp, ConsComp, ConjComp, + BaseImp, ConsImp, ConjImp, EmbedSSlash, AdjAsNP, GerundNP, PassVPSlash, ---- bogus implementation, see below + PassAgentVPSlash, PresPartAP, PastPartAP, PastPartAgentAP, ProgrVPSlash, + ReflPron, ReflPoss, AdvRNP, AdvRVP, AdvRAP, PossPronRNP, + CompoundAP, GerundCN, GerundAdv, ByVP, PositAdVAdj, CompoundN, UseDAP, UseDAPMasc, UseDAPFem ] with (Grammar=GrammarAra) ** open ResAra, + (P=ParamX), Prelude, ParadigmsAra, RelativeAra, @@ -71,6 +78,10 @@ lin lincat VPS = {s : PerGenNum => Str} ; -- finite VP's with tense and polarity [VPS] = {s1,s2 : PerGenNum => Str} ; + VPI = {s : Str} ; + [VPI] = {s1,s2 : Str} ; + [Comp] = {s1,s2 : AAgr => ResAra.Case => Str} ; + [Imp] = {s1,s2 : P.Polarity => ResAra.Gender => ResAra.Number => Str} ; lin -- : Temp -> Pol -> VP -> VPS ; -- hasn't slept MkVPS t p vp = { @@ -95,11 +106,70 @@ lin s = \\_ => np.s ! Nom ++ vps.s ! np.a.pgn -- first quick version with order always Nominal. } ; -- if necessary, change VPS into {s : PerGenNum => Order => {before,after : Str}} + MkVPI vp = {s = uttVP VPGer vp ! Masc} ; + BaseVPI x y = {s1 = x.s ; s2 = y.s} ; + ConsVPI x xs = {s1 = x.s ++ SOFT_BIND ++ "," ++ xs.s1 ; s2 = xs.s2} ; + ConjVPI conj xs = {s = xs.s1 ++ conj.s2 ++ xs.s2} ; + ComplVPIVV vv vpi = insertStr (vv.s2 ++ vpi.s) (predV vv) ; + + BaseComp x y = { + s1 = \\agr,cas => x.s ! agr ! cas ++ x.obj.s ; + s2 = \\agr,cas => y.s ! agr ! cas ++ y.obj.s + } ; + ConsComp x xs = { + s1 = \\agr,cas => x.s ! agr ! cas ++ x.obj.s ++ SOFT_BIND ++ "," ++ xs.s1 ! agr ! cas ; + s2 = xs.s2 + } ; + ConjComp conj xs = { + s = \\agr,cas => xs.s1 ! agr ! cas ++ conj.s2 ++ xs.s2 ! agr ! cas ; + obj = emptyObj ; + isNP = False + } ; + + BaseImp x y = {s1 = x.s ; s2 = y.s} ; + ConsImp x xs = { + s1 = \\p,g,n => x.s ! p ! g ! n ++ SOFT_BIND ++ "," ++ xs.s1 ! p ! g ! n ; + s2 = xs.s2 + } ; + ConjImp conj xs = { + s = \\p,g,n => xs.s1 ! p ! g ! n ++ conj.s2 ++ xs.s2 ! p ! g ! n + } ; + -- AR 24-02-08 - PassVPSlash vpslash = vpslash ** {s = \\pgn, vpf => vpslash.s ! pgn ! vpf} ; - ---- vpf does not have passive forms left, - ---- so this function is not possible with the current lincat of VP and VPSlash + PassVPSlash vpslash = vpslash ** { + s = \\pgn,vpf => case vpf of { + VPPerf => vpslash.s ! pgn ! VPPassPerf ; + VPImpf m => vpslash.s ! pgn ! VPPassImpf m ; + _ => vpslash.s ! pgn ! vpf + } ; + obj = emptyObj ; + c2 = accPrep ; + agrObj = \\_ => [] + } ; + + PassAgentVPSlash vpslash agent = + insertStr ("مِنْ قِبَلِ" ++ agent.s ! Gen) (PassVPSlash vpslash) ; + + PresPartAP vp = { + s = \\h,g,n,_,_ => presentRelative ! h ! g ! n + ++ vp.s ! Per3 g n ! VPImpf Ind + ++ vp.obj.s ++ vp.pred.s ! {g = g ; n = n} ! Acc ++ vp.s2 + } ; + + PastPartAP vpslash = { + s = \\_,_,_,_,_ => + vpslash.s ! Per3 Masc ResAra.Sg ! VPPPart + ++ vpslash.obj.s ++ vpslash.s2 + } ; + + PastPartAgentAP vpslash agent = + let ap = PastPartAP vpslash in ap ** { + s = \\h,g,n,d,c => ap.s ! h ! g ! n ! d ! c + ++ "مِنْ قِبَلِ" ++ agent.s ! Gen + } ; + + ProgrVPSlash vpslash = vpslash ; ---- very unsure about this as well CompoundN a b = b ** { @@ -134,4 +204,47 @@ lin UseDAPFem dap = case dap.isEmpty of { } ; False => emptyNP ** {s = dap.s ! NoHum ! Fem} } ; +lin ReflPoss num cn = + DetCN (DetQuant (PossPron he_Pron) num) cn ; + + ReflPron = lin NP (indeclNP "نَفْسِهِ" ResAra.Sg) ; + + AdvRNP np prep rnp = AdvNP np (PrepNP prep rnp) ; + AdvRVP vp prep rnp = AdvVP vp (PrepNP prep rnp) ; + AdvRAP ap prep rnp = AdvAP ap (PrepNP prep rnp) ; + + PossPronRNP pron num cn rnp = + DetCN (DetQuant (PossPron pron) num) + (PossNP cn rnp) ; + + GerundCN vp = useN { + s = \\_,_,_ => uttVP VPGer vp ! Masc ; + s2 = emptyNTable ; + g = Masc ; + h = NoHum ; + isDual = False + } ; + GerundAdv vp = {s = uttVP VPGer vp ! Masc} ; + ByVP vp = {s = "بِـ" ++ uttVP VPGer vp ! Masc} ; + + CompoundAP n a = + let ap = Grammar.PositA a in ap ** { + s = \\h,g,num,d,c => ap.s ! h ! g ! num ! d ! c + ++ n.s ! ResAra.Sg ! Const ! Gen + } ; + + PositAdVAdj a = {s = a.s ! APosit Masc ResAra.Sg Indef Acc} ; + +oper presentRelative : ResAra.Species => ResAra.Gender => ResAra.Number => Str = table { + NoHum => \\_,_ => "الَّتِي" ; + Hum => table { + Masc => table { + ResAra.Sg => "الَّذِي" ; Dl => "اللَّذَانِ" ; ResAra.Pl => "الَّذِينَ" + } ; + Fem => table { + ResAra.Sg => "الَّتِي" ; Dl => "اللَّتَانِ" ; ResAra.Pl => "اللَّاتِي" + } + } + } ; + } diff --git a/src/arabic/IdiomAra.gf b/src/arabic/IdiomAra.gf index 5b434768..60612b9c 100644 --- a/src/arabic/IdiomAra.gf +++ b/src/arabic/IdiomAra.gf @@ -44,9 +44,17 @@ concrete IdiomAra of Idiom = CatAra ** open -- ExistIPAdv : IP -> Adv -> QCl ; -- which houses are there in Paris - -- ProgrVP : VP -> VP ; -- be sleeping + -- Arabic normally expresses the unmarked progressive with the + -- imperfect, so no extra auxiliary is required here. + ProgrVP vp = vp ; - -- ImpPl1 : VP -> Utt ; -- let's go + -- The first-person plural jussive prefixed by لِ is the usual + -- hortative construction: لِنَذْهَبْ "let us go". + ImpPl1 vp = {s = \\_ => "لِ" ++ BIND + ++ vp.s ! Per1 Plur ! VPImpf Jus + ++ vp.obj.s + ++ vp.pred.s ! {g = Masc ; n = Pl} ! Acc + ++ vp.s2} ; -- ImpP3 : NP -> VP -> Utt ; -- let John walk diff --git a/src/arabic/NamesAra.gf b/src/arabic/NamesAra.gf index 958829dd..972bc936 100644 --- a/src/arabic/NamesAra.gf +++ b/src/arabic/NamesAra.gf @@ -11,6 +11,12 @@ lin FullName gn sn = emptyNP ** { lin UseLN ln = ln ; +lin AdjLN ap ln = ln ** { + s = \\c => ln.s ! c + ++ ap.s ! NoHum ! (pgn2gn ln.a.pgn).g + ! (pgn2gn ln.a.pgn).n ! Def ! c + } ; + lin PlainLN ln = ln ; lin InLN n = A.PrepNP S.in_Prep n ; ---- TODO: alternative prepositions diff --git a/src/arabic/NounAra.gf b/src/arabic/NounAra.gf index 6822fbab..6f7a80d7 100644 --- a/src/arabic/NounAra.gf +++ b/src/arabic/NounAra.gf @@ -75,6 +75,24 @@ lin }; -} + PartNP cn np = cn ** { + np = \\c => cn.np ! c ++ "مِنْ" ++ np.s ! Gen ; + isHeavy = True + } ; + + CountNP det np = emptyNP ** { + s = \\c => det.s ! NoHum ! Masc ! c ++ "مِنْ" ++ np.s ! Gen ; + a = {pgn = agrP3 NoHum Masc (sizeToNumber det.n) ; isPron = False} ; + isHeavy = True + } ; + + AdjDAP dap ap = dap ** { + s = \\h,g,c => dap.s ! h ! g ! c + ++ ap.s ! h ! g ! (sizeToNumber dap.n) ! dap.d ! c + } ; + + ExtAdvNP np adv = AdvNP np adv ; + AdvNP np adv = np ** { s = \\c => np.s ! c ++ adv.s ; isHeavy = True ; diff --git a/src/arabic/NumeralAra.gf b/src/arabic/NumeralAra.gf index 2de4439c..476d2a0a 100644 --- a/src/arabic/NumeralAra.gf +++ b/src/arabic/NumeralAra.gf @@ -105,6 +105,46 @@ lincat -- s = \\c => n.s ! NCard ++ "تهُْسَند" ++ m.s ! c ; n = Pl} ; lin pot3as4 n = n ; + +-- Arabic treats the scale nouns as ordinary masculine count nouns: the +-- numeral therefore has feminine polarity with 3--10 (ثلاثة ملايين), while +-- one million is conventionally written without an overt "one". +lin pot41 = { + s = \\co,_,d,c => case co of { + NCard => defArt d c "مِلْيُون" ; + NOrd => defArt d c "مِلْيُونِيّ" + } ; + n = One + } ; + +lin pot4 m = { + s = \\co,_,d,c => case m.n of { + One => defArt d c "مِلْيُون" ; + Two => m.s ! co ! Fem ! d ! c ++ "مِلْيُون" ; + ThreeTen => m.s ! co ! Fem ! d ! c ++ "مَلَايِين" ; + _ => m.s ! co ! Fem ! d ! c ++ "مِلْيُون" + } ; + n = m.n + } ; + +lin pot51 = { + s = \\co,_,d,c => case co of { + NCard => defArt d c "مِلْيَار" ; + NOrd => defArt d c "مِلْيَارِيّ" + } ; + n = One + } ; + +lin pot5 m = { + s = \\co,_,d,c => case m.n of { + One => defArt d c "مِلْيَار" ; + Two => m.s ! co ! Fem ! d ! c ++ "مِلْيَار" ; + ThreeTen => m.s ! co ! Fem ! d ! c ++ "مِلْيَارَات" ; + _ => m.s ! co ! Fem ! d ! c ++ "مِلْيَار" + } ; + n = m.n + } ; + lin pot4as5 n = n ; -- numerals as sequences of digits diff --git a/src/arabic/ParadigmsAra.gf b/src/arabic/ParadigmsAra.gf index b5cf1340..6bb80ea5 100644 --- a/src/arabic/ParadigmsAra.gf +++ b/src/arabic/ParadigmsAra.gf @@ -907,10 +907,6 @@ param VerbForm = FormI | FormII | FormIII | FormIV | FormV | FormVI | FormVII | FormVIII | FormX | FormXI ; - --- paradigms for Wiktionary extraction ----- TODO: better usage of information in Wiktionary - oper wmkN = overload { wmkN : {sg, pl : Str ; g : Gender} -> N @@ -1001,4 +997,11 @@ oper = \r -> variants {} ; ---- mkV r.imperfect ; -- expects cls I } ; + invarCard : Str -> Size -> NumOrdCard = \s,n -> { + s = \\_,_,_ => s ; n = n ; isNum = False + } ; + invarQuant : Str -> State -> Quant = \s,d -> lin Quant baseQuant ** { + s = \\_,_,_,_ => s ; d = d + } ; + } ; diff --git a/src/arabic/PhraseAra.gf b/src/arabic/PhraseAra.gf index 138ab57c..bbc01f01 100644 --- a/src/arabic/PhraseAra.gf +++ b/src/arabic/PhraseAra.gf @@ -22,6 +22,8 @@ concrete PhraseAra of Phrase = CatAra ** open UttS s = {s = \\_ => s.s ! Verbal} ; UttAdv, UttIAdv = \s -> {s = \\_ => s.s} ; ---- OK? AR + + VocNP np = {s = "يَا" ++ np.s ! Nom} ; -- NoPConj = {s = []} ; -- PConjConj conj = conj ; diff --git a/src/arabic/ResAra.gf b/src/arabic/ResAra.gf index 28443474..375dea65 100644 --- a/src/arabic/ResAra.gf +++ b/src/arabic/ResAra.gf @@ -465,8 +465,11 @@ oper param VPForm = VPPerf + | VPPassPerf | VPImpf Mood + | VPPassImpf Mood | VPImp + | VPPPart | VPGer ; VType = -- indicates if there is a predicate (xabar): @@ -500,8 +503,11 @@ oper let gn = pgn2gn pgn in case vf of { VPPerf => v.s ! VPerf Act pgn ; + VPPassPerf => v.s ! VPerf Pas pgn ; VPImpf m => v.s ! VImpf m Act pgn ; + VPPassImpf m => v.s ! VImpf m Pas pgn ; VPImp => v.s ! VImp gn.g gn.n ; + VPPPart => v.s ! VPPart ; VPGer => v.s ! Masdar }; sc = noPrep ; @@ -515,8 +521,8 @@ oper let actVP = predV v in actVP ** { s = \\pgn,vf => case vf of { - VPPerf => v.s ! VPerf Pas pgn ; - VPImpf m => v.s ! VImpf m Pas pgn ; + VPPerf => actVP.s ! pgn ! VPPassPerf ; + VPImpf m => actVP.s ! pgn ! VPPassImpf m ; _ => actVP.s ! pgn ! vf } }; diff --git a/src/arabic/SentenceAra.gf b/src/arabic/SentenceAra.gf index ad64b05c..26f22f21 100644 --- a/src/arabic/SentenceAra.gf +++ b/src/arabic/SentenceAra.gf @@ -15,6 +15,8 @@ concrete SentenceAra of Sentence = CatAra ** open PredVP = predVP ; + PredSCVP sc vp = predVP (indeclNP sc.s ResAra.Sg) vp ; + ImpVP vp = { s = \\p,g,n => case p of { @@ -37,8 +39,15 @@ concrete SentenceAra of Sentence = CatAra ** open SlashVP = predVPSlash ; AdvSlash slash adv = slash ** { s2 = slash.s2 ++ adv.s } ; + AdvImp adv imp = {s = \\p,g,n => adv.s ++ imp.s ! p ! g ! n} ; + -- : Cl -> Prep -> ClSlash --- SlashPrep cl prep = TODO + SlashPrep cl prep = (predV copula) ** { + s = \\_,_ => cl.s ! Pres ! Pos ! Verbal ; + c2 = prep ; + agrObj = \\_ => [] ; + subj = np2subj emptyNP + } ; -- SlashVS np vs sslash = TODO @@ -72,4 +81,8 @@ concrete SentenceAra of Sentence = CatAra ** open AdvS adv s = s ** {s = \\o => adv.s ++ s.s ! o} ; ExtAdvS adv s = s ** {s = \\o => adv.s ++ s.s ! o} ; + + SSubjS s1 subj s2 = { + s = \\o => s1.s ! o ++ SOFT_BIND ++ "," ++ subj.s ++ s2.s ! subj.o + } ; } diff --git a/src/arabic/VerbAra.gf b/src/arabic/VerbAra.gf index 27ff4690..d2d749e1 100644 --- a/src/arabic/VerbAra.gf +++ b/src/arabic/VerbAra.gf @@ -43,6 +43,10 @@ concrete VerbAra of Verb = CatAra ** open Prelude, ResAra, ParamX in { } ; SlashV2a = slashV2 ; + + -- The adjective is a secondary predicate of the missing object. + -- Keeping it in `pred` lets ComplSlash supply the agreement features. + SlashV2A v ap = slashV2 v ** {pred = CompAP ap} ; Slash2V3 v np = insertObj np (slashV2 v) ** {c2 = v.c3 ; agrObj = \\_ => []}; Slash3V3 v np = @@ -108,6 +112,10 @@ concrete VerbAra of Verb = CatAra ** open Prelude, ResAra, ParamX in { AdVVP adv = insertStr adv.s ; AdVVPSlash adv vps = vps ** insertStr adv.s vps ; + AdvVPSlash vps adv = vps ** insertStr adv.s vps ; + + ExtAdvVP vp adv = insertStr adv.s vp ; + -- : VPSlash -> VP ; -- love himself ReflVP vps = vps ** { s = \\pgn,vf => vps.s ! pgn ! vf