gf-3.4: lib/src/maltese/ParadigmsMlt.gf
-- ParadigmsMlt.gf: morphological paradigms
--
-- Maltese Resource Grammar Library
-- John J. Camilleri, 2012
-- Licensed under LGPL
--# -path=.:../abstract:../../prelude:../common
resource ParadigmsMlt = open
Predef,
Prelude,
MorphoMlt,
ResMlt,
CatMlt
in {
flags
optimize=noexpand ;
coding=utf8 ;
oper
{- Parameters --------------------------------------------------------- -}
-- Abstraction over gender names
Gender : Type ;
masculine : Gender ; --%
feminine : Gender ; --%
Gender = ResMlt.Gender ;
masculine = Masc ;
feminine = Fem ;
singular : Number = Sg ;
plural : Number = Pl ;
{- Noun paradigms ----------------------------------------------------- -}
-- Helper function for inferring noun plural from singulative
-- Nouns with collective & determinate forms should not use this...
inferNounPlural : Str -> Str = \sing ->
case sing of {
_ + "na" => init sing + "iet" ; -- eg WIDNIET
_ + "i" => sing + "n" ; -- eg BAĦRIN, DĦULIN, RAĦLIN
_ + ("a"|"u") => init(sing) + "i" ; -- eg ROTI
_ + "q" => sing + "at" ; -- eg TRIQAT
_ => sing + "i"
} ;
-- Helper function for inferring noun gender from singulative
-- Refer {MDG pg190}
inferNounGender : Str -> Gender = \sing ->
case sing of {
_ + "aġni" => Fem ;
_ + "anti" => Fem ;
_ + "zzjoni" => Fem ;
_ + "ġenesi" => Fem ;
_ + "ite" => Fem ;
_ + "itù" => Fem ;
_ + "joni" => Fem ;
_ + "ojde" => Fem ;
_ + "udni" => Fem ;
_ + ("a"|"à") => Fem ;
_ => Masc
} ;
-- Smart paradigm for building a noun
mkN : N = overload {
-- Take the singular and infer gender & plural.
-- Assume no special plural forms.
-- Params:
-- Singular, eg AJRUPLAN
mkN : Str -> N = \sing ->
let
plural = inferNounPlural sing ;
gender = inferNounGender sing ;
in
mk5N sing [] [] plural [] gender ;
-- Take an explicit gender.
-- Assume no special plural forms.
-- Params:
-- Singular, eg AJRUPLAN
-- Gender
mkN : Str -> Gender -> N = \sing,gender ->
let
plural = inferNounPlural sing ;
in
mk5N sing [] [] plural [] gender ;
-- Take the singular, plural. Infer gender.
-- Assume no special plural forms.
-- Params:
-- Singular, eg KTIEB
-- Plural, eg KOTBA
mkN : Str -> Str -> N = \sing,plural ->
let
gender = inferNounGender sing ;
in
mk5N sing [] [] plural [] gender ;
-- Take the singular, plural and gender.
-- Assume no special plural forms.
-- Params:
-- Singular, eg KTIEB
-- Plural, eg KOTBA
-- Gender
mkN : Str -> Str -> Gender -> N = \sing,plural,gender ->
mk5N sing [] [] plural [] gender ;
-- Takes all 5 forms, inferring gender
-- Params:
-- Singulative, eg KOXXA
-- Collective, eg KOXXOX
-- Double, eg KOXXTEJN
-- Determinate Plural, eg KOXXIET
-- Indeterminate Plural
mkN : Str -> Str -> Str -> Str -> Str -> N = \sing,coll,dual,det,ind ->
let
gender = if_then_else (Gender) (isNil sing) (inferNounGender coll) (inferNounGender sing) ;
in
mk5N sing coll dual det ind gender ;
} ; --end of mkN overload
-- Take the singular and infer gender.
-- No other plural forms.
-- Params:
-- Singular, eg ARTI
mkNNoPlural : N = overload {
mkNNoPlural : Str -> N = \sing ->
let gender = inferNounGender sing ;
in mk5N sing [] [] [] [] gender
;
mkNNoPlural : Str -> Gender -> N = \sing,gender ->
mk5N sing [] [] [] [] gender
;
} ; --end of mkNNoPlural overload
-- Take the singular and infer dual, plural & gender
-- Params:
-- Singular, eg AJRUPLAN
mkNDual : Str -> N = \sing ->
let
dual : Str = case sing of {
_ + ("għ"|"'") => sing + "ajn" ;
_ + ("a") => init(sing) + "ejn" ;
_ => sing + "ejn"
} ;
plural = inferNounPlural sing ;
gender = inferNounGender sing ;
in
mk5N sing [] dual plural [] gender ;
-- Take the collective, and infer singulative, determinate plural, and gender.
-- Params:
-- Collective Plural, eg TUFFIEĦ
mkNColl : Str -> N = \coll ->
let
stem : Str = case coll of {
-- This can only apply when there are 2 syllables in the word
_ + #Vowel + #Consonant + #Vowel + K@#Consonant => dropSfx 2 coll + K ; -- eg GĦADAM -> GĦADM-
_ => coll
} ;
sing : Str = case stem of {
_ => stem + "a"
} ;
det : Str = case stem of {
_ => stem + "iet"
} ;
-- gender = inferNounGender sing ;
gender = Masc ; -- Collective noun is always treated as Masculine
in
mk5N sing coll [] det [] gender ;
-- Build a noun using 5 forms, and a gender
mk5N : (_,_,_,_,_ : Str) -> Gender -> N ;
mk5N = \sing,coll,dual,det,ind,gen -> lin N (mkNoun sing coll dual det ind gen) ;
-- Make a proper noun
mkPN : Str -> Gender -> Number -> ProperNoun = \name,g,n -> {
s = name ;
a = mkAgr g n P3 ;
} ;
{-
-- Correctly abbreviate definite prepositions and join with noun
-- Params:
-- preposition (eg TAL, MAL, BĦALL)
-- noun
abbrevPrepositionDef : Str -> Str -> Str = \prep,noun ->
let
-- Remove either 1 or 2 l's
prepStem : Str = case prep of {
_ + "ll" => dropSfx 2 prep ;
_ + "l" => dropSfx 1 prep ;
_ => prep -- this should never happen, I don't think
}
in
case noun of {
("s"|#LiquidCons) + #Consonant + _ => prep + "-i" + noun ;
("għ" | #Vowel) + _ => case prep of {
("fil"|"bil") => (takePfx 1 prep) + "l-" + noun ;
_ => prep + "-" + noun
};
K@#CoronalConsonant + _ => prepStem + K + "-" + noun ;
#Consonant + _ => prep + "-" + noun ;
_ => []
} ;
-}
-- Correctly abbreviate indefinite prepositions and join with noun
-- Params:
-- preposition (eg TA', MA', BĦAL)
-- noun
abbrevPrepositionIndef : Str -> Str -> Str = \prep,noun ->
let
initPrepLetter = takePfx 1 prep ;
initNounLetter = takePfx 1 noun
in
if_then_Str (isNil noun) [] (
case prep of {
-- TA', MA', SA
_ + ("a'"|"a") =>
case noun of {
#Vowel + _ => initPrepLetter + "'" + noun ;
("għ" | "h") + #Vowel + _ => initPrepLetter + "'" + noun ;
_ => prep ++ noun
} ;
-- FI, BI
_ + "i" =>
if_then_Str (pbool2bool (eqStr initPrepLetter initNounLetter))
(prep ++ noun)
(case noun of {
-- initPrepLetter + _ => prep ++ noun ;
#Vowel + _ => initPrepLetter + "'" + noun ;
#Consonant + #Vowel + _ => initPrepLetter + "'" + noun ;
#Consonant + "r" + #Vowel + _ => initPrepLetter + "'" + noun ;
_ => prep ++ noun
}) ;
-- Else leave untouched
_ => prep ++ noun
});
mkN2 = overload {
mkN2 : N -> Prep -> N2 = prepN2 ;
mkN2 : N -> Str -> N2 = \n,s -> prepN2 n (mkPrep s);
-- mkN2 : Str -> Str -> N2 = \n,s -> prepN2 (regN n) (mkPrep s);
mkN2 : N -> N2 = \n -> prepN2 n (mkPrep "ta'") ;
-- mkN2 : Str -> N2 = \s -> prepN2 (regN s) (mkPrep "ta'")
} ;
prepN2 : N -> Prep -> N2 ;
prepN2 = \n,p -> lin N2 (n ** {c2 = p.s}) ;
mkPrep : Str -> Prep ; -- e.g. "in front of"
noPrep : Prep ; -- no preposition
mkPrep p = lin Prep (ss p) ;
noPrep = mkPrep [] ;
{- Verb paradigms ----------------------------------------------------- -}
-- Re-export ResMlt.mkRoot
mkRoot : Root = overload {
mkRoot : Root = ResMlt.mkRoot ;
mkRoot : Str -> Root = \s0 -> ResMlt.mkRoot s0 ;
mkRoot : Str -> Str -> Str -> Root = \s0,s1,s2 -> ResMlt.mkRoot s0 s1 s2 ;
mkRoot : Str -> Str -> Str -> Str -> Root = \s0,s1,s2,s3 -> ResMlt.mkRoot s0 s1 s2 s3 ;
} ;
-- Re-export ResMlt.mkPattern
mkPattern : Pattern = overload {
mkPattern : Pattern = ResMlt.mkPattern ;
mkPattern : Str -> Pattern = \s0 -> ResMlt.mkPattern s0 ;
mkPattern : Str -> Str -> Pattern = \s0,s1 -> ResMlt.mkPattern s0 s1 ;
} ;
-- Return the class for a given root
classifyRoot : Root -> VClass = \r ->
case <r.C1,r.C2,r.C3,r.C4> of {
<#WeakCons, #StrongCons, #StrongCons, ""> => Weak Assimilative ;
<#StrongCons, #WeakCons, #StrongCons, ""> => Weak Hollow ;
<#StrongCons, #StrongCons, #WeakCons, ""> => Weak Lacking ;
<#StrongCons, #WeakCons, #WeakCons, ""> => Weak Lacking ;
<#Consonant, #Consonant, "għ", ""> => Weak Defective ;
<#Consonant, c2@#Consonant, c3@#Consonant, ""> =>
if_then_else VClass (pbool2bool (eqStr c2 c3))
(Strong Geminated)
(case c2 of {
#LiquidCons => Strong LiquidMedial ;
_ => Strong Regular
}) ;
<#Consonant, #Consonant, #Consonant, #WeakCons> => Quad QWeak ;
<#Consonant, #Consonant, #Consonant, #Consonant> => Quad QStrong ;
-- Irregular
<"'",_,_,_> => Irregular ;
<_,"'",_,_> => Irregular ;
<_,_,"'",_> => Irregular ;
<_,_,_,"'"> => Irregular ;
<_,_,_,""> => Predef.error("Cannot classify root:"++r.C1+"-"+r.C2+"-"+r.C3) ;
<_,_,_,_> => Predef.error("Cannot classify root:"++r.C1+"-"+r.C2+"-"+r.C3+"-"+r.C4)
} ;
-- Just get the non-suffixed forms of a verb, for quick testing
-- plainVerbTable : V -> (VForm => Str) = \v ->
-- \\tense => v.s ! tense ! VSuffixNone ! Pos ;
-- Smart paradigm for building a verb
mkV : V = overload {
-- With no root, automatically treat as loan verb
-- Params: mamma
mkV : Str -> V = loanV ;
-- Take an explicit root, implying it is a root & pattern verb
-- Params: mamma, root
mkV : Str -> Root -> V = \mamma,root ->
let
class : VClass = classifyRoot root ;
patt : Pattern = extractPattern mamma ;
in
case class of {
Strong Regular => strongV root patt ;
Strong LiquidMedial => liquidMedialV root patt ;
Strong Geminated => geminatedV root patt ;
Weak Assimilative => assimilativeV root patt ;
Weak Hollow => hollowV root patt ;
Weak Lacking => lackingV root patt ;
Weak Defective => defectiveV root patt ;
Quad QStrong => quadV root patt ;
Quad QWeak => quadWeakV root patt ;
Irregular => Predef.error("Cannot use smart paradigm for irregular verb:"++mamma) ;
Loan => loanV mamma --- this should probably be an error
} ;
-- Takes takes an Imperative of the word for when it behaves less predictably
-- Params: mamma, imperative P2Sg, root
mkV : Str -> Str -> Root -> V = \mamma,imp_sg,root ->
let
class : VClass = classifyRoot root ;
patt : Pattern = extractPattern mamma ;
in
case class of {
Strong Regular => strongV root patt imp_sg ;
Strong LiquidMedial => liquidMedialV root patt imp_sg ;
Strong Geminated => geminatedV root patt imp_sg ;
Weak Assimilative => assimilativeV root patt imp_sg ;
Weak Hollow => hollowV root patt imp_sg ;
Weak Lacking => lackingV root patt imp_sg ;
Weak Defective => defectiveV root patt imp_sg ;
Quad QStrong => quadV root patt imp_sg ;
Quad QWeak => quadWeakV root patt imp_sg ;
Irregular => Predef.error("Cannot use smart paradigm for irregular verb:"++mamma) ;
Loan => loanV mamma
} ;
-- All forms! :S
-- mkV (Strong Regular) (FormI) (mkRoot "k-t-b") (mkPattern "i" "e") "ktibt" "ktibt" "kiteb" "kitbet" "ktibna" "ktibtu" "kitbu" "nikteb" "tikteb" "jikteb" "tikteb" "niktbu" "tiktbu" "jiktbu" "ikteb" "iktbu"
mkV : VClass -> VDerivedForm -> Root -> Pattern -> (_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ : Str) -> V =
\class, form, root, patt,
perfP1Sg, perfP2Sg, perfP3SgMasc, perfP3SgFem, perfP1Pl, perfP2Pl, perfP3Pl,
impfP1Sg, impfP2Sg, impfP3SgMasc, impfP3SgFem, impfP1Pl, impfP2Pl, impfP3Pl,
impSg, impPl ->
let
tbl : (VForm => Str) = table {
VPerf (AgP1 Sg) => perfP1Sg ;
VPerf (AgP2 Sg) => perfP2Sg ;
VPerf (AgP3Sg Masc) => perfP3SgMasc ;
VPerf (AgP3Sg Fem) => perfP3SgFem ;
VPerf (AgP1 Pl) => perfP1Pl ;
VPerf (AgP2 Pl) => perfP2Pl ;
VPerf (AgP3Pl) => perfP3Pl ;
VImpf (AgP1 Sg) => impfP1Sg ;
VImpf (AgP2 Sg) => impfP2Sg ;
VImpf (AgP3Sg Masc) => impfP3SgMasc ;
VImpf (AgP3Sg Fem) => impfP3SgFem ;
VImpf (AgP1 Pl) => impfP1Pl ;
VImpf (AgP2 Pl) => impfP2Pl ;
VImpf (AgP3Pl) => impfP3Pl ;
VImp (Pl) => impSg ;
VImp (Sg) => impPl
} ;
info : VerbInfo = mkVerbInfo class form root patt impSg ;
in lin V {
s = tbl ;
i = info ;
} ;
} ; --end of mkV overload
-- Some shortcut function names (haven't decided on naming yet)
mkV_II = overload {
mkV_II : Str -> Root -> V = \s,r -> derivedV_II s r ;
mkV_II : Str -> Str -> Root -> V = \s,i,r -> derivedV_II s i r ;
} ;
mkV_III : Str -> Root -> V = \s,r -> derivedV_III s r ;
mkV_V : Str -> Root -> V = \s,r -> derivedV_V s r ;
mkV_VI : Str -> Root -> V = \s,r -> derivedV_VI s r ;
mkV_VII : Str -> Str -> Root -> V = \s,t,r -> derivedV_VII s t r ;
mkV_VIII : Str -> Root -> V = \s,r -> derivedV_VIII s r ;
mkV_IX : Str -> Root -> V = \s,r -> derivedV_IX s r ;
mkV_X : Str -> Root -> V = \s,r -> derivedV_X s r ;
derivedV_I : Str -> Root -> V = mkV ;
-- Make a Form II verb. Accepts both Tri & Quad roots, then delegates.
derivedV_II : V = overload {
-- e.g.: derivedV_II "waqqaf" (mkRoot "w-q-f")
derivedV_II : Str -> Root -> V = \mammaII, root ->
case root.C4 of {
"" => derivedV_TriII mammaII root ;
_ => derivedV_QuadII mammaII root
} ;
-- e.g.: derivedV_II "waqqaf" "waqqaf" (mkRoot "w-q-f")
derivedV_II : Str -> Str -> Root -> V = \mammaII, imp, root ->
case root.C4 of {
"" => derivedV_TriII mammaII root ;
_ => derivedV_QuadII mammaII imp root
} ;
} ;
-- Make a Tri-Consonantal Form II verb
derivedV_TriII : Str -> Root -> V = \mammaII, root ->
let
class : VClass = classifyRoot root ;
patt : Pattern = extractPattern mammaII ;
imp : Str = case mammaII of {
nehh + "a" => nehh + "i" ; --- maybe too generic?
_ => mammaII --- assumption: mamma II is also imperative
} ;
newinfo : VerbInfo = mkVerbInfo class FormII root patt imp ;
in lin V {
s = conjFormII newinfo ;
i = newinfo ;
} ;
-- Make a Quadri-Consonantal Form II verb
derivedV_QuadII : V = overload {
derivedV_QuadII : Str -> Root -> V = \mammaII, root ->
let
class : VClass = classifyRoot root ;
patt : Pattern = extractPattern mammaII ;
imp : Str = mammaII ; --- assumption: mamma II is also imperative
newinfo : VerbInfo = mkVerbInfo class FormII root patt imp ;
in lin V {
s = conjFormII_quad newinfo ;
i = newinfo ;
} ;
derivedV_QuadII : Str -> Str -> Root -> V = \mammaII, imp, root ->
let
class : VClass = classifyRoot root ;
patt : Pattern = extractPattern mammaII ;
newinfo : VerbInfo = mkVerbInfo class FormII root patt imp ;
in lin V {
s = conjFormII_quad newinfo ;
i = newinfo ;
} ;
} ;
-- Make a Form III verb
-- e.g.: derivedV_III "qiegħed" (mkRoot "q-għ-d")
derivedV_III : Str -> Root -> V = \mammaIII, root ->
let
vowels : Pattern = extractPattern mammaIII ;
vowels2 : Pattern = vowelChangesIE root vowels ;
class : VClass = classifyRoot root ;
info : VerbInfo = mkVerbInfo class FormIII root vowels vowels2 mammaIII ; --- assumption: mamma III is also imperative
in lin V {
s = conjFormIII info ;
i = info ;
} ;
-- No point having a paradigm for Form IV
-- derivedV_IV
-- Make a Form V verb
-- e.g.: derivedV_V "twaqqaf" (mkRoot "w-q-f")
derivedV_V : Str -> Root -> V = \mammaV, root ->
let
-- use the Form II conjugation, just prefixing a T
mammaII : Str = dropPfx 1 mammaV ; -- WAQQAF
vII : V = derivedV_II mammaII root ;
info : VerbInfo = mkVerbInfo vII.i.class FormV vII.i.root vII.i.patt mammaV ;
in lin V {
s = table {
VPerf agr => pfx_T (vII.s ! VPerf agr) ;
VImpf (AgP1 Sg) => pfx "ni" (pfx_T (dropPfx 1 (vII.s ! VImpf (AgP1 Sg)))) ;
VImpf (AgP2 Sg) => pfx "ti" (pfx_T (dropPfx 1 (vII.s ! VImpf (AgP2 Sg)))) ;
VImpf (AgP3Sg Masc) => pfx "ji" (pfx_T (dropPfx 1 (vII.s ! VImpf (AgP3Sg Masc)))) ;
VImpf (AgP3Sg Fem) => pfx "ti" (pfx_T (dropPfx 1 (vII.s ! VImpf (AgP3Sg Fem)))) ;
VImpf (AgP1 Pl) => pfx "ni" (pfx_T (dropPfx 1 (vII.s ! VImpf (AgP1 Pl)))) ;
VImpf (AgP2 Pl) => pfx "ti" (pfx_T (dropPfx 1 (vII.s ! VImpf (AgP2 Pl)))) ;
VImpf (AgP3Pl) => pfx "ji" (pfx_T (dropPfx 1 (vII.s ! VImpf (AgP3Pl)))) ;
VImp num => pfx_T (vII.s ! VImp num)
} ;
i = info ;
} ;
-- Make a Form VI verb
-- e.g.: derivedV_VI "tqiegħed" (mkRoot "q-għ-d")
derivedV_VI : Str -> Root -> V = \mammaVI, root ->
let
-- use the Form III conjugation, just prefixing a T
mammaIII : Str = dropPfx 1 mammaVI ; -- QIEGĦED
vIII : V = derivedV_III mammaIII root ;
info : VerbInfo = updateVerbInfo vIII.i FormVI mammaVI ;
in lin V {
s = table {
VPerf agr => pfx_T (vIII.s ! VPerf agr) ;
VImpf (AgP1 Sg) => pfx "ni" (pfx_T (dropPfx 1 (vIII.s ! VImpf (AgP1 Sg)))) ;
VImpf (AgP2 Sg) => pfx "ti" (pfx_T (dropPfx 1 (vIII.s ! VImpf (AgP2 Sg)))) ;
VImpf (AgP3Sg Masc) => pfx "ji" (pfx_T (dropPfx 1 (vIII.s ! VImpf (AgP3Sg Masc)))) ;
VImpf (AgP3Sg Fem) => pfx "ti" (pfx_T (dropPfx 1 (vIII.s ! VImpf (AgP3Sg Fem)))) ;
VImpf (AgP1 Pl) => pfx "ni" (pfx_T (dropPfx 1 (vIII.s ! VImpf (AgP1 Pl)))) ;
VImpf (AgP2 Pl) => pfx "ti" (pfx_T (dropPfx 1 (vIII.s ! VImpf (AgP2 Pl)))) ;
VImpf (AgP3Pl) => pfx "ji" (pfx_T (dropPfx 1 (vIII.s ! VImpf (AgP3Pl)))) ;
VImp num => pfx_T (vIII.s ! VImp num)
} ;
i = info ;
} ;
-- Make a Form VII verb
-- e.g.: derivedV_VII "xeħet" "nxteħet" (mkRoot "x-ħ-t")
derivedV_VII : Str -> Str -> Root -> V = \mammaI, mammaVII, root ->
let
class : VClass = classifyRoot root ;
vowels : Pattern = extractPattern mammaI ;
c1 : Str = case mammaVII of {
"n" + c@#Cns + "t" + _ => "n"+c+"t" ; -- NXT-EĦET
"ntgħ" + _ => "ntgħ" ; -- NTGĦ-AĠEN
"nt" + c@#Cns + _ => "nt"+c ; -- NTR-IFES
"nt" + #Vowel + _ => "nt" ; -- NT-IŻEN
"n" + c@#Cns + _ => "n"+c ; -- NĦ-ASEL
_ => "nt" --- unknown case
} ;
info : VerbInfo = mkVerbInfo class FormVII root vowels mammaVII ;
in lin V {
s = conjFormVII info c1 ;
i = info ;
} ;
-- Make a Form VIII verb
-- e.g.: derivedV_VIII "xteħet" (mkRoot "x-ħ-t")
derivedV_VIII : Str -> Root -> V = \mammaVIII, root ->
let
mammaI : Str = delCharAt 1 mammaVIII ;
class : VClass = classifyRoot root ;
vowels : Pattern = extractPattern mammaI ;
info : VerbInfo = mkVerbInfo class FormVIII root vowels mammaVIII ;
c1 : Str = root.C1+"t";
in lin V {
s = conjFormVII info c1 ; -- note we use conjFormVII !
i = info ;
} ;
-- Make a Form IX verb
-- e.g.: derivedV_IX "sfar"
derivedV_IX : Str -> Root -> V = \mammaIX, root ->
case mammaIX of {
-- c1@#Consonant + c2@#Consonant + v1@("ie"|"a") + c3@#Consonant =>
_ + v1@("ie"|"a"|"â") + _ =>
let
patt : Pattern = mkPattern v1 ;
class : VClass = classifyRoot root ;
info : VerbInfo = mkVerbInfo class FormIX root patt mammaIX ;
in lin V {
s = conjFormIX info ;
i = info ;
} ;
_ => Predef.error("I don't know how to make a Form IX verb out of" ++ mammaIX)
} ;
-- Make a Form X verb
-- e.g.: derivedV_X "stagħġeb" (mkRoot "għ-ġ-b")
derivedV_X : Str -> Root -> V = \mammaX, root ->
let
class : VClass = classifyRoot root ;
patt : Pattern = extractPattern mammaX ;
patt2 : Pattern = vowelChangesIE root patt ;
info : VerbInfo = mkVerbInfo class FormX root patt patt2 mammaX ;
in lin V {
s = conjFormX info ;
i = info ;
} ;
{- ~~~ Strong Verb ~~~ -}
-- Regular strong verb ("sħiħ"), eg KITEB
strongV : V = overload {
-- Params: root, pattern
strongV : Root -> Pattern -> V = \root,patt ->
let imp = conjStrongImp root patt
in strongVWorst root patt imp ;
-- Params: root, pattern, imperative P2Sg
strongV : Root -> Pattern -> Str -> V =\root,patt,imp_sg ->
let
imp = table {
Sg => imp_sg ;
Pl => (takePfx 3 imp_sg) + root.C3 + "u" -- IFTAĦ > IFTĦU
} ;
in strongVWorst root patt imp ;
} ;
-- Worst case for strong verb
strongVWorst : Root -> Pattern -> (Number => Str) -> V = \root,patt,imp ->
let
tbl : (VForm => Str) = table {
VPerf agr => ( conjStrongPerf root patt ) ! agr ;
VImpf agr => ( conjStrongImpf (imp ! Sg) (imp ! Pl) ) ! agr ;
VImp n => imp ! n
} ;
info : VerbInfo = mkVerbInfo (Strong Regular) (FormI) root patt (imp ! Sg) ;
in lin V {
s = tbl ;
i = info ;
} ;
{- ~~~ Liquid-Medial Verb ~~~ -}
-- Liquid-medial strong verb, eg ŻELAQ
liquidMedialV : V = overload {
-- Params: root, pattern
liquidMedialV : Root -> Pattern -> V = \root,patt ->
let imp = conjLiquidMedialImp root patt
in liquidMedialVWorst root patt imp ;
-- Params: root, pattern, imperative P2Sg
liquidMedialV : Root -> Pattern -> Str -> V = \root,patt,imp_sg ->
let
vowels = extractPattern imp_sg ;
imp = table {
Sg => imp_sg ;
Pl => case root.C1 of {
"għ" => vowels.V1 + root.C1 + root.C2 + root.C3 + "u" ; -- AGĦMEL > AGĦMLU
_ => vowels.V1 + root.C1 + vowels.V2 + root.C2 + root.C3 + "u" -- OĦROĠ > OĦORĠU
}
} ;
in liquidMedialVWorst root patt imp ;
} ;
-- Worst case for liquid medial strong verb
liquidMedialVWorst : Root -> Pattern -> (Number => Str) -> V = \root,patt,imp ->
let
tbl : (VForm => Str) = table {
VPerf agr => ( conjLiquidMedialPerf root patt ) ! agr ;
VImpf agr => ( conjLiquidMedialImpf (imp ! Sg) (imp ! Pl) ) ! agr ;
VImp n => imp ! n
} ;
info : VerbInfo = mkVerbInfo (Strong LiquidMedial) (FormI) root patt (imp ! Sg) ;
in lin V {
s = tbl ;
i = info ;
} ;
{- ~~~ Geminated Verb ~~~ -}
-- Geminated strong verb ("trux"), eg ĦABB
geminatedV : V = overload {
-- Params: root, pattern
geminatedV : Root -> Pattern -> V = \root,patt ->
let imp = conjGeminatedImp root patt
in geminatedVWorst root patt imp ;
-- Params: root, pattern, imperative P2Sg
geminatedV : Root -> Pattern -> Str -> V = \root,patt,imp_sg ->
let
imp = table {
Sg => imp_sg ;
Pl => imp_sg + "u" -- ŻOMM > ŻOMMU
} ;
in geminatedVWorst root patt imp ;
};
-- Worst case for reduplicated verb
geminatedVWorst : Root -> Pattern -> (Number => Str) -> V = \root,patt,imp ->
let
tbl : (VForm => Str) = table {
VPerf agr => ( conjGeminatedPerf root patt ) ! agr ;
VImpf agr => ( conjGeminatedImpf (imp ! Sg) (imp ! Pl) ) ! agr ;
VImp n => imp ! n
} ;
info : VerbInfo = mkVerbInfo (Strong Geminated) (FormI) root patt (imp ! Sg) ;
in lin V {
s = tbl ;
i = info ;
} ;
{- ~~~ Assimilative Verb ~~~ -}
-- Assimilative weak verb, eg WASAL
assimilativeV : V = overload {
-- Params: root, pattern
assimilativeV : Root -> Pattern -> V = \root,patt ->
let imp = conjAssimilativeImp root patt
in assimilativeVWorst root patt imp ;
-- Params: root, pattern, imperative P2Sg
assimilativeV : Root -> Pattern -> Str -> V =\root,patt,imp_sg ->
let
imp = table {
Sg => imp_sg ;
Pl => (dropSfx 2 imp_sg) + root.C3 + "u" -- ASAL > ASLU
} ;
in assimilativeVWorst root patt imp ;
} ;
-- Worst case for assimilative verb
assimilativeVWorst : Root -> Pattern -> (Number => Str) -> V = \root,patt,imp ->
let
tbl : (VForm => Str) = table {
VPerf agr => ( conjAssimilativePerf root patt ) ! agr ;
VImpf agr => ( conjAssimilativeImpf (imp ! Sg) (imp ! Pl) ) ! agr ;
VImp n => imp ! n
} ;
patt2 : Pattern = case (imp!Sg) of {
"ie"+_ => mkPattern "i" patt.V2 ; -- (WAQAF) IEQAF > TIQAFLI
_ => patt -- (WASAL) ASAL > TASALLI
} ;
info : VerbInfo = mkVerbInfo (Weak Assimilative) (FormI) root patt patt2 (imp ! Sg) ;
in lin V {
s = tbl ;
i = info ;
} ;
{- ~~~ Hollow Verb ~~~ -}
-- Hollow weak verb, eg SAR (S-J-R)
hollowV : V = overload {
-- Params: root, pattern
hollowV : Root -> Pattern -> V = \root,patt ->
let imp = conjHollowImp root patt
in hollowVWorst root patt imp ;
-- Params: root, pattern, imperative P2Sg
hollowV : Root -> Pattern -> Str -> V =\root,patt,imp_sg ->
let
imp = table {
Sg => imp_sg ;
Pl => imp_sg + "u" -- SIR > SIRU
} ;
in hollowVWorst root patt imp ;
} ;
-- Worst case for hollow verb
hollowVWorst : Root -> Pattern -> (Number => Str) -> V = \root,patt,imp ->
let
tbl : (VForm => Str) = table {
VPerf agr => ( conjHollowPerf root patt ) ! agr ;
VImpf agr => ( conjHollowImpf (imp ! Sg) (imp ! Pl) ) ! agr ;
VImp n => imp ! n
} ;
patt2 : Pattern = case patt.V1 of {
"ie" => mkPattern "i" patt.V2 ; -- (ŻIED) ŻID > ŻIDLI
_ => patt -- (MAR) MUR > MURLI
} ;
info : VerbInfo = mkVerbInfo (Weak Hollow) (FormI) root patt patt2 (imp ! Sg) ;
in lin V {
s = tbl ;
i = info ;
} ;
{- ~~~ Lacking Verb ~~~ -}
-- Lacking (nieqes) verb, eg MEXA (M-X-J)
lackingV : V = overload {
-- Params: root, pattern
lackingV : Root -> Pattern -> V = \root,patt ->
let imp = conjLackingImp root patt
in lackingVWorst root patt imp ;
-- Params: root, pattern, imperative P2Sg
lackingV : Root -> Pattern -> Str -> V =\root,patt,imp_sg ->
let
imp = table {
Sg => imp_sg ;
Pl => case imp_sg of {
aqr+"a" => aqr+"aw" ; -- AQRA > AQRAW
imx+"i" => imx+"u" ; -- IMXI > IMXU
x => (dropSfx 1 x) + "u" --- unknown case
}
} ;
in lackingVWorst root patt imp ;
} ;
-- Worst case for lacking verb
lackingVWorst : Root -> Pattern -> (Number => Str) -> V = \root,patt,imp ->
let
tbl : (VForm => Str) = table {
VPerf agr => ( conjLackingPerf root patt ) ! agr ;
VImpf agr => ( conjLackingImpf (imp ! Sg) (imp ! Pl) ) ! agr ;
VImp n => imp ! n
} ;
info : VerbInfo = mkVerbInfo (Weak Lacking) (FormI) root patt (imp ! Sg) ;
in lin V {
s = tbl ;
i = info ;
} ;
{- ~~~ Defective Verb ~~~ -}
-- Defective verb, eg QALA' (Q-L-GĦ)
defectiveV : V = overload {
-- Params: root, pattern
defectiveV : Root -> Pattern -> V = \root,patt ->
let imp = conjDefectiveImp root patt
in defectiveVWorst root patt imp ;
-- Params: root, pattern, imperative P2Sg
defectiveV : Root -> Pattern -> Str -> V =\root,patt,imp_sg ->
let
imp = table {
Sg => imp_sg ;
Pl => (takePfx 2 imp_sg) + "i" + root.C2 + "għu" -- ISMA' > ISIMGĦU
} ;
in defectiveVWorst root patt imp ;
} ;
-- Worst case for defective verb
defectiveVWorst : Root -> Pattern -> (Number => Str) -> V = \root,patt,imp ->
let
tbl : (VForm => Str) = table {
VPerf agr => ( conjDefectivePerf root patt ) ! agr ;
VImpf agr => ( conjDefectiveImpf (imp ! Sg) (imp ! Pl) ) ! agr ;
VImp n => imp ! n
} ;
info : VerbInfo = mkVerbInfo (Weak Defective) (FormI) root patt (imp ! Sg) ;
in lin V {
s = tbl ;
i = info ;
} ;
{- ~~~ Quadriliteral Verb (Strong) ~~~ -}
-- Make a Quad verb, eg DENDEL (D-L-D-L)
quadV : V = overload {
-- Params: root, pattern
quadV : Root -> Pattern -> V = \root,patt ->
let imp = conjQuadImp root patt
in quadVWorst root patt imp ;
-- Params: root, pattern, imperative P2Sg
quadV : Root -> Pattern -> Str -> V =\root,patt,imp_sg ->
let
imp = table {
Sg => imp_sg ;
Pl => (takePfx 4 imp_sg) + root.C4 + "u" -- ĦARBAT > ĦARBTU
} ;
in quadVWorst root patt imp ;
} ;
-- Worst case for quad verb
quadVWorst : Root -> Pattern -> (Number => Str) -> V = \root,patt,imp ->
let
tbl : (VForm => Str) = table {
VPerf agr => ( conjQuadPerf root patt ) ! agr ;
VImpf agr => ( conjQuadImpf (imp ! Sg) (imp ! Pl) ) ! agr ;
VImp n => imp ! n
} ;
info : VerbInfo = mkVerbInfo (Quad QStrong) (FormI) root patt (imp ! Sg) ;
in lin V {
s = tbl ;
i = info ;
} ;
{- ~~~ Quadriliteral Verb (Weak Final) ~~~ -}
-- Make a weak-final Quad verb, eg SERVA (S-R-V-J)
quadWeakV : V = overload {
-- Params: root, pattern
quadWeakV : Root -> Pattern -> V = \root,patt ->
let imp = conjQuadWeakImp root patt
in quadWeakVWorst root patt imp ;
-- Params: root, pattern, imperative P2Sg
quadWeakV : Root -> Pattern -> Str -> V =\root,patt,imp_sg ->
let
imp = table {
Sg => imp_sg ;
Pl => case (takeSfx 1 imp_sg) of {
"a" => imp_sg + "w" ; -- KANTA > KANTAW
_ => (dropSfx 1 imp_sg) + "u" -- SERVI > SERVU
}
} ;
in quadWeakVWorst root patt imp ;
} ;
-- Worst case for quadWeak verb
quadWeakVWorst : Root -> Pattern -> (Number => Str) -> V = \root,patt,imp ->
let
tbl : (VForm => Str) = table {
VPerf agr => ( conjQuadWeakPerf root patt (imp ! Sg) ) ! agr ;
VImpf agr => ( conjQuadWeakImpf (imp ! Sg) (imp ! Pl) ) ! agr ;
VImp n => imp ! n
} ;
info : VerbInfo = mkVerbInfo (Quad QWeak) (FormI) root patt (imp ! Sg) ;
in lin V {
s = tbl ;
i = info ;
} ;
{- ~~~ Non-semitic verbs ~~~ -}
-- Make a loan verb, eg IPPARKJA
-- Params: mamma
loanV : Str -> V = \mamma ->
let
imp = conjLoanImp mamma ;
tbl : (VForm => Str) = table {
VPerf agr => ( conjLoanPerf mamma ) ! agr ;
VImpf agr => ( conjLoanImpf (imp ! Sg) (imp ! Pl) ) ! agr ;
VImp n => imp ! n
} ;
info : VerbInfo = mkVerbInfo (Loan) (FormI) (imp ! Sg) ;
in lin V {
s = tbl ;
i = info ;
} ;
{- Adjective paradigms ------------------------------------------------ -}
-- Overloaded function for building an adjective
mkA : A = overload {
-- Same form for gender and number; no comparative form.
-- Params:
-- Adjective, eg BLU
mkA : Str -> A = sameA ;
-- Infer feminine from masculine; no comparative form.
-- Params:
-- Masculine, eg SABIĦ
-- Plural, eg SBIEĦ
mkA : Str -> Str -> A = brokenA ;
-- Infer feminine from masculine; no comparative form.
-- Params:
-- Masculine, eg SABIĦ
-- Feminine, eg SABIĦA
-- Plural, eg SBIEĦ
mkA : Str -> Str -> Str -> A = mk3A ;
-- Take all forms.
-- Params:
-- Masculine, eg SABIĦ
-- Feminine, eg SABIĦA
-- Plural, eg SBIEĦ
-- Comparative, eg ISBAĦ
mkA : Str -> Str -> Str -> Str -> A = mk4A ;
} ;
-- Regular adjective with predictable feminine and plural forms
regA : Str -> A ;
regA masc =
let
fem = determineAdjFem masc ;
plural = determineAdjPlural fem
in
mk3A masc fem plural ;
-- Adjective with same forms for masculine, feminine and plural.
sameA : Str -> A ;
sameA a = mk3A a a a ;
-- Adjective with predictable feminine but broken plural
brokenA = overload {
-- without comparative form
brokenA : Str -> Str -> A = \masc,plural ->
let
fem = determineAdjFem masc
in
mk3A masc fem plural ;
-- with comparative form
brokenA : Str -> Str -> Str -> A = \masc,plural,compar ->
let
fem = determineAdjFem masc
in
mk4A masc fem plural compar ;
} ;
-- Build an adjective noun using all 3 forms, when it has no comparative form
mk3A : (_,_,_ : Str) -> A ;
mk3A = \masc,fem,plural ->
lin A (mkAdjective masc fem plural []) ** {hasComp = False} ;
-- Build an adjective noun using all 4 forms (superlative is trivial)
mk4A : (_,_,_,_ : Str) -> A ;
mk4A = \masc,fem,plural,compar ->
lin A (mkAdjective masc fem plural compar) ** {hasComp = True} ;
-- Determine femininine form of adjective from masculine
determineAdjFem : Str -> Str ;
determineAdjFem masc = case masc of {
_ + "ef" => (dropSfx 2 masc) + "fa" ; -- NIEXEF
_ + "u" => (init masc) + "a" ; -- BRAVU
_ + "i" => masc + "ja" ; -- MIMLI
_ => masc + "a" -- VOJT
} ;
-- Determine plural form of adjective from feminine
determineAdjPlural : Str -> Str ;
determineAdjPlural fem = case fem of {
_ + ("f"|"j"|"ġ") + "a" => (init fem) + "in" ; -- NIEXFA, MIMLIJA, MAĦMUĠA
_ => (init fem) + "i" -- BRAVA
} ;
}