mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-04-21 10:49:33 -06:00
1231 lines
40 KiB
Plaintext
1231 lines
40 KiB
Plaintext
-- ResMlt.gf: Language-specific parameter types, morphology, VP formation
|
|
--
|
|
-- Maltese GF Resource Grammar
|
|
-- John J. Camilleri 2011 -- 2013
|
|
-- Angelo Zammit 2012
|
|
-- Licensed under LGPL
|
|
|
|
--# -path=.:../abstract:../common:../prelude
|
|
|
|
resource ResMlt = ParamX ** open Prelude, Predef, Maybe in {
|
|
|
|
flags coding=utf8 ;
|
|
optimize=noexpand ;
|
|
|
|
{- General -------------------------------------------------------------- -}
|
|
|
|
param
|
|
|
|
Gender = Masc | Fem ;
|
|
|
|
GenNum =
|
|
GSg Gender -- DAK, DIK
|
|
| GPl -- DAWK
|
|
;
|
|
|
|
Definiteness =
|
|
Definite -- eg BIL-
|
|
| Indefinite -- eg BI
|
|
;
|
|
|
|
oper
|
|
bool2definiteness : Bool -> Definiteness = \b ->
|
|
if_then_else Definiteness b Definite Indefinite ;
|
|
|
|
-- Agreement system corrected based on comments by [AZ]
|
|
Agr : Type = { n : Number ; p : Person ; g : Gender } ;
|
|
|
|
-- Make Agr from raw ingredients
|
|
mkAgr : Number -> Person -> Gender -> Agr = \n,p,g -> {n = n ; p = p ; g = g} ;
|
|
|
|
-- Convert to Agr from other typek
|
|
toAgr = overload {
|
|
toAgr : GenNum -> Agr = \gn -> case gn of {
|
|
GSg g => {n = Sg ; p = P3 ; g = g} ;
|
|
GPl => {n = Pl ; p = P3 ; g = Masc}
|
|
} ;
|
|
toAgr : VAgr -> Agr = \vagr ->
|
|
case vagr of {
|
|
AgP1 num => mkAgr num P1 Masc ;
|
|
AgP2 num => mkAgr num P2 Masc ;
|
|
AgP3Sg gen => mkAgr Sg P3 gen ;
|
|
AgP3Pl => mkAgr Pl P3 Masc
|
|
} ;
|
|
} ;
|
|
|
|
-- Make Agr from raw ingredients
|
|
mkGenNum = overload {
|
|
mkGenNum : Gender -> Number -> GenNum = \g,n ->
|
|
case n of {
|
|
Sg => GSg g ;
|
|
Pl => GPl
|
|
} ;
|
|
mkGenNum : Number -> Gender -> GenNum = \n,g ->
|
|
case n of {
|
|
Sg => GSg g ;
|
|
Pl => GPl
|
|
} ;
|
|
mkGenNum : Noun_Number -> Gender -> GenNum = \n,g ->
|
|
case nounnum2num n of {
|
|
Sg => GSg g ;
|
|
Pl => GPl
|
|
} ;
|
|
} ;
|
|
|
|
-- Convert to GenNum from another type
|
|
toGenNum : Agr -> GenNum = \a ->
|
|
case a.n of {
|
|
Sg => GSg a.g ;
|
|
Pl => GPl
|
|
} ;
|
|
|
|
-- Convert to VAgr from another type
|
|
toVAgr = overload {
|
|
toVAgr : Agr -> VAgr = \agr ->
|
|
case <agr.p,agr.n> of {
|
|
<P1,num> => AgP1 num;
|
|
<P2,num> => AgP2 num;
|
|
<P3,Sg> => AgP3Sg agr.g;
|
|
<P3,Pl> => AgP3Pl
|
|
} ;
|
|
toVAgr : GenNum -> VAgr = \gn ->
|
|
case gn of {
|
|
GSg g => AgP3Sg g;
|
|
GPl => AgP3Pl
|
|
} ;
|
|
} ;
|
|
|
|
agrP3 : Number -> Gender -> Agr = \n,g -> mkAgr n P3 g;
|
|
|
|
VPForm2VAgr : VPForm -> VAgr = \vpform ->
|
|
case vpform of {
|
|
VPIndicat _ vagr => vagr ;
|
|
VPImperat n => AgP2 n
|
|
};
|
|
|
|
sing : VAgr -> Bool = \agr ->
|
|
case toAgr agr of {
|
|
{n=Sg; p=_; g=_} => True ;
|
|
_ => False
|
|
} ;
|
|
|
|
femOrPlural : Agr -> Bool = \agr ->
|
|
case agr of {
|
|
{n=Sg; p=_; g=Fem} => True ;
|
|
{n=Pl; p=_; g=_} => True ;
|
|
_ => False
|
|
} ;
|
|
|
|
conjAgr : Agr -> Agr -> Agr = \a,b -> {
|
|
n = (conjNumber a.n b.n) ;
|
|
p = (conjPerson a.p b.p) ;
|
|
g = a.g ;
|
|
} ;
|
|
|
|
-- ConjNumber, ConjPerson are defined in ParamX
|
|
conjGender : Gender -> Gender -> Gender = \a,b -> b ;
|
|
|
|
param
|
|
-- Agreement for verbs
|
|
VAgr =
|
|
AgP1 Number -- JIENA, AĦNA
|
|
| AgP2 Number -- INTI, INTOM
|
|
| AgP3Sg Gender -- HUWA, HIJA
|
|
| AgP3Pl -- HUMA
|
|
;
|
|
|
|
param
|
|
NPCase =
|
|
NPNom
|
|
| NPAcc -- I have a feeling we'll this need eventually
|
|
| NPCPrep -- [AZ]
|
|
;
|
|
|
|
oper
|
|
npNom = NPNom ;
|
|
npAcc = NPAcc ;
|
|
|
|
{- Clause --------------------------------------------------------------- -}
|
|
|
|
oper
|
|
Clause : Type = {
|
|
s : Tense => Anteriority => Polarity => Order => Str
|
|
} ;
|
|
QClause : Type = {
|
|
s : Tense => Anteriority => Polarity => QForm => Str
|
|
} ;
|
|
RClause : Type = {
|
|
s : Tense => Anteriority => Polarity => Agr => Str
|
|
} ;
|
|
|
|
-- Clause
|
|
mkClause : Str -> Agr -> VerbPhrase -> Clause = \subj,agr,vp -> {
|
|
s = \\t,a,p,o =>
|
|
let
|
|
-- verb = vp.s ! t ! a ! p ! o ! agr ;
|
|
-- vform = case <t,agr> of {
|
|
-- _ => VPres
|
|
-- } ;
|
|
vpform : VPForm = VPIndicat t (toVAgr agr) ;
|
|
verb : Str = joinVP vp vpform a p ;
|
|
compl : Str = vp.s2 ! agr ;
|
|
in
|
|
case o of {
|
|
-- ODir => subj ++ verb.aux ++ verb.adv ++ vp.ad ++ verb.fin ++ verb.inf ++ vp.p ++ compl ;
|
|
-- OQuest => verb.aux ++ subj ++ verb.adv ++ vp.ad ++ verb.fin ++ verb.inf ++ vp.p ++ compl
|
|
|
|
-- ABSOLUTELY NOT CORRECT: in progress
|
|
ODir => subj ++ verb ++ compl ;
|
|
OQuest => subj ++ verb ++ compl
|
|
}
|
|
} ;
|
|
|
|
mkQuestion : {s : Str} -> Clause -> QClause = \wh,cl -> {
|
|
s = \\t,a,p =>
|
|
let
|
|
cls = cl.s ! t ! a ! p ;
|
|
why = wh.s
|
|
in table {
|
|
QDir => why ++ cls ! OQuest ;
|
|
QIndir => why ++ cls ! ODir
|
|
}
|
|
} ;
|
|
|
|
{- Numeral -------------------------------------------------------------- -}
|
|
|
|
param
|
|
CardOrd = NCard | NOrd ;
|
|
|
|
-- Order of magnitude
|
|
DForm =
|
|
Unit -- 0..10
|
|
| Teen -- 11..19
|
|
| Ten -- 20..99
|
|
| Hund -- 100..999
|
|
| Thou -- 1000+
|
|
;
|
|
|
|
-- Indicate how a corresponding object should be treated
|
|
--- Overlap between Num Sg and Num1, but leaving as is for now
|
|
NumForm =
|
|
NumX Number -- Sg | Pl
|
|
| Num0 -- 0 (l-edba SIEGĦA)
|
|
| Num1 -- 1, 101... (SIEGĦA, mija u SIEGĦA)
|
|
| Num2 -- 2 (SAGĦTEJN)
|
|
| Num3_10 -- 3..10, 102, 103... (tlett SIEGĦAT, għaxar SIEGĦAT, mija u żewġ SIEGĦAT, mija u tlett SIEGĦAT)
|
|
| Num11_19 -- 11..19, 111... (ħdax-il SIEGĦA, mija u dsatax-il SIEGĦA)
|
|
| Num20_99 -- 20..99, 120... (għoxrin SIEGĦA, disa' u disgħajn SIEGĦA)
|
|
;
|
|
|
|
NumCase =
|
|
NumNom -- "Type B" in {MDG, 133}, e.g. TNEJN, ĦAMSA, TNAX, MIJA
|
|
| NumAdj -- "Type A" in {MDG, 133}, e.g. ŻEWĠ, ĦAMES, TNAX-IL, MITT
|
|
;
|
|
|
|
oper
|
|
|
|
num2nounnum : Number -> Noun_Number = \n ->
|
|
case n of {
|
|
Sg => Singulative ;
|
|
Pl => Plural
|
|
} ;
|
|
|
|
nounnum2num : Noun_Number -> Number = \n ->
|
|
case n of {
|
|
Singulative => Sg ;
|
|
Collective => Sg ;
|
|
Dual => Pl ;
|
|
Plural => Pl
|
|
} ;
|
|
|
|
numform2nounnum : NumForm -> Noun_Number = \n ->
|
|
case n of {
|
|
NumX Sg => Singulative ;
|
|
NumX Pl => Plural ;
|
|
Num0 => Singulative ;
|
|
Num1 => Singulative ;
|
|
Num2 => Dual ;
|
|
Num3_10 => Collective ;
|
|
Num11_19 => Singulative ;
|
|
Num20_99 => Plural
|
|
} ;
|
|
|
|
numform2num : NumForm -> Number = \n ->
|
|
case n of {
|
|
NumX num => num ;
|
|
Num0 => Sg ;
|
|
Num1 => Sg ;
|
|
_ => Pl
|
|
} ;
|
|
|
|
{- Determiners etc. ----------------------------------------------------- -}
|
|
|
|
oper
|
|
-- [AZ]
|
|
Determiner : Type = {
|
|
s : Gender => Str ;
|
|
n : NumForm ;
|
|
clitic : Str ;
|
|
hasNum : Bool ; -- has a numeral
|
|
isPron : Bool ; -- is a pronoun
|
|
isDefn : Bool ; -- is definite
|
|
} ;
|
|
-- Determiner = {
|
|
-- s : NPCase => Gender => NumCase => Str ;
|
|
-- s2 : NPCase => Gender => Str ; -- tieghi (possessive pronoun)
|
|
-- -- size : Num_Size ; -- One (agreement feature for noun)
|
|
-- isNum : Bool ; -- True (a numeral is present)
|
|
-- isDemo : Bool ; -- True (is a demostrative)
|
|
-- isDefn : Bool ;-- True (is definite)
|
|
-- } ;
|
|
|
|
-- [AZ]
|
|
Quantifier : Type = {
|
|
s : GenNum => Str ;
|
|
clitic : Str ;
|
|
isPron : Bool ;
|
|
isDemo : Bool ; -- Demonstrative (this/that/those/these)
|
|
isDefn : Bool ; -- is definite
|
|
} ;
|
|
-- Quantifier = {
|
|
-- s : NPCase => Gender => NumForm => Str ;
|
|
-- s2 : NPCase => Gender => NumForm => Str ;
|
|
-- isDemo : Bool ; -- Demonstrative (this/that/those/these)
|
|
-- isDefn : Bool ;
|
|
-- } ;
|
|
|
|
{- Noun ----------------------------------------------------------------- -}
|
|
|
|
oper
|
|
Noun : Type = {
|
|
s : Noun_Number => Str ;
|
|
g : Gender ;
|
|
hasColl : Bool ; -- has a collective form? e.g. BAQAR
|
|
hasDual : Bool ; -- has a dual form? e.g. SAGĦTEJN
|
|
takesPron : Bool ; -- takes enclitic pronon? e.g. MISSIERI
|
|
} ;
|
|
|
|
ProperNoun : Type = {
|
|
s : Str ;
|
|
a : Agr ; -- ignore a.p (always P3)
|
|
} ;
|
|
|
|
NounPhrase : Type = {
|
|
s : NPCase => Str ;
|
|
a : Agr ;
|
|
isPron : Bool ;
|
|
isDefn : Bool ;
|
|
} ;
|
|
|
|
param
|
|
Noun_Number =
|
|
Singulative -- ĦUTA
|
|
| Collective -- ĦUT
|
|
| Dual -- WIDNEJN
|
|
| Plural -- ĦUTIET
|
|
;
|
|
|
|
oper
|
|
-- Noun: Takes all forms and a gender
|
|
-- Params:
|
|
-- Singulative, eg KOXXA
|
|
-- Collective, eg KOXXOX
|
|
-- Double, eg KOXXTEJN
|
|
-- Determinate Plural, eg KOXXIET
|
|
-- Indeterminate Plural
|
|
-- Gender
|
|
mkNoun : (_,_,_,_,_ : Str) -> Gender -> (_,_ : Bool) -> Noun = \sing,coll,dual,det,ind,gen,hasColl,hasDual -> {
|
|
s = table {
|
|
Singulative => sing ;
|
|
Collective => coll ;
|
|
Dual => dual ;
|
|
Plural => det
|
|
-- Plural => variants {det ; ind}
|
|
} ;
|
|
g = gen ;
|
|
takesPron = False ;
|
|
hasDual = hasDual ;
|
|
hasColl = hasColl ;
|
|
} ;
|
|
|
|
-- Noun phrase
|
|
mkNP : Str -> Number -> Person -> Gender -> NounPhrase = \s,n,p,g -> {
|
|
s = \\npcase => s ;
|
|
a = mkAgr n p g ;
|
|
isPron = False ;
|
|
isDefn = False ;
|
|
};
|
|
|
|
regNP : Str -> NounPhrase = \kulhadd ->
|
|
mkNP kulhadd Sg P3 Masc ; -- kulħadd kuntent
|
|
|
|
-- Join a preposition and NP to a string
|
|
prepNP : Preposition -> NounPhrase -> Str ;
|
|
prepNP prep np = case np.isPron of {
|
|
True => prep.enclitic ! np.a ; -- magħha
|
|
False => case <np.isDefn, prep.takesDet> of {
|
|
<True,True> => prep.s ! Definite ++ np.s ! NPCPrep ; -- fit-triq
|
|
<True,False> => prep.s ! Definite ++ np.s ! NPNom ; -- fuq it-triq
|
|
<False,_> => prep.s ! Indefinite ++ np.s ! NPNom -- fi triq
|
|
}
|
|
} ;
|
|
|
|
Compl : Type = Preposition ** {isPresent : Bool} ;
|
|
-- Compl : Type = {
|
|
-- s : Str ;
|
|
-- -- c : NPForm ;
|
|
-- -- isPre : Bool
|
|
-- } ;
|
|
|
|
noCompl : Compl = {
|
|
s = \\_ => [] ;
|
|
enclitic = \\_ => [] ;
|
|
takesDet = False ;
|
|
joinsVerb = False ;
|
|
isPresent = False ;
|
|
} ;
|
|
|
|
Preposition = {
|
|
s : Definiteness => Str ;
|
|
enclitic : Agr => Str ; -- when suffixed by pronouns; magħ-ha
|
|
takesDet : Bool ; -- True: fil- / False: fuq il-
|
|
joinsVerb : Bool ; -- True for for_Prep (I.O. suffix)
|
|
} ;
|
|
|
|
{- Pronoun -------------------------------------------------------------- -}
|
|
|
|
oper
|
|
Pronoun = {
|
|
s : PronForm => Str ; -- cases like omm-i / hi-ja are handled elsewhere
|
|
a : Agr ;
|
|
} ;
|
|
|
|
param
|
|
PronForm =
|
|
Personal -- jiena
|
|
| Possessive -- tiegħi
|
|
| Suffixed -- qalb-i Only nouns!
|
|
-- | Suffixed PronCase
|
|
;
|
|
|
|
-- PronCase =
|
|
-- Acc -- Accusative: rajtu
|
|
-- | Dat -- Dative: rajtlu
|
|
-- | Gen -- Genitive: qalbu
|
|
-- ;
|
|
|
|
oper
|
|
-- Interrogative pronoun
|
|
mkIP : Str -> Number -> {s : Str ; n : Number} = \who,n ->
|
|
{
|
|
s = who ;
|
|
n = n
|
|
} ;
|
|
|
|
{- Verb ----------------------------------------------------------------- -}
|
|
|
|
oper
|
|
-- Generic variants (used for verb stems)
|
|
Variants3 : Type = {s1, s2, s3 : Str} ;
|
|
|
|
mkVariants3 : Variants3 = overload {
|
|
mkVariants3 : (s1 : Str) -> Variants3 = \a -> { s1 = a ; s2 = a ; s3 = a } ;
|
|
mkVariants3 : (s1, s2, s3 : Str) -> Variants3 = \a,b,c -> { s1 = a ; s2 = b ; s3 = c } ;
|
|
} ;
|
|
|
|
mkMaybeVariants3 : Str -> Maybe Variants3 = \s -> Just Variants3 (mkVariants3 s) ;
|
|
|
|
NullVariants3 : Maybe Variants3 = Nothing Variants3 { s1 = [] ; s2 = [] ; s3 = [] } ;
|
|
|
|
NullAgr : Maybe Agr = Nothing Agr (agrP3 Sg Masc) ;
|
|
|
|
-- Direct object clitic
|
|
DirObjVerbClitic : Type = {
|
|
s1 : Str ;
|
|
s2 : Str ;
|
|
s3 : Str ;
|
|
} ;
|
|
|
|
dirObjSuffix : Agr -> DirObjVerbClitic = \agr' ->
|
|
let agr : VAgr = toVAgr agr' in
|
|
case agr of {
|
|
-- DO DO + .. DO + .. (Neg)
|
|
AgP1 Sg => { s1="ni" ; s2="ni" ; s3="ni" } ;
|
|
AgP2 Sg => { s1="ek" ; s2="ek" ; s3="k" } ;
|
|
AgP3Sg Masc => { s1="u" ; s2="hu" ; s3="hu" } ;
|
|
AgP3Sg Fem => { s1="ha" ; s2="hie" ; s3="hi" } ;
|
|
AgP1 Pl => { s1="na" ; s2="nie" ; s3="hi" } ;
|
|
AgP2 Pl => { s1="kom" ; s2="kom" ; s3="kom" } ;
|
|
AgP3Pl => { s1="hom" ; s2="hom" ; s3="hom" }
|
|
} ;
|
|
|
|
-- Indirect object clitic
|
|
IndObjVerbClitic : Type = {
|
|
s1 : Str ; -- ftaħt-ilha
|
|
s2 : Str ; -- ftaħnie-lha
|
|
s3 : Str ; -- ftaħt-ilhiex
|
|
s4 : Str ; -- ftaħnie-lhiex
|
|
} ;
|
|
|
|
-- Only for_Prep causes these to be used, thus it doesn't make sense to store this
|
|
-- information in Prep.
|
|
indObjSuffix : Agr -> IndObjVerbClitic = \agr' ->
|
|
let agr : VAgr = toVAgr agr' in
|
|
case agr of {
|
|
-- IO IO + Neg IO IO + Neg
|
|
AgP1 Sg => { s1="li" ; s2="li" ; s3="li" ; s4="li" } ;
|
|
AgP2 Sg => { s1="lek" ; s2="lek" ; s3="lok" ; s4="lok" } ;
|
|
AgP3Sg Masc => { s1="lu" ; s2="lu" ; s3="lu" ; s4="lu" } ;
|
|
AgP3Sg Fem => { s1="lha" ; s2="lhie" ; s3="ilha" ; s4="ilhie" } ;
|
|
AgP1 Pl => { s1="lna" ; s2="lnie" ; s3="ilna" ; s4="ilnie" } ;
|
|
AgP2 Pl => { s1="lkom" ; s2="lkom" ; s3="ilkom" ; s4="ilkom" } ;
|
|
AgP3Pl => { s1="lhom" ; s2="lhom" ; s3="ilhom" ; s4="ilhom" }
|
|
} ;
|
|
|
|
-- Produce stem variants as needed (only call on compile-time strings!)
|
|
-- Refer to doc/stems.org
|
|
stemVariantsPerf : Str -> Variants3 = \s ->
|
|
let
|
|
ftahna : Str = s ;
|
|
ftahnie : Str = case s of {
|
|
ftahn + "a" => ftahn + "ie" ;
|
|
fet + h@#Cns + "et" => fet + h + "it" ;
|
|
fet + "aħ" => fet + "ħ" ;
|
|
_ => s
|
|
} ;
|
|
ftahni : Str = case s of {
|
|
ftahn + "a" => ftahn + "i" ;
|
|
_ => ftahnie
|
|
} ;
|
|
in {
|
|
s1 = ftahna ; s2 = ftahnie ; s3 = ftahni ;
|
|
} ;
|
|
|
|
stemVariantsImpf : Str -> Variants3 = \s ->
|
|
let
|
|
jiftah : Str = s ;
|
|
jifth : Str = case s of {
|
|
jift + "aħ" => jift + "ħ" ;
|
|
_ => s
|
|
} ;
|
|
in {
|
|
s1 = jiftah ; s2 = jifth ; s3 = jifth ;
|
|
} ;
|
|
|
|
-- Convert old verb form table into one with stem variants
|
|
stemVariantsTbl : (VForm => Str) -> (VForm => Variants3) = \tbl ->
|
|
\\vf => case vf of {
|
|
VPerf _ => stemVariantsPerf (tbl ! vf) ;
|
|
VImpf _ => stemVariantsImpf (tbl ! vf) ;
|
|
_ => mkVariants3 (tbl ! vf)
|
|
} ;
|
|
|
|
Verb : Type = {
|
|
s : VForm => Variants3 ; --- need to store different "stems" already at verb level (ġera/ġerie/ġeri)
|
|
i : VerbInfo ;
|
|
} ;
|
|
|
|
VerbInfo : Type = {
|
|
class : VClass ;
|
|
form : VDerivedForm ;
|
|
root : Root ; -- radicals
|
|
patt : Pattern ; -- vowels extracted from mamma
|
|
patt2 : Pattern ; -- vowel changes; default to patt (experimental)
|
|
-- in particular, patt2 is used to indicate whether an IE sould be shortened
|
|
-- to an I or an E (same for entire verb)
|
|
imp : Str ; -- Imperative Sg. Gives so much information jaħasra!
|
|
} ;
|
|
|
|
param
|
|
-- Possible verb forms (tense + person)
|
|
VForm =
|
|
VPerf VAgr -- Perfect tense in all pronoun cases
|
|
| VImpf VAgr -- Imperfect tense in all pronoun cases
|
|
| VImp Number -- Imperative is always P2, Sg & Pl
|
|
| VActivePart GenNum -- Present/active particible, e.g. RIEQED
|
|
| VPassivePart GenNum -- Passive/past particible, e.g. MAĦBUB
|
|
-- | VVerbalNoun -- Verbal Noun
|
|
;
|
|
|
|
VDerivedForm =
|
|
FormI
|
|
| FormII
|
|
| FormIII
|
|
| FormIV
|
|
| FormV
|
|
| FormVI
|
|
| FormVII
|
|
| FormVIII
|
|
| FormIX
|
|
| FormX
|
|
| FormUnknown
|
|
;
|
|
|
|
-- Verb classification
|
|
VClass =
|
|
Strong VStrongClass
|
|
| Weak VWeakClass
|
|
| Quad VQuadClass
|
|
| Loan
|
|
| Irregular
|
|
;
|
|
VStrongClass =
|
|
Regular
|
|
| LiquidMedial
|
|
| Geminated
|
|
;
|
|
VWeakClass =
|
|
Assimilative
|
|
| Hollow
|
|
| Lacking
|
|
| Defective
|
|
;
|
|
VQuadClass =
|
|
QStrong
|
|
| QWeak
|
|
;
|
|
|
|
Order =
|
|
ODir -- ĠANNI JIEKOL ĦUT
|
|
| OQuest -- JIEKOL ĦUT ĠANNI [?]
|
|
;
|
|
|
|
|
|
{- Verb Phrase ---------------------------------------------------------- -}
|
|
|
|
oper
|
|
|
|
-- Join verp phrase components into a string
|
|
joinVP : VerbPhrase -> VPForm -> Anteriority -> Polarity -> Str = \vp,form,ant,pol ->
|
|
let
|
|
stems = (vp.s ! form ! ant ! pol).main ;
|
|
aux = (vp.s ! form ! ant ! pol).aux ;
|
|
x : Str = "x" ;
|
|
agr : VAgr = VPForm2VAgr form ;
|
|
dir_a : Agr = fromJust Agr vp.dir ; -- These are lazy
|
|
ind_a : Agr = fromJust Agr vp.ind ;
|
|
dir = dirObjSuffix dir_a ;
|
|
ind = indObjSuffix ind_a ;
|
|
|
|
ind_pos : Str = case <toVAgr dir_a, toVAgr ind_a> of {
|
|
<AgP3Pl, AgP2 Sg> => ind.s3 ; -- hom-lok
|
|
_ => ind.s1 -- hie-lek
|
|
} ;
|
|
ind_neg : Str = case <toVAgr dir_a, toVAgr ind_a> of {
|
|
<AgP3Pl, AgP2 Sg> => ind.s4 ; -- hom-lokx
|
|
_ => ind.s2 -- hie-lekx
|
|
} ;
|
|
in
|
|
case takesAux form ant of {
|
|
|
|
-- aux is already negated for us
|
|
True => aux ++ case <exists Agr vp.dir, exists Agr vp.ind> of {
|
|
|
|
-- konna ftaħna / ma konniex ftaħna
|
|
<False,False> => stems.s1 ;
|
|
|
|
-- konna ftaħnie-ha / ma konniex ftaħni-ha
|
|
<True ,False> => stems.s2 ++ BIND ++ dir.s1 ;
|
|
|
|
-- konna ftaħnie-lha / ma konniex ftaħni-lha
|
|
<False,True > => stems.s2 ++ BIND ++ ind.s1 ;
|
|
|
|
-- konna ftaħni-hie-lha / ma konniex ftaħni-hi-lha
|
|
<True, True > => stems.s3 ++ BIND ++ dir.s2 ++ BIND ++ ind.s1
|
|
|
|
} ;
|
|
|
|
-- No aux part to handle
|
|
False => aux ++ case isPerf form ant of {
|
|
|
|
True => case <exists Agr vp.dir, exists Agr vp.ind, pol> of {
|
|
|
|
-- ftaħna / ftaħnie-x
|
|
<False,False,Pos> => stems.s1 ;
|
|
<False,False,Neg> => stems.s2 ++ BIND ++ x ;
|
|
|
|
-- ftaħnie-ha / ftaħni-hie-x
|
|
<True ,False,Pos> => stems.s2 ++ BIND ++ dir.s1 ;
|
|
<True ,False,Neg> => stems.s3 ++ BIND ++ dir.s2 ++ BIND ++ x ;
|
|
|
|
-- ftaħnie-lha / ftaħni-lhie-x
|
|
<False,True ,Pos> => case <sing agr, femOrPlural ind_a> of {
|
|
<True,True> => stems.s2 ++ BIND ++ ind.s3 ; -- fetħ-ilha
|
|
<False,True> => stems.s2 ++ BIND ++ ind.s1 ; -- ftaħnie-lha
|
|
_ => stems.s1 ++ BIND ++ ind.s1 -- fetaħ-li
|
|
} ;
|
|
<False,True ,Neg> => case <sing agr, femOrPlural ind_a> of {
|
|
<True,True> => stems.s2 ++ BIND ++ ind.s4 ++ BIND ++ x ; -- fetħ-ilhiex
|
|
<False,True> => stems.s3 ++ BIND ++ ind.s2 ++ BIND ++ x ; -- ftaħni-lhiex
|
|
_ => stems.s1 ++ BIND ++ ind.s2 ++ BIND ++ x -- fetaħ-lix
|
|
} ;
|
|
|
|
-- ftaħni-hie-lha / ftaħni-hi-lhie-x
|
|
<True, True ,Pos> => stems.s2 ++ BIND ++ dir.s2 ++ BIND ++ ind_pos ;
|
|
<True, True ,Neg> => stems.s3 ++ BIND ++ dir.s3 ++ BIND ++ ind_neg ++ BIND ++ x
|
|
|
|
} ;
|
|
|
|
False => case <exists Agr vp.dir, exists Agr vp.ind, pol> of {
|
|
|
|
-- jiftaħ / jiftaħ-x
|
|
<False,False,Pos> => stems.s1 ;
|
|
<False,False,Neg> => stems.s1 ++ BIND ++ x ;
|
|
|
|
-- jiftaħ-ha / jiftaħ-hie-x
|
|
<True ,False,Pos> => stems.s1 ++ BIND ++ dir.s1 ;
|
|
<True ,False,Neg> => stems.s1 ++ BIND ++ dir.s2 ++ BIND ++ x ;
|
|
|
|
-- jiftħ-ilha / jiftħ-ilhie-x
|
|
<False,True ,Pos> => case <sing agr, femOrPlural ind_a> of {
|
|
<True,True> => stems.s2 ++ BIND ++ ind.s3 ; -- jiftħ-ilha
|
|
<False,True> => stems.s2 ++ BIND ++ ind.s1 ; -- jiftħu-lha
|
|
_ => stems.s1 ++ BIND ++ ind.s1 -- jiftaħ-li
|
|
} ;
|
|
<False,True ,Neg> => case <sing agr, femOrPlural ind_a> of {
|
|
<True,True> => stems.s2 ++ BIND ++ ind.s4 ++ BIND ++ x ; -- jiftħ-ilhiex
|
|
<False,True> => stems.s2 ++ BIND ++ ind.s2 ++ BIND ++ x ; -- jiftħu-lhiex
|
|
_ => stems.s1 ++ BIND ++ ind.s2 ++ BIND ++ x -- jiftaħ-lix
|
|
} ;
|
|
|
|
-- jiftaħ-hie-lha / jiftaħ-hi-lhie-x
|
|
<True, True ,Pos> => stems.s1 ++ BIND ++ dir.s2 ++ BIND ++ ind_pos ;
|
|
<True, True ,Neg> => stems.s1 ++ BIND ++ dir.s3 ++ BIND ++ ind_neg ++ BIND ++ x
|
|
|
|
}
|
|
}
|
|
} ;
|
|
|
|
-- Does a tense + ant take an auxiliary verb?
|
|
-- This affects where (if) the negation is applied
|
|
-- This is a workaround to avoid having a bool param in VerbParts
|
|
-- Must match with the logic in predV
|
|
takesAux : VPForm -> Anteriority -> Bool = \vpf,ant ->
|
|
case <vpf,ant> of {
|
|
<VPIndicat Pres _, Simul> => False ;
|
|
<VPIndicat Past _, Simul> => False ;
|
|
<VPIndicat Fut _, Simul> => True ;
|
|
<VPIndicat Cond _, Simul> => True ;
|
|
<VPIndicat Pres _, Anter> => False ;
|
|
<VPIndicat Past _, Anter> => True ;
|
|
<VPIndicat Fut _, Anter> => True ;
|
|
<VPIndicat Cond _, Anter> => True ;
|
|
<VPImperat _, _> => False
|
|
} ;
|
|
|
|
-- Does a tense + ant give a perfective verb?
|
|
-- Must match with the logic in predV
|
|
isPerf : VPForm -> Anteriority -> Bool = \vpf,ant ->
|
|
case <vpf,ant> of {
|
|
<VPIndicat Pres _, Simul> => False ;
|
|
<VPIndicat Past _, Simul> => True ;
|
|
<VPIndicat Fut _, Simul> => False ;
|
|
<VPIndicat Cond _, Simul> => False ;
|
|
<VPIndicat Pres _, Anter> => True ;
|
|
<VPIndicat Past _, Anter> => True ;
|
|
<VPIndicat Fut _, Anter> => True ;
|
|
<VPIndicat Cond _, Anter> => False ;
|
|
<VPImperat _, _> => False
|
|
} ;
|
|
|
|
VerbParts : Type = {
|
|
aux : Str ; -- when present, negation is applied here
|
|
main : Variants3 ; -- enclitics always applied here
|
|
} ;
|
|
|
|
mkVerbParts = overload {
|
|
mkVerbParts : Variants3 -> VerbParts = \vs -> { aux = [] ; main = vs } ;
|
|
mkVerbParts : Str -> VerbParts = \m -> { aux = [] ; main = mkVariants3 m } ;
|
|
mkVerbParts : Str -> Variants3 -> VerbParts = \a,vs -> { aux = a ; main = vs } ;
|
|
mkVerbParts : Str -> Str -> VerbParts = \a,m -> { aux = a ; main = mkVariants3 m } ;
|
|
} ;
|
|
|
|
VerbPhrase : Type = {
|
|
s : VPForm => Anteriority => Polarity => VerbParts ;
|
|
s2 : Agr => Str ; -- complement
|
|
dir : Maybe Agr ; -- direct object clitic
|
|
ind : Maybe Agr ; -- indirect object clitic
|
|
} ;
|
|
|
|
SlashVerbPhrase : Type = VerbPhrase ** {c2 : Compl} ;
|
|
|
|
param
|
|
-- [AZ]
|
|
VPForm =
|
|
VPIndicat Tense VAgr
|
|
| VPImperat Number
|
|
;
|
|
|
|
oper
|
|
|
|
insertObj : (Agr => Str) -> VerbPhrase -> VerbPhrase = \obj,vp -> {
|
|
s = vp.s ;
|
|
s2 = \\agr => vp.s2 ! agr ++ obj ! agr ;
|
|
dir = vp.dir ;
|
|
ind = vp.ind ;
|
|
} ;
|
|
|
|
insertObjPre : (Agr => Str) -> VerbPhrase -> VerbPhrase = \obj,vp -> {
|
|
s = vp.s ;
|
|
s2 = \\agr => obj ! agr ++ vp.s2 ! agr ;
|
|
dir = vp.dir ;
|
|
ind = vp.ind ;
|
|
} ;
|
|
|
|
insertObjc : (Agr => Str) -> SlashVerbPhrase -> SlashVerbPhrase = \obj,vp ->
|
|
insertObj obj vp ** {c2 = vp.c2} ;
|
|
|
|
insertDirObj : Agr -> VerbPhrase -> VerbPhrase = \dir,vp -> {
|
|
s = vp.s ;
|
|
s2 = vp.s2 ;
|
|
dir = Just Agr dir ;
|
|
ind = vp.ind ;
|
|
};
|
|
|
|
insertIndObj : Agr -> VerbPhrase -> VerbPhrase = \ind,vp -> {
|
|
s = vp.s ;
|
|
s2 = vp.s2 ;
|
|
dir = vp.dir ;
|
|
ind = Just Agr ind ;
|
|
};
|
|
|
|
insertAdV : Str -> VerbPhrase -> VerbPhrase = \adv,vp -> {
|
|
s = vp.s ;
|
|
s2 = \\agr => vp.s2 ! agr ++ adv ;
|
|
dir = vp.dir ;
|
|
ind = vp.ind ;
|
|
} ;
|
|
|
|
predVc : (Verb ** {c2 : Compl}) -> SlashVerbPhrase = \verb ->
|
|
predV verb ** {c2 = verb.c2} ;
|
|
|
|
copula_kien : {s : VForm => Polarity => Str} = {
|
|
s = \\vform,pol => case <vform,pol> of {
|
|
<VPerf (AgP1 Sg), Pos> => "kont" ;
|
|
<VPerf (AgP2 Sg), Pos> => "kont" ;
|
|
<VPerf (AgP3Sg Masc), Pos> => "kien" ;
|
|
<VPerf (AgP3Sg Fem), Pos> => "kienet" ;
|
|
<VPerf (AgP1 Pl), Pos> => "konna" ;
|
|
<VPerf (AgP2 Pl), Pos> => "kontu" ;
|
|
<VPerf (AgP3Pl), Pos> => "kienu" ;
|
|
<VImpf (AgP1 Sg), Pos> => "nkun" ;
|
|
<VImpf (AgP2 Sg), Pos> => "tkun" ;
|
|
<VImpf (AgP3Sg Masc), Pos> => "jkun" ;
|
|
<VImpf (AgP3Sg Fem), Pos> => "tkun" ;
|
|
<VImpf (AgP1 Pl), Pos> => "nkunu" ;
|
|
<VImpf (AgP2 Pl), Pos> => "tkunu" ;
|
|
<VImpf (AgP3Pl), Pos> => "jkunu" ;
|
|
<VImp (Pl), Pos> => "kun" ;
|
|
<VImp (Sg), Pos> => "kunu" ;
|
|
|
|
<VPerf (AgP1 Sg), Neg> => "kontx" ;
|
|
<VPerf (AgP2 Sg), Neg> => "kontx" ;
|
|
<VPerf (AgP3Sg Masc), Neg> => "kienx" ;
|
|
<VPerf (AgP3Sg Fem), Neg> => "kinitx" ;
|
|
<VPerf (AgP1 Pl), Neg> => "konniex" ;
|
|
<VPerf (AgP2 Pl), Neg> => "kontux" ;
|
|
<VPerf (AgP3Pl), Neg> => "kienux" ;
|
|
<VImpf (AgP1 Sg), Neg> => "nkunx" ;
|
|
<VImpf (AgP2 Sg), Neg> => "tkunx" ;
|
|
<VImpf (AgP3Sg Masc), Neg> => "jkunx" ;
|
|
<VImpf (AgP3Sg Fem), Neg> => "tkunx" ;
|
|
<VImpf (AgP1 Pl), Neg> => "nkunux" ;
|
|
<VImpf (AgP2 Pl), Neg> => "tkunux" ;
|
|
<VImpf (AgP3Pl), Neg> => "jkunux" ;
|
|
<VImp (Pl), Neg> => "kunx" ;
|
|
<VImp (Sg), Neg> => "kunux" ;
|
|
<VActivePart gn, _> => "" ;
|
|
<VPassivePart gn, _> => ""
|
|
}
|
|
} ;
|
|
|
|
-- Adapted from [AZ]
|
|
CopulaVP : VerbPhrase = {
|
|
s = \\vpf,ant,pol =>
|
|
--- We are ignoring the anteriority
|
|
case <vpf, pol> of {
|
|
--- Here we are bypassing VerbParts by putting negatives in the stem
|
|
<VPIndicat Past vagr, Pos> => mkVerbParts (copula_kien.s ! VPerf vagr ! Pos) [] ; -- kien
|
|
<VPIndicat Pres vagr, Pos> => mkVerbParts (copula_kien.s ! VImpf vagr ! Pos) [] ; -- jkun
|
|
<VPIndicat Fut vagr, Pos> => mkVerbParts ("se" ++ copula_kien.s ! VImpf vagr ! Pos) [] ; -- se jkun
|
|
<VPIndicat Cond vagr, Pos> => mkVerbParts ("kieku" ++ copula_kien.s ! VPerf vagr ! Pos) [] ; -- kieku kien
|
|
<VPImperat num, Pos> => mkVerbParts (copula_kien.s ! VImp num ! Pos) [] ; -- kun
|
|
<VPIndicat Past vagr, Neg> => mkVerbParts (copula_kien.s ! VPerf vagr ! Neg) [] ; -- ma kienx
|
|
<VPIndicat Pres vagr, Neg> => mkVerbParts (copula_kien.s ! VImpf vagr ! Neg) [] ; -- ma jkunx
|
|
<VPIndicat Fut vagr, Neg> => mkVerbParts (mhux ! vagr ++ "se" ++ copula_kien.s ! VImpf vagr ! Pos) [] ; -- mhux se jkun
|
|
<VPIndicat Cond vagr, Neg> => mkVerbParts ("kieku" ++ "ma" ++ copula_kien.s ! VPerf vagr ! Neg) [] ; -- kieku ma kienx
|
|
<VPImperat num, Neg> => mkVerbParts (copula_kien.s ! VImp num ! Neg) [] -- kunx
|
|
} ;
|
|
s2 = \\agr => [] ;
|
|
dir = NullAgr ;
|
|
ind = NullAgr ;
|
|
} ;
|
|
|
|
-- [AZ]
|
|
predV : Verb -> VerbPhrase = \verb -> {
|
|
s = \\vpf,ant,pol =>
|
|
let
|
|
ma = makePreVowel "ma" "m'" ;
|
|
b1 : Variants3 -> VerbParts = \vs -> mkVerbParts vs ;
|
|
b2 : Str -> Variants3 -> VerbParts = \s,vs -> mkVerbParts s vs ;
|
|
in
|
|
case vpf of {
|
|
VPIndicat tense vagr =>
|
|
let
|
|
kien = copula_kien.s ! (VPerf vagr) ! Pos ;
|
|
kienx = copula_kien.s ! (VPerf vagr) ! Neg ;
|
|
nkun = copula_kien.s ! (VImpf vagr) ! Pos ;
|
|
in
|
|
case <tense,ant,pol> of {
|
|
<Pres,Simul,Pos> => b1 (verb.s ! VImpf vagr) ; -- norqod
|
|
<Pres,Simul,Neg> => b2 ma (verb.s ! VImpf vagr) ; -- ma norqodx
|
|
|
|
<Past,Simul,Pos> => b1 (verb.s ! VPerf vagr) ; -- rqadt
|
|
<Past,Simul,Neg> => b2 ma (verb.s ! VPerf vagr) ; -- ma rqadtx
|
|
|
|
<Fut, Simul,Pos> => b2 "se" (verb.s ! VImpf vagr) ; -- se norqod
|
|
<Fut, Simul,Neg> => b2 (mhux ! vagr ++ "se") (verb.s ! VImpf vagr) ; -- m'iniex se norqod
|
|
|
|
<Cond, _ ,Pos> => b2 kien (verb.s ! VImpf vagr) ; -- kont norqod
|
|
<Cond, _ ,Neg> => b2 (ma ++ kienx) (verb.s ! VImpf vagr) ; -- ma kontx norqod
|
|
|
|
-- Same as Past Simul
|
|
<Pres,Anter,Pos> => b1 (verb.s ! VPerf vagr) ; -- rqadt
|
|
<Pres,Anter,Neg> => b2 ma (verb.s ! VPerf vagr) ; -- ma rqadtx
|
|
|
|
<Past,Anter,Pos> => b2 kien (verb.s ! VPerf vagr) ; -- kont rqadt
|
|
<Past,Anter,Neg> => b2 (ma ++ kienx) (verb.s ! VPerf vagr) ; -- ma kontx rqadt
|
|
|
|
<Fut, Anter,Pos> => b2 ("se" ++ nkun) (verb.s ! VPerf vagr) ; -- se nkun rqadt
|
|
<Fut, Anter,Neg> => b2 (mhux ! vagr ++ "se" ++ nkun) (verb.s ! VPerf vagr) -- m'iniex se nkun rqadt
|
|
} ;
|
|
VPImperat num => b1 (verb.s ! VImp num) -- torqodx
|
|
};
|
|
s2 = \\agr => [] ;
|
|
dir = NullAgr ;
|
|
ind = NullAgr ;
|
|
} ;
|
|
|
|
-- There is no infinitive in Maltese; use perfective
|
|
infVP : VerbPhrase -> Anteriority -> Polarity -> Agr -> Str = \vp,ant,pol,agr ->
|
|
let
|
|
vpform : VPForm = VPIndicat Past (toVAgr agr) ;
|
|
in
|
|
joinVP vp vpform ant pol ++ vp.s2 ! agr ;
|
|
|
|
Aux = {
|
|
s : Tense => Polarity => Str ;
|
|
} ;
|
|
auxHemm : Aux = {
|
|
s = \\t,p => case <t,p> of {
|
|
<Pres,Pos> => "hemm" ;
|
|
<Pres,Neg> => "m'hemmx" ;
|
|
<Past,Pos> => "kien hemm" ;
|
|
<Past,Neg> => "ma kienx hemm" ;
|
|
<Fut,Pos> => "ħa jkun hemm" ;
|
|
<Fut,Neg> => "mhux ħa jkun hemm" ;
|
|
<Cond,Pos> => "jekk hemm" ;
|
|
<Cond,Neg> => "jekk hemmx"
|
|
}
|
|
} ;
|
|
|
|
reflPron : VAgr => Str = table {
|
|
AgP1 Sg => "lili nnifsi" ;
|
|
AgP2 Sg => "lilek innifsek" ;
|
|
AgP3Sg Masc => "lilu nnifsu" ;
|
|
AgP3Sg Fem => "lila nnifisha" ;
|
|
AgP1 Pl => "lilna nfusna" ;
|
|
AgP2 Pl => "lilkom infuskom" ;
|
|
AgP3Pl => "lilhom infushom"
|
|
} ;
|
|
|
|
mhux : VAgr => Str = table {
|
|
AgP1 Sg => "m'iniex" ;
|
|
AgP2 Sg => "m'intix" ;
|
|
AgP3Sg Masc => "m'hux" ;
|
|
AgP3Sg Fem => "m'hix" ;
|
|
AgP1 Pl => "m'aħniex" ;
|
|
AgP2 Pl => "m'intomx" ;
|
|
AgP3Pl => "m'humiex"
|
|
} ;
|
|
|
|
conjLi : Str = "li" ;
|
|
conjThat = conjLi ;
|
|
|
|
{- Adjecive ------------------------------------------------------------ -}
|
|
|
|
oper
|
|
Adjective : Type = {
|
|
s : AForm => Str ;
|
|
hasComp : Bool ;
|
|
} ;
|
|
|
|
param
|
|
AForm =
|
|
APosit GenNum -- Positive, e.g. SABIĦ
|
|
| ACompar -- Comparative, e.g. ISBAĦ
|
|
| ASuperl -- Superlative, e.g. L-ISBAĦ
|
|
;
|
|
|
|
oper
|
|
-- adjective: Takes all forms (except superlative)
|
|
-- Params:
|
|
-- Masculine, eg SABIĦ
|
|
-- Feminine, eg SABIĦA
|
|
-- Plural, eg SBIEĦ
|
|
-- Comparative, eg ISBAĦ
|
|
mkAdjective : (_,_,_,_ : Str) -> Adjective = \masc,fem,plural,compar -> {
|
|
s = table {
|
|
APosit gn => case gn of {
|
|
GSg Masc => masc ;
|
|
GSg Fem => fem ;
|
|
GPl => plural
|
|
} ;
|
|
ACompar => compar ;
|
|
ASuperl => artDef ++ compar
|
|
} ;
|
|
hasComp = notB (isNil compar) ;
|
|
} ;
|
|
|
|
{- Other ---------------------------------------------------------------- -}
|
|
|
|
oper
|
|
|
|
{- ~~~ Some character classes ~~~ -}
|
|
|
|
Letter : pattern Str = #( "a" | "b" | "ċ" | "d" | "e" | "f" | "ġ" | "g" | "għ" | "h" | "ħ" | "i" | "ie" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "ż" | "z" );
|
|
Consonant : pattern Str = #( "b" | "ċ" | "d" | "f" | "ġ" | "g" | "għ" | "h" | "ħ" | "j" | "k" | "l" | "m" | "n" | "p" | "q" | "r" | "s" | "t" | "v" | "w" | "x" | "ż" | "z" );
|
|
CoronalCons : pattern Str = #( "ċ" | "d" | "n" | "r" | "s" | "t" | "x" | "ż" | "z" ); -- "konsonanti xemxin"
|
|
LiquidCons : pattern Str = #( "l" | "m" | "n" | "r" | "għ" );
|
|
SonorantCons : pattern Str = #( "l" | "m" | "n" | "r" ); -- See {SA pg13}. Currently unused, but see DoublingConsN below
|
|
DoublingConsT : pattern Str = #( "ċ" | "d" | "ġ" | "s" | "x" | "ż" | "z" ); -- require doubling when prefixed with 't', eg DDUM, ĠĠORR, SSIB, TTIR, ŻŻID {GM pg68,2b} {OM pg90}
|
|
DoublingConsN : pattern Str = #( "l" | "m" | "r" ); -- require doubling when prefixed with 'n', eg LLAĦĦAQ, MMUR, RRID {OM pg90}
|
|
StrongCons : pattern Str = #( "b" | "ċ" | "d" | "f" | "ġ" | "g" | "għ" | "h" | "ħ" | "k" | "l" | "m" | "n" | "p" | "q" | "r" | "s" | "t" | "v" | "x" | "ż" | "z" );
|
|
WeakCons : pattern Str = #( "j" | "w" );
|
|
Vowel : pattern Str = #( "a" | "e" | "i" | "o" | "u" );
|
|
VowelIE : pattern Str = #( "a" | "e" | "i" | "ie" | "o" | "u" );
|
|
Digraph : pattern Str = #( "ie" );
|
|
SemiVowel : pattern Str = #( "għ" | "j" );
|
|
|
|
Vwl = Vowel ;
|
|
Cns = Consonant ;
|
|
LCns = LiquidCons ;
|
|
|
|
EorI : Str = "e" | "i" ;
|
|
IorE : Str = "i" | "e" ;
|
|
|
|
{- ~~~ Roots & Patterns ~~~ -}
|
|
|
|
Pattern : Type = {V1, V2 : Str} ;
|
|
Root : Type = {C1, C2, C3, C4 : Str} ;
|
|
|
|
-- Make a root object. Accepts following overloads:
|
|
-- mkoot (empty root)
|
|
-- mkRoot "k-t-b" / mkRoot "k-t-b-l"
|
|
-- mkRoot "k" "t" "b"
|
|
-- mkRoot "k" "t" "b" "l"
|
|
mkRoot : Root = overload {
|
|
mkRoot : Root =
|
|
{ C1=[] ; C2=[] ; C3=[] ; C4=[] } ;
|
|
mkRoot : Str -> Root = \s ->
|
|
case toLower s of {
|
|
c1 + "-" + c2 + "-" + c3 + "-" + c4 => { C1=c1 ; C2=c2 ; C3=c3 ; C4=c4 } ; -- "k-t-b-l"
|
|
c1 + "-" + c2 + "-" + c3 => { C1=c1 ; C2=c2 ; C3=c3 ; C4=[] } ; -- "k-t-b"
|
|
_ => Predef.error("Cannot make root from:"++s)
|
|
} ;
|
|
mkRoot : Str -> Str -> Str -> Root = \c1,c2,c3 ->
|
|
{ C1=toLower c1 ; C2=toLower c2 ; C3=toLower c3 ; C4=[] } ;
|
|
mkRoot : Str -> Str -> Str -> Str -> Root = \c1,c2,c3,c4 ->
|
|
{ C1=toLower c1 ; C2=toLower c2 ; C3=toLower c3 ; C4=toLower c4 } ;
|
|
} ;
|
|
|
|
mkPattern : Pattern = overload {
|
|
mkPattern : Pattern =
|
|
{ V1=[] ; V2=[] } ;
|
|
mkPattern : Str -> Pattern = \v1 ->
|
|
{ V1=toLower v1 ; V2=[] } ;
|
|
mkPattern : Str -> Str -> Pattern = \v1,v2 ->
|
|
{ V1=toLower v1 ; V2=case v2 of {"" => [] ; _ => toLower v2}} ;
|
|
} ;
|
|
|
|
-- Extract first two vowels from a token (designed for semitic verb forms)
|
|
--- potentially slow
|
|
extractPattern : Str -> Pattern = \s ->
|
|
case s of {
|
|
v1@"ie" + _ + v2@#Vowel + _ => mkPattern v1 v2 ; -- IEQAF
|
|
v1@#Vowel + _ + v2@#Vowel + _ => mkPattern v1 v2 ; -- IKTEB
|
|
_ + v1@"ie" + _ + v2@#Vowel + _ => mkPattern v1 v2 ; -- RIEQED
|
|
_ + v1@"ie" + _ => mkPattern v1 ; -- ŻIED
|
|
_ + v1@#Vowel + _ + v2@#Vowel + _ => mkPattern v1 v2 ; -- ĦARBAT
|
|
_ + v1@#Vowel + _ => mkPattern v1 ; -- ĦOBB
|
|
_ => mkPattern
|
|
} ;
|
|
|
|
-- Create a VerbInfo record, optionally omitting various fields
|
|
mkVerbInfo : VerbInfo = overload {
|
|
mkVerbInfo : VClass -> VDerivedForm -> VerbInfo = \c,f ->
|
|
{ class=c ; form=f ; root=mkRoot ; patt=mkPattern ; patt2=mkPattern ; imp=[] } ;
|
|
mkVerbInfo : VClass -> VDerivedForm -> Str -> VerbInfo = \c,f,i ->
|
|
{ class=c ; form=f ; root=mkRoot ; patt=mkPattern ; patt2=mkPattern ; imp=i } ;
|
|
mkVerbInfo : VClass -> VDerivedForm -> Root -> Pattern -> VerbInfo = \c,f,r,p ->
|
|
{ class=c ; form=f ; root=r ; patt=p ; patt2=p ; imp=[] } ;
|
|
mkVerbInfo : VClass -> VDerivedForm -> Root -> Pattern -> Str -> VerbInfo = \c,f,r,p,i ->
|
|
{ class=c ; form=f ; root=r ; patt=p ; patt2=p ; imp=i } ;
|
|
mkVerbInfo : VClass -> VDerivedForm -> Root -> Pattern -> Pattern -> Str -> VerbInfo = \c,f,r,p,p2,i ->
|
|
{ class=c ; form=f ; root=r ; patt=p ; patt2=p2 ; imp=i } ;
|
|
} ;
|
|
|
|
-- Change certain fields of a VerbInfo record
|
|
updateVerbInfo : VerbInfo = overload {
|
|
|
|
-- Root
|
|
updateVerbInfo : VerbInfo -> Root -> VerbInfo = \i,r ->
|
|
{ class=i.class ; form=i.form ; root=r ; patt=i.patt ; patt2=i.patt2 ; imp=i.imp } ;
|
|
|
|
-- DerivedForm
|
|
updateVerbInfo : VerbInfo -> VDerivedForm -> VerbInfo = \i,f ->
|
|
{ class=i.class ; form=f ; root=i.root ; patt=i.patt ; patt2=i.patt2 ; imp=i.imp } ;
|
|
|
|
-- DerivedForm, Imperative
|
|
updateVerbInfo : VerbInfo -> VDerivedForm -> Str -> VerbInfo = \i,f,imp ->
|
|
{ class=i.class ; form=f ; root=i.root ; patt=i.patt ; patt2=i.patt2 ; imp=imp } ;
|
|
|
|
} ;
|
|
|
|
{- ~~~ Useful helper functions ~~~ -}
|
|
|
|
-- New names for the drop/take operations
|
|
takePfx = Predef.take ;
|
|
dropPfx = Predef.drop ;
|
|
takeSfx = Predef.dp ;
|
|
dropSfx = Predef.tk ;
|
|
|
|
-- Get the character at the specific index (0-based).
|
|
-- Negative indices behave as 0 (first character). Out of range indexes return the empty string.
|
|
charAt : Int -> Str -> Str ;
|
|
charAt i s = takePfx 1 (dropPfx i s) ;
|
|
|
|
-- Delete character at the specific index (0-based).
|
|
-- Out of range indices are just ignored.
|
|
delCharAt : Int -> Str -> Str ;
|
|
delCharAt i s = (takePfx i s) + (dropPfx (plus i 1) s) ;
|
|
|
|
-- -- Replace first substring
|
|
-- replace : Str -> Str -> Str -> Str ;
|
|
-- replace needle haystack replacement =
|
|
-- case haystack of {
|
|
-- x + needle + y => x + replacement + y ;
|
|
-- _ => haystack
|
|
-- } ;
|
|
|
|
-- Prefix with a 'n'/'t' or double initial consonant, as necessary. See {OM pg 90}
|
|
pfx_N : Str -> Str = \s -> case s of {
|
|
"" => [] ;
|
|
m@#DoublingConsN + _ => m + s ;
|
|
_ => "n" + s
|
|
} ;
|
|
pfx_T : Str -> Str = \s -> case s of {
|
|
"" => [] ;
|
|
d@#DoublingConsT + _ => d + s ;
|
|
_ => "t" + s
|
|
} ;
|
|
pfx_J : Str -> Str = \s -> pfx "j" s ;
|
|
|
|
-- Generically prefix a string (avoiding empty strings)
|
|
pfx : Str -> Str -> Str = \p,s -> case <p,s> of {
|
|
<_, ""> => [] ;
|
|
<"", str> => str ;
|
|
<px, str> => px + str
|
|
} ;
|
|
|
|
-- Add suffix, avoiding triple letters {GO pg96-7}
|
|
--- add more cases?
|
|
--- potentially slow
|
|
sfx : Str -> Str -> Str = \a,b ->
|
|
case <a,takePfx 1 b> of {
|
|
<"",_> => [] ;
|
|
<ke+"nn","n"> => ke+"n"+b ;
|
|
<ha+"kk","k"> => ha+"k"+b ;
|
|
<ho+"ll","l"> => ho+"l"+b ;
|
|
<si+"tt","t"> => si+"t"+b ;
|
|
<be+"xx","x"> => be+"x"+b ;
|
|
_ => a + b
|
|
} ;
|
|
|
|
-- Replace any IE in the word with an I or E --- potentially slow
|
|
ie2i : Str -> Str = ie2_ "i" ;
|
|
ie2e : Str -> Str = ie2_ "e" ;
|
|
ie2_ : Str -> Str -> Str = \iore,serviet ->
|
|
case serviet of {
|
|
x + "ie" => x + iore ;
|
|
x + "ie" + y => x + iore + y ;
|
|
x => x
|
|
} ;
|
|
|
|
-- Is a word mono-syllabic?
|
|
--- potentially slow
|
|
isMonoSyl : Str -> Bool = \s ->
|
|
case s of {
|
|
#Consonant + ("ie" | #Vowel) => True ; -- ra
|
|
#Consonant + #Consonant + ("ie" | #Vowel) => True ; -- bla
|
|
|
|
("ie" | #Vowel) + #Consonant => True ; -- af
|
|
("ie" | #Vowel) + #Consonant + #Consonant => True ; -- elf
|
|
|
|
#Consonant + ("ie" | #Vowel) + #Consonant => True ; -- miet
|
|
#Consonant + ("ie" | #Vowel) + #Consonant + #Consonant => True ; -- mort
|
|
#Consonant + #Consonant + ("ie" | #Vowel) + #Consonant => True ; -- ħliet
|
|
#Consonant + #Consonant + ("ie" | #Vowel) + #Consonant + #Consonant => True ; -- ħriġt
|
|
_ => False
|
|
} ;
|
|
|
|
artIndef : Str = "" ;
|
|
|
|
artDef : Str =
|
|
makePreFull
|
|
"il-" -- il-ktieb
|
|
"i" -- it-triq
|
|
"l-" -- l-ajruplan
|
|
;
|
|
|
|
-- Make a pre string which only varies for vowels
|
|
makePreVowel : Str -> Str -> Str = \cons,vowel ->
|
|
let
|
|
vowel' : Str = case vowel of {
|
|
_ + "'" => vowel ++ BIND ;
|
|
_ => vowel
|
|
} ;
|
|
in
|
|
pre {
|
|
-- Consonant
|
|
cons ;
|
|
-- Vowel
|
|
vowel' / strs { "a" ; "e" ; "i" ; "o" ; "u" ; "h" ; "għ" }
|
|
} ;
|
|
|
|
-- Make a pre string which varies coronal consonants and vowels
|
|
makePreFull : Str -> Str -> Str -> Str = \cons,corcons,vowel ->
|
|
let
|
|
mal = cons ++ BIND ;
|
|
m' = vowel ++ BIND ;
|
|
ma = corcons ;
|
|
in
|
|
pre {
|
|
-- Regular consonant
|
|
mal ;
|
|
-- Vowel
|
|
m' / strs { "a" ; "e" ; "i" ; "o" ; "u" ; "h" ; "għ" } ;
|
|
-- Coronal consonants
|
|
ma+"ċ-" ++ BIND / strs { "ċ" } ;
|
|
ma+"d-" ++ BIND / strs { "d" } ;
|
|
ma+"n-" ++ BIND / strs { "n" } ;
|
|
ma+"r-" ++ BIND / strs { "r" } ;
|
|
ma+"s-" ++ BIND / strs { "s" } ;
|
|
ma+"t-" ++ BIND / strs { "t" } ;
|
|
ma+"x-" ++ BIND / strs { "x" } ;
|
|
ma+"ż-" ++ BIND / strs { "ż" } ;
|
|
ma+"z-" ++ BIND / strs { "z" }
|
|
} ;
|
|
|
|
}
|