--# -path=.:../abstract:../../prelude:../common --1 Arabic Lexical Paradigms -- -- Ali El Dada 2005--2006 -- Inari Listenmaa 2018- -- -- This is an API to the user of the resource grammar -- for adding lexical items. It gives functions for forming -- expressions of open categories: nouns, adjectives, verbs. -- -- Closed categories (determiners, pronouns, conjunctions) are -- accessed through the resource syntax API, $Structural.gf$. -- -- The main difference with $MorphoAra.gf$ is that the types -- referred to are compiled resource grammar types. We have moreover -- had the design principle of always having existing forms, rather -- than stems, as string arguments of the paradigms. -- -- The structure of functions for each word class $C$ is the following: -- first we give a handful of patterns that aim to cover all -- regular cases. Then we give a worst-case function $mkC$, which serves as an -- escape to construct the most irregular words of type $C$. -- -- The following modules are presupposed: resource ParadigmsAra = open Predef, Prelude, ResAra, OrthoAra, (A=AdjectiveAra), CatAra in { flags optimize = noexpand; coding=utf8 ; oper Case : Type ; -- Argument to mkPrep nom : Case ; -- Nominative acc : Case ; -- Accusative gen : Case ; -- Genitive Gender : Type ; -- Argument to mkN and mkPN masc : Gender ; -- Masculine fem : Gender ; -- Feminine Number : Type ; -- Argument to mkConj ("NP and NP" plural; "NP or NP" singular), and special cases of mkN, where nominal attribute is included in the N. sg : Number ; -- Singular pl : Number ; -- Plural Species : Type ; -- Argument to mkN. hum : Species ; -- Human nouns (teacher, woman, brother, …) nohum : Species ; -- Any other nouns (house, dog, …) Vowel : Type ; -- Argument to mkV, when constructing verbs of Form I. va : Vowel ; -- a (fatha) as the perfect or imperfect vowel, e.g. فعَل vi : Vowel ; -- i (kasra) as the perfect or imperfect vowel, e.g فعِل vu : Vowel ; -- u (damma) as the perfect or imperfect vowel, e.g. فعُل --2 Nouns -- Overloaded operator for main cases mkN : overload { mkN : (sg : Str) -> N ; -- Takes the singular without case marking, gives a non-human regular noun. Plural is sound feminine if the word ends in ة, otherwise sound masculine. mkN : (sg,pl : Str) -> Gender -> Species -> N ; -- Takes the singular and the plural (sound or broken) forms without case marking, returns a noun with basic triptote declension. NB for irregular/weak roots, safer to use brkN, sdfN or sdmN, which take root and pattern. mkN : (root,sgPat,plPat : Str) -> Gender -> Species -> N ; -- (This is brkN; see its description.) mkN : Species -> N -> N ; -- Change species (hum/nohum) of a noun. mkN : N -> (attr : Str) -> N ; -- Compound noun with invariant attribute. mkN : N -> N -> N ; -- Compound noun with singular genitive attribute, but inflects in state. mkN : Number -> N -> N -> N ; -- Compound noun with genitive attribute, but inflects in state. Attribute's number specified by 1st arg. } ; brkN : (root,sgPat,brokenPlPat : Str) -> Gender -> Species -> N ; -- Takes a root string, a singular pattern string, a broken plural pattern string, a gender, and species. Gives a noun. (This is also overloaded as mkN.) sdfN : (root,sgPat : Str) -> Gender -> Species -> N ; -- Takes a root string, a singular pattern string, a gender, and species. Gives a noun whose plural is sound feminine. sdmN : (root,sgPat : Str) -> Gender -> Species -> N ; -- Takes a root string, a singular pattern string, a gender, and species. Gives a noun whose plural is sound masculine dualN : N -> N ; -- Force the plural of the N into dual (e.g. "twins") --3 Proper names mkPN = overload { mkPN : Str -> PN -- Predictable PN from a Str: fem hum if ends in ة, otherwise masc hum. = smartPN ; mkPN : N -> PN -- Make a PN out of N. The PN is in construct state. = \n -> lin PN (n ** { s = \\c => n.s ! Sg ! Const ! c ++ n.s2 ! Sg ! Def ! c -- NB this hack works for idaafa constructions (if you used mkN : N -> N -> N), but wrong for mkN : N -> A -> N. /IL }) ; mkPN : Str -> Gender -> Species -> PN -- Make a PN out of string, gender and species. = mkFullPN ; } ; --3 Relational nouns mkN2 : overload { mkN2 : N -> Prep -> N2 ; -- Noun and a ready-made preposition. mkN2 : N -> Str -> N2 ; -- Noun, preposition given as a string, complement case genitive. mkN2 : N -> N2 ; -- Noun, no preposition, complement case genitive. mkN2 : Str -> N2 ; -- Predictable inflection, no preposition, complement case genitive. } ; mkN3 : overload { mkN3 : N -> Preposition -> Preposition -> N3 ; -- ready-made prepositions mkN3 : N -> Str -> Str -> N3 ; -- prepositions given as strings } ; --2 Adjectives -- Overloaded operator for main cases mkA = overload { mkA : (root : Str) -> A -- adjective with positive form aFCal = \r -> lin A (clrA r); mkA : (root,sgPat : Str) -> A -- adjective with sound plural, takes root string and sg. pattern string = \r,p -> lin A (sndA r p); mkA : (root,sgPat,plPat : Str) -> A -- adjective with broken plural, same for both fem. and masc. = \r,s,p -> lin A (brkA r s p) ; mkA : (isSoundFem : Bool) -> (root,sg,pl : Str) -> A -- adjective with broken plural, boolean argument whether feminine is sound (True) or shared with masc (False) = \b,r,s,p -> lin A (brkABool b r s p) ; mkA : A -> Str -> A -- add non-inflecting component after adjective = \a,s -> a ** {s = table {af => a.s ! af ++ s}} ; mkA : Str -> A -> A -- add non-inflecting component before adjective = \s,a -> a ** {s = table {af => s ++ a.s ! af}} } ; nisbaA : Str -> Adj ; -- Forms relative adjectives with the suffix ِيّ. Takes either the stem and adds يّ, or the whole word ending in يّ and just adds declension. idaafaA : N -> A -> A ; -- Forms adjectives of type غَيْرُ طَيِّبٍ 'not good'. Noun is in construct state but inflects in case. Adjective is in genitive, but inflects in gender, number and state. degrA : (masc,fem,plur : Str) -> A ; -- Adjective where masculine singular is also the comparative form. Indeclinable singular, basic triptote declension for dual and plural. irregFemA : (masc : A) -> (fem : A) -> A ; -- Adjective with irregular feminine. Takes two adjectives (masc. regular and fem. "regular", with fem. forms in the masc fields,) and puts them together. invarGenderA : A -> A ; -- Forms an adjective that has no feminine form. Takes a regular adjective and forces the masculine forms into the fem. table. --3 Two-place adjectives -- -- Two-place adjectives need a preposition for their second argument. mkA2 : overload { mkA2 : A -> Prep -> A2 ; mkA2 : A -> Str -> A2 } ; --2 Adverbs -- Adverbs are not inflected. Most lexical ones have position -- after the verb. Some can be preverbal. mkAdv : Str -> Adv ; mkAdV : Str -> AdV ; -- Adverbs modifying adjectives and sentences can also be formed. mkAdA : Str -> AdA ; mkInterj : Str -> Interj ; mkSubj : overload { mkSubj : Str -> Subj ; -- Default order Subord (=noun first and in accusative) mkSubj : Str -> Order -> Subj -- Specify word order } ; --2 Prepositions -- -- A preposition as used for rection in the lexicon, as well as to -- build $PP$s in the resource API. Requires a string and a case. mkPrep : overload { mkPrep : Str -> Prep ; -- Build a preposition out of the given string, with genitive case. mkPrep : Str -> Case -> Prep ; -- Build a preposition out of the given string and case. mkPrep : Case -> Prep ; -- Just a case, no preposition. } ; liPrep : Prep ; -- The preposition لِ, binding to its head. Vowel assimilation and def. article elision implemented. biPrep : Prep ; -- The preposition بِ, binding to its head. noPrep : Prep ; -- No preposition at all, "complement case" is nominative. --2 Conjunctions mkConj : overload { mkConj : Str -> Conj ; -- and mkConj : Str -> Str -> Conj ; -- either … or mkConj : Str -> Number -> Conj ; -- and, pl mkConj : Str -> Str -> Number -> Conj ; -- either, or, sg } ; --2 Verbs -- Overloaded operations mkV : overload { mkV : (imperfect,masdar : Str) -> V ; -- Takes a verb of Form I in 3rd person masculine imperfect tense. Unpredictable masdar given as an argument. mkV : (imperfect : Str) -> V ; -- Takes a verb of Form I in 3rd person masculine imperfect tense. Dummy masdar inserted. mkV : (root : Str) -> (perf,impf : Vowel) -> (masdar : Str) -> V ; -- Takes the root of a verb of Form I. Vowel is one of {va,vi,vu}. Unpredictable masdar given as an argument. mkV : (root : Str) -> (perf,impf : Vowel) -> V ; -- Like above, but dummy masdar inserted. This function is here only to keep compatibility for the old API; for new grammars, use the constructor with masdar as an argument. mkV : (root,masdar : Str) -> VerbForm -> V ; -- FormI…FormXI (no IX). XI is quadriliteral. For FormI, default vowels are va and vu. The given masdar is used for FormI, but currently ignored for Forms II-XI. mkV : (root : Str) -> VerbForm -> V ; -- Like above, but dummy masdar inserted for FormI verbs. No difference for FormII-FormXI, because they have predictable masdar. mkV : V -> (particle : Str) -> V -- V with a non-inflecting particle/phrasal verb } ; reflV : V -> V ; -- نَفْس in the proper case and with possessive suffix, e.g. نَفْسَكِ v1 = overload { v1 : (root : Str) -> (perf,impf : Vowel) -> (masdar : Str) -> V -- Verb Form I: fa`ala, fa`ila, fa`ula. Verbal noun (masdar) given as the third argument. = v1masdar ; v1 : (root : Str) -> (perf,impf : Vowel) -> V -- To keep compatibility for the old API; dummy masdar inserted. = v1dummymasdar ; } ; v2 : Str -> V ; -- Verb Form II: fa``ala v3 : Str -> V ; -- Verb Form III: faa`ala v4 : Str -> V ; -- Verb Form IV: 'af`ala v5 : Str -> V ; -- Verb Form V: tafa``ala v6 : Str -> V ; -- Verb Form VI: tafaa`ala v7 : Str -> V ; -- Verb Form VII: infa`ala v8 : Str -> V ; -- Verb Form VIII: ifta`ala v10 : Str -> V ; -- Verb Form X: 'istaf`ala v11 : Str -> V ; -- Verb Form XI (quadriliteral): fa`laba --3 Two-place verbs -- Two-place verbs need a preposition, except the special case with direct object. -- (transitive verbs). Notice that a particle comes from the $V$. mkV2 : overload { mkV2 : V -> V2 ; -- No preposition mkV2 : V -> Str -> V2 ; -- Preposition as string, default case genitive mkV2 : V -> Prep -> V2 ; -- Ready-made preposition mkV2 : Str -> V2 ; -- Predictable verb conjugation, no preposition } ; dirV2 : V -> V2 ; --3 Three-place verbs -- Three-place (ditransitive) verbs need two prepositions, of which -- the first one or both can be absent. mkV3 : overload { mkV3 : V -> Prep -> Prep -> V3 ; -- speak, with, about mkV3 : V -> (to : Str) -> (about:Str) -> V3 -- like above, but with strings as arguments (default complement case genitive) } ; dirV3 : overload { dirV3 : V -> Prep -> V3 ; -- give,_,to dirV3 : V -> (to : Str) -> V3 -- like above, but with string as argument (default complement case genitive) } ; dirdirV3 : V -> V3 ; -- give,_,_ --3 Other complement patterns -- -- Verbs and adjectives can take complements such as sentences, -- questions, verb phrases, and adjectives. mkV0 : V -> V0 ; mkVS : overload { mkVS : V -> VS ; -- Takes a V, returns a VS with default complementiser أَنَّ. mkVS : V -> Str -> VS -- Takes a V and a complementiser. } ; mkV2S : overload { mkV2S : V -> V2S ; -- Takes a V, returns a V2S with default complementiser أَنَّ and accusative as the direct object case. mkV2S : VS -> V2S ; -- Takes a VS, returns a V2S with accusative as the object case, retaining the VS's complementiser. mkV2S : V2 -> V2S ; -- Takes a V2, returns a V2S with default complementiser أَنَّ, retaining the V2's direct object case. mkV2S : V -> Prep -> Str -> V2S ; -- Takes V, preposition and complementiser. } ; mkVV = overload { mkVV : V -> VV -- Takes a V, returns a VV with default complementiser أَنَّ. = regVV ; mkVV : V -> Str -> VV -- Takes a V and a complementiser. = s2VV ; } ; mkV2V : overload { mkV2V : V -> V2V ; -- Takes a V, returns a V2V with default complementiser أَنْ and accusative as the direct object case. mkV2V : VV -> V2V ; -- Takes VV, returns V2V with accusative as the object case, retaining the VV's complementiser. mkV2V : V -> Prep -> Str -> V2V ; -- Takes V, preposition and complementiser. } ; subjCase : overload { subjCase : VV -> Prep -> VV ; -- Change the subject case of a VV. (Default is nominative; use any other case or preposition.) subjCase : V2V -> Prep -> V2V ; -- Change the subject case to a V2V. (Default is nominative; use any other case or preposition.) } ; mkVA : V -> VA ; mkV2A : V -> Str -> V2A ; -- Takes a V and an object case/preposition. NB. V2A = V2, see mkV2 for more constructors. mkVQ : V -> VQ ; mkV2Q : V -> Str -> V2Q ; -- Takes a V and an object case/preposition. NB. V2Q = V2, see mkV2 for more constructors. mkAS : A -> AS ; mkA2S : A -> Str -> A2S ; mkAV : A -> AV ; mkA2V : A -> Str -> A2V ; -- Notice: categories $AS, A2S, AV, A2V$ are just $A$, -- and the second argument is given -- as an adverb. Likewise -- $V0$ is just $V$. V0 : Type ; AS, A2S, AV, A2V : Type ; --. --2 Definitions of paradigms -- The definitions should not bother the user of the API. So they are -- hidden from the document. Case = ResAra.Case ; nom = ResAra.Nom ; acc = ResAra.Acc ; gen = ResAra.Gen ; Gender = ResAra.Gender ; masc = ResAra.Masc ; fem = ResAra.Fem ; Number = ResAra.Number ; sg = ResAra.Sg ; pl = ResAra.Pl ; Species = ResAra.Species ; hum = ResAra.Hum ; nohum = ResAra.NoHum ; Vowel = ResAra.Vowel ; va = ResAra.a ; vu = ResAra.u ; vi = ResAra.i ; mkPrep = overload { mkPrep : Str -> Prep = \s -> lin Prep (mkPreposition s) ; mkPrep : Str -> Case -> Prep = \s,c -> lin Prep (mkPreposition s c) ; mkPrep : Case -> Prep = \c -> lin Prep (casePrep c) ; } ; noPrep = lin Prep ResAra.noPrep ; biPrep = lin Prep ResAra.biPrep ; liPrep = lin Prep ResAra.liPrep ; casePrep : Case -> Prep = \c -> lin Prep {s=[]; c=c; binds=False} ; mkV2 = overload { mkV2 : V -> V2 = dirV2 ; mkV2 : V -> Str -> V2 = \v,p -> prepV2 v (mkPreposition p); mkV2 : V -> Prep -> V2 = prepV2 ; mkV2 : Str -> V2 = strV2; } ; prepV2 : V -> Preposition -> V2 = \v,p -> v ** {s = v.s ; c2 = p ; lock_V2 = <>} ; strV2 : Str -> V2 = \str -> dirV2 (mkV str) ; mkN = overload { mkN : (sg : Str) -> N -- non-human regular nouns = smartN ; mkN : Species -> N -> N = \p,n -> n ** {h = p} ; mkN : (sg,pl : Str) -> Gender -> Species -> N = \sg,pl -> case of { => mkFullN (sndf x) ; -- extra safety: if someone gives case marking to the constructor, ignore it _ => mkFullN (reg sg pl) } ; mkN : NTable -> Gender -> Species -> N -- TO BE DEPRECATED; kept for backwards-compatibility. For the same behaviour, use either the constructor above, sdfN or sdmN. = mkFullN ; mkN : (root,sgPatt,brokenPlPatt : Str) -> Gender -> Species -> N -- broken plural = brkN ; mkN : N -> (attr : Str) -> N -- Compound nouns with noninflecting attribute = \n,attr -> n ** {s2 = \\num,s,c => n.s2 ! num ! s ! c ++ attr} ; mkN : N -> N -> N -- Compound nouns where attribute inflects in state and case but not number = attrN Sg ; mkN : Number -> N -> N -> N -- Compound nouns where attribute inflects in state, case and number = attrN ; mkN : N -> A -> N = mkAN ; mkN : Number -> N -> A -> N = \num,n,a -> mkAPNumN n (A.PositA a) num ; mkN : N -> AP -> N = mkAPN } ; attrN : Number -> N -> N -> N = \num,n1,n2 -> n1 ** { s = \\n,_,c => n1.s ! n ! Const ! c ; s2 = \\n,s,_ => n1.s2 ! num ! s ! Gen -- attribute doesn't change ++ n2.s ! num ! s ! Gen ++ n2.s2 ! num ! s ! Gen} ; mkAN : N -> A -> N = \n,a -> mkAPN n (A.PositA a) ; mkAPN : N -> AP -> N = \n,ap -> n ** { s2 = \\num,s,c => n.s2 ! num ! s ! c ++ ap.s ! n.h ! n.g ! num ! s ! c } ; mkAPNumN : N -> AP -> Number -> N = \n,ap,forceNum -> n ** { s2 = \\num,s,c => n.s2 ! num ! s ! c ++ ap.s ! Hum ! n.g ! forceNum ! s ! c } ; -- Hum because we want to override the smartness in number agreement dualN : N -> N = \n -> n ** {isDual=True} ; proDrop : NP -> NP ; -- Force a NP to lose its string, only contributing with its agreement. mkPron : (_,_,_ : Str) -> PerGenNum -> Pron ; mkV = overload { mkV : (imperfect,masdar : Str) -> V = \v,m -> regV v m ; mkV : (imperfect : Str) -> V = \v -> regV v ; mkV : (root : Str) -> (perf,impf : Vowel) -> (masdar : Str) -> V -- verb form I ; vowel = a|i|u = v1masdar ; mkV : (root : Str) -> (perf,impf : Vowel) -> V -- verb form I ; vowel = a|i|u ; dummy masdar = v1dummymasdar ; mkV : (root : Str) -> VerbForm -> V -- FormI .. FormX (no VII, IX) ; default vowels a u for I = formV ; mkV : V -> (particle : Str) -> V = \v,p -> v ** { s = \\vf => v.s ! vf ++ p } ; } ; regV = overload { regV : (v,msdr : Str) -> V = \wo,msdr -> let rau : Str * Vowel * Vowel = case wo of { "يَ" + fc + "ُ" + l => ; "يَ" + fc + "ِ" + l => ; "يَ" + fc + "َ" + l => ; f@? + "َ" + c@? + "ِ" + l => ; _ => Predef.error ("regV not applicable to" ++ wo) } in v1masdar rau.p1 rau.p2 rau.p3 msdr ; regV : Str -> V = \wo -> let rau : Str * Vowel * Vowel = case wo of { "يَ" + fc + "ُ" + l => ; "يَ" + fc + "ِ" + l => ; "يَ" + fc + "َ" + l => ; f@? + "َ" + c@? + "ِ" + l => ; _ => Predef.error ("regV not applicable to" ++ wo) } in v1dummymasdar rau.p1 rau.p2 rau.p3 } ; v1masdar : Str -> (perf,impf : Vowel) -> (masdar : Str) -> V = \rootStr,vPerf,vImpf,msdr -> let { raw = v1' rootStr vPerf vImpf msdr } in lin V { s = \\vf =>rectifyHmz (raw.s ! vf) } ; v1dummymasdar : Str -> (p,i : Vowel) -> V = \rootStr,vPerf,vImpf -> let { dummyMasdar = mkStrong facl (mkRoot3 rootStr) ; raw = v1' rootStr vPerf vImpf dummyMasdar } in lin V { s = \\vf =>rectifyHmz (raw.s ! vf) } ; v1' : Str -> (p,i : Vowel) -> (masdar : Str) -> Verb = \rootStr,vPerf,vImpf,masdar -> let root = mkRoot3 rootStr in case rootStr of { f@? + c@? + "ّ" => v1geminate (f+c+c) vPerf vImpf masdar ; ? + #hamza + #weak => v1doubleweak root masdar ; #weak + ? + #weak => v1assimilated_defective root vPerf vImpf masdar ; ? + ? + #weak => case vPerf of { i => v1defective_i root vImpf masdar ; _ => v1defective_a root vImpf masdar } ; ? + #weak + ? => v1hollow root vImpf masdar ; _ => v1sound root vPerf vImpf masdar } ; v2 = \rootStr -> let { root = mkRoot3 rootStr } in lin V { s = case rootStr of { -- #weak + ? + ? => ? + ? + #weak => (v2defective root).s; _ => (v2sound root).s } }; v3 = \rootStr -> let { tbc = mkRoot3 rootStr ; } in lin V { s = (v3sound tbc).s }; v4 = \rootStr -> let root : Root3 = mkRoot3 rootStr ; verb : Verb = case rootStr of { #weak + ? + ? => v4assimilated root ; ? + #hamza + #weak => v4doubleweak root ; ? + #weak + ? => v4hollow root ; _ + #weak => v4defective root ; _ => v4sound root } ; in lin V verb ; v5 = \rootStr -> let { raw = v5' rootStr } in raw ** { s = \\vf => case rootStr of { _ + #hamza + _ => rectifyHmz(raw.s ! vf); _ => raw.s ! vf } }; v5' : Str -> V = \rootStr -> let { nfs = mkRoot3 rootStr ; } in lin V { s = (v5sound nfs).s }; v6 = \rootStr -> let { fqm = mkRoot3 rootStr ; } in lin V { s = (v6sound fqm).s }; v7 = \rootStr -> let { fcl = mkRoot3 rootStr ; verb : Verb = case rootStr of { f@? + c@? + "ّ" => v7geminate (f+c+c) ; _ => v7sound fcl } } in lin V verb ; v8 = \rootStr -> let { fcl = mkRoot3 rootStr ; verb : Verb = case rootStr of { f@? + c@? + "ّ" => v8geminate (f+c+c) ; #weak + ? + ? => v8assimilated fcl ; ? + #weak + ? => v8hollow fcl ; _ => v8sound fcl } } in lin V verb ; v10 = \rootStr -> let { fcl = mkRoot3 rootStr ; verb : Verb = case rootStr of { f@? + c@? + "ّ" => v10geminate (f+c+c) ; ? + #weak + ? => v10hollow fcl ; ? + ? + #weak => v10defective fcl ; _ => v10sound fcl } } in lin V verb ; v11 = \rootStr -> let fcl : Root3 = case rootStr of { f@? + c@? + l@? + b@? => {f=f ; c=c+"ْ"+l ; l=b} ; _ => Predef.error "v11: implement quadriliterals properly" } ; verb : Verb = case rootStr of { _ => v11sound fcl -- TODO more cases? } ; in lin V verb ; reflV v = lin V (ResAra.reflV v) ; mkFullN : NTable -> Gender -> Species -> N ; -- This is used for loan words or anything that has untreated irregularities in the interdigitization process of its words mkFullN nsc gen spec = lin N { s = nsc; --NTable s2 = emptyNTable; g = gen; h = spec; isDual = False }; brkN' : Str -> Str -> Str -> Gender -> Species -> N = \root,sg,pl,gen,spec -> let { kitAb = case root of { ? + ? + "ي" => mkDefectiveAlifMaqsura (mkPat sg) (mkRoot3 root) ; _ => mkWord sg root }; kutub = mkWord pl root } in mkFullN (reg kitAb kutub) gen spec; --Takes a root string, a singular pattern string, a broken plural --pattern string, a gender, and species. Gives a noun. brkN root sg pl gen spec = let { raw = brkN' root sg pl gen spec} in raw ** { s = \\n,d,c => case root of { _ + #hamza + _ => rectifyHmz(raw.s ! n ! d ! c); _ => raw.s ! n ! d ! c } }; sdfN = \root,sg,gen,spec -> let { kalimaStr = case root of { x@? + y@? + "ي" => mkDefectiveAlifMaqsura (mkPat sg) (mkRoot3 root) ; _ => mkWord sg root } ; kalimaRaw : NTable = case gen of { Fem => sndf kalimaStr ; Masc => sgMsndf kalimaStr } ; -- TODO this isn't actually the case of gender, add an argument kalima : NTable = \\n,d,c => rectifyHmz (kalimaRaw ! n ! d ! c) } in mkFullN kalima gen spec; sdmN = \root,sg,gen,spec -> let { mucallim = mkWord sg root; } in mkFullN (sndm mucallim) gen spec; mkFullPN : Str -> Gender -> Species -> PN ; mkFullPN = \str,gen,species -> { s = \\c => str + indecl!c ; g = gen; h = species; lock_PN = <> }; mkN2 = overload { mkN2 : N -> Prep -> N2 = prepN2 ; mkN2 : N -> Str -> N2 = \n,s -> prepN2 n (mkPreposition s); mkN2 : N -> N2 = \n -> prepN2 n genPrep; mkN2 : Str -> N2 = \str -> prepN2 (smartN str) genPrep; } ; prepN2 : N -> Preposition -> N2 = \n,p -> lin N2 (n ** {c2 = p}) ; mkN3 = overload { mkN3 : N -> Prep -> Prep -> N3 = \n,p,q -> lin N3 (n ** {c2 = p ; c3 = q}) ; mkN3 : N -> Str -> Str -> N3 = \n,p,q -> lin N3 (n ** {c2 = mkPreposition p ; c3 = mkPreposition q}) ; } ; mkConj = overload { mkConj : Str -> Conj = \s -> lin Conj {s1 = [] ; s2 = s ; n = Sg} ; mkConj : Str -> Str -> Conj = \s1,s2 -> lin Conj {s1 = s1 ; s2 = s2 ; n = Sg} ; mkConj : Str -> Number -> Conj = \s,n -> lin Conj {s1 = [] ; s2 = s ; n = n} ; mkConj : Str -> Str -> Number -> Conj = \s1,s2,n -> lin Conj {s1 = s1 ; s2 = s2 ; n = n} } ; mkPron : (_,_,_ : Str) -> PerGenNum -> Pron = \ana,nI,I,pgn -> lin Pron (ResAra.mkPron ana nI I pgn) ; proDrop : NP -> NP = \np -> lin NP (ResAra.proDrop np) ; mkQuant7 : (_,_,_,_,_,_,_ : Str) -> State -> Quant = \hava,havihi,havAn,havayn,hAtAn,hAtayn,hA'ulA,det -> lin Quant (ResAra.mkQuant7 hava havihi havAn havayn hAtAn hAtayn hA'ulA det) ; mkQuant3 : (_,_,_ : Str) -> State -> Quant = \dalika,tilka,ula'ika,det -> lin Quant (ResAra.mkQuant3 dalika tilka ula'ika det) ; brkA : (root,sg,pl : Str) -> Adj -- also broken feminine = brkABool False ; brkABool : Bool -> (root,sg,pl : Str) -> Adj = \isSndFem,root,sg,pl -> let jadId = mkWord sg root ; jadIda = jadId + "َة" ; judud = mkWord pl root ; jadIdAt = case isSndFem of { True => jadId + "َات" ; False => judud } ; akbar = mkWord "أَفعَل" root ; mascTbl = reg jadId judud ; femTbl = reg jadIda jadIdAt ; in { s = table { APosit Masc n d c => rectifyHmz (mascTbl ! n ! d ! c) ; APosit Fem n d c => rectifyHmz (femTbl ! n ! d ! c) ; AComp d c => rectifyHmz (indeclN akbar ! d ! c) } } ; degrA : (masc,fem,plur : Str) -> A = \masc,fem,plur -> lin A {s = clr masc fem plur} ; idaafaA : N -> A -> A = \ghayr,tayyib -> tayyib ** { s = table { APosit g n d c => ghayr.s ! n ! Const ! c ++ tayyib.s ! APosit g n d c ; AComp d c => ghayr.s ! Sg ! Const ! c ++ tayyib.s ! AComp d c } } ; sndA : Str -> Str -> A = \root,pat -> let raw = sndA' root pat in lin A { s = \\af => case root of { _ + #hamza + _ => rectifyHmz(raw.s ! af); _ => raw.s ! af } }; sndA' : Str -> Str -> Adj = \root,pat -> let { kabIr = mkWord pat root; akbar = mkWord "أَفعَل" root } in { s = table { APosit g n d c => positAdj kabIr ! g ! n ! d ! c ; AComp d c => indeclN akbar ! d ! c } }; irregFemA : (masc : A) -> (fem : A) -> A = \m,f -> m ** { s = table { APosit Masc n d c => m.s ! APosit Masc n d c ; APosit Fem n d c => f.s ! APosit Masc n d c ; -- The fem. adjective is built as if the irregular fem. forms were Masc. This is on purpose. x => m.s ! x } } ; invarGenderA = \m -> irregFemA m m ; nisbaA Haal = let Haaliyy : Str = case Haal of { x + "يّ" => Haal ; -- if the ending is already given, don't add it x + ("ا"|"ة") => x + "ِيّ" ; -- drop final alif or ta marbuta _ => Haal + "ِيّ" } in lin A { s = table { APosit g n d c => positAdj Haaliyy ! g ! n ! d ! c ; AComp d c => "أَكْثَر" ++ indeclN Haaliyy ! d ! c } } ; clrA : Str -> A = \root -> let { eaHmar = mkWord "أَفعَل" root; HamrA' = mkWord "فَعلاء" root; Humr = mkWord "فُعل" root } in lin A { s = clr eaHmar HamrA' Humr; }; mkA2 = overload { mkA2 : A -> Prep -> A2 = prepA2 ; mkA2 : A -> Str -> A2 = \a,p -> prepA2 a (mkPreposition p) } ; prepA2 : A -> Preposition -> A2 = \a,p -> lin A2 (a ** {c2 = p}) ; mkAdv x = lin Adv (ss x) ; mkAdV x = lin AdV (ss x) ; mkAdA x = lin AdA (ss x) ; mkInterj x = lin Interj (ss x) ; mkSubj = overload { mkSubj : Str -> Subj = \s -> lin Subj {s = s ; o = Subord} ; mkSubj : Str -> Order -> Subj = \s,o -> lin Subj {s = s ; o = o} ; } ; dirV2 v = prepV2 v accPrep ; mkV3 = overload { mkV3 : V -> Prep -> Prep -> V3 = \v,p,q -> lin V3 (prepV3 v p q) ; mkV3 : V -> Str -> Str -> V3 = \v,p,q -> lin V3 (v ** {s = v.s ; c2 = mkPreposition p ; c3 = mkPreposition q}) } ; prepV3 : V -> Preposition -> Preposition -> Verb3 = \v,p,q -> v ** {s = v.s ; c2 = p ; c3 = q} ; dirV3 = overload { dirV3 : V -> Prep -> V3 = \v,p -> mkV3 v (casePrep acc) p ; dirV3 : V -> Str -> V3 = \v,s -> mkV3 v (casePrep acc) (mkPreposition s) } ; dirdirV3 v = dirV3 v (casePrep acc) ; mkVS = overload { mkVS : V -> VS = \v -> lin VS (v ** {o = Subord; s2 = anna}) ; mkVS : V -> Str -> VS = \v,s -> lin VS (v ** {o = Subord; s2 = s}) } ; mkVQ v = lin VQ v ; -- Complementisers for V*V and V*S an : Str = "أَنْ" ; anna : Str = "أَنَّ" ; regVV : V -> VV = \v -> lin VV v ** {s2=an ; sc=noPrep} ; s2VV : V -> Str -> VV = \v,compl -> regVV v ** {s2=compl; sc=noPrep} ; prepVV : V -> Prep -> VV = \v,prep -> regVV v ** {s2=an ; sc=prep} ; prep2VV : V -> Prep -> Str -> VV = \v,p,c -> regVV v ** {s2=c; sc=p} ; V0 : Type = V ; ---- V2S, V2V, V2Q, V2A : Type = V2 ; AS, A2S, AV : Type = A ; A2V : Type = A2 ; mkV0 v = v ; mkV2S = overload { mkV2S : V -> V2S = \v -> lin V2S (prepV2 v accPrep ** {s2=anna ; o=Subord}) ; mkV2S : V2 -> V2S = \v2 -> lin V2S (v2 ** {s2=anna ; o=Subord}) ; mkV2S : V -> Preposition -> V2S = \v,p -> lin V2S ((prepV2 v p) ** {s2=anna ; o=Subord}) } ; mkV2V = overload { mkV2V : V -> V2V = \v -> lin V2V (v ** {c2=accPrep ; s2=an ; sc=noPrep}) ; mkV2V : VV -> V2V = \vv -> lin V2V (vv ** {c2 = accPrep}) ; mkV2V : VV -> Prep -> V2V = \vv,p -> lin V2V (vv ** {c2 = p}) ; mkV2V : V -> Prep -> Str -> V2V = \v,p,q -> lin V2V (v ** {c2 = p ; s2 = q ; sc = noPrep}) ; mkV2V : V2 -> V2V = \v2 -> lin V2V (v2 ** {s2 = an ; sc = noPrep}) ; mkV2V : V2 -> Str -> V2V = \v2,c -> lin V2V (v2 ** {c2 = v2.c2 ; s2 = c ; sc = noPrep}) ; } ; subjCase = overload { subjCase : VV -> Prep -> VV = \vv,p -> vv ** {sc=p} ; subjCase : V2V -> Prep -> V2V = \vv,p -> vv ** {sc=p} } ; mkVA v = v ** {lock_VA = <>} ; mkV2A v p = lin V2A (prepV2 v (mkPreposition p)); mkV2Q v p = lin V2Q (prepV2 v (mkPreposition p)); mkAS, mkAV = \a -> a ; mkA2S, mkA2V = \a,p -> prepA2 a (mkPreposition p) ; smartN : Str -> N = \s -> case s of { _ + "ة" => mkFullN (sndf s) Fem NoHum ; _ + "ة" + #vow => mkFullN (sndf s) Fem NoHum ; _ => mkFullN (sndm s) Masc NoHum } ; smartPN : Str -> PN = \s -> case last s of { "ة" => mkFullPN s Fem Hum ; _ => mkFullPN s Masc Hum } ; formV : (root : Str) -> VerbForm -> V = \s,f -> case f of { FormI => v1 s a u ; FormII => v2 s ; FormIII => v3 s ; FormIV => v4 s ; FormV => v5 s ; FormVI => v6 s ; FormVII => v7 s ; FormVIII => v8 s ; FormX => v10 s ; FormXI => v11 s } ; param VerbForm = FormI | FormII | FormIII | FormIV | FormV | FormVI | FormVII | FormVIII | FormX | FormXI ; } ;