packages feed

FM-SBLEX-3.0: src/saldo/TestSw.hs

module TestSw (sal_id_exceptions, tests) where

import General
import List
import Frontend
import Char
import Maybe
import TestGenSw
import qualified Data.Set as Set


sal_id_exceptions :: [(String,String)]
sal_id_exceptions = [("lova_2..vb.1","lova_1..vb.1"),
                     ("kola_2..vb.1","kola_1..vb.1"),
                     ("förslag_2..nn.1","förslag_1..nn.1"),
                     ("förlag_2..nn.1","förlag_1..nn.1"),
                     ("fris_2..nn.1","fris_1..nn.1"),
                     ("bildrulle_2..nn.1","bildrulle_1..nn.1"),
                     ("jaja_2..in.1","jaja_1..in.1"),
                     ("oskyld_2..av.1","oskyld_1..av.1"),
                    ("väl_2..ab.1","väl_1..ab.1"),
                    ("förut_2..ab.1","förut_1..ab.1"),
                     ("förklistra_2..vb.1","förklistra_1..vb.1"),
                     ("förklistring_2..nn.1","förklistring_1..nn.1")
                    ]

tests :: (PositiveTests, NegativeTests)
tests = (pos,neg)
 where 
 pos = pos_gen_rules ++ pos_noun_rules ++ pos_verb_rules ++ pos_adj_rules
 neg = neg_gen_rules ++ neg_noun_rules ++ neg_verb_rules ++ neg_adj_rules

-- General rules
pos_gen_rules = [pos_id_para, multi_word, head_lemma,paradigm_pos]

neg_gen_rules = [three_of_same, symbols, mmn,mmr,nnt,sms_missing_hyphen,end_with_h]

-- Is POS in lemma id = paradigm id?
pos_id_para :: TestInput -> Result
pos_id_para t 
 | not ( is_a_word t) = pass
 | p_pos t == id_pos t = pass
 | otherwise           = message t "lemma_id pos - paradigm pos mismatch"
 
-- Have the multi words more than one word?
multi_word :: TestInput -> Result
multi_word t
 | not (is_multi_word t)                             = pass
 | length (words (thead t)) > 1                      = pass
 | otherwise                                         = message t "singleton multi word"

--  Is head == lemma id head?
head_lemma :: TestInput -> Result
head_lemma t 
 | not ( is_a_word t) = pass
 | elem (tid t) ["SS_433..pmm.1"]                = pass
 | isDigit (last (thead t))                      = pass
 | norm_id_lemma t == head_to_lemma_id t         = pass
 | otherwise                                     = message t "lemma_id_head - head mismatch"

-- paradigm pos == pos?
paradigm_pos :: TestInput -> Result
paradigm_pos t
 | not ( is_a_word t) = pass
 | p_pos t == tcat t = pass
 | otherwise = message t "paradigm_pos - pos mismatch"

-- every word, with some exceptions, should contain a vowel.
contains_vowel :: TestInput -> Result
contains_vowel t
  | is_abbr t || elem (tcat t) ["nl","in"]            = pass
  | Set.member (tid t) exception                      = pass
  | length (thead t) <= 1                             = pass
  | or [is_vowel c | c <- w t] || null (w t)          = pass
  | otherwise                                         = message t "no vowel"
 where exception = Set.fromList ["cp..av.1","_-273_·B0C..nnm.1", "MP3..nn.1","mp3..nn.1", "T9..nn.1","_1984..pm.1", "SS_433..pmm.1","f_n..abm.1","m_m..abm.1", "s_k..avm.1","m._fl...abm.1","f._Kr...abm.1","f._d...avm.1","f_Kr..abm.1"]

-- every word, with some exceptions, should contain a consonant.
contains_consonant :: TestInput -> Result
contains_consonant t
 | not ( is_a_word t) = pass
 | is_abbr t || (tcat t) == "nl"                = pass
 | length (thead t) <= 1                        = pass
 | elem (tid t) ["Io..pm.1","_1984..pm.1"]      = pass
 | or [is_consonant c | c <- w t] || null (w t) = pass
 | otherwise                                    = message t "no consonant"

-- not three of same.
three_of_same :: TestInput -> Result
three_of_same t
 | elem (tid t) ["Gustav_III..pmm.1"] = pass
 | is_abbr t || (tcat t) == "nl" = pass
 | traverse (w t) 
    $ \s -> (case s of 
              (c:c1:c2:_) | (c == c1) && (c1 == c2) && not (isDigit c) -> True
              _           -> False) = message t "three of same"
 | otherwise = pass

-- no consecutive symbols.
symbols :: TestInput -> Result
symbols t
 | elem (tid t) ["HCO3-..nna.1","OH-..nna.1","e-..nna.1"] = pass
 | traverse (w t) 
   $ \s -> (case s of 
             (c:c1:_) | c == c1 && elem c "-:\"+." -> True
             _        -> False) = message t "consecutive symbols"
 | otherwise = pass


-- no mmn substring.
mmn :: TestInput -> Result
mmn t
 | member_str "mmn" (w t) = message t "found 'mmn' substring"
 | otherwise                         = pass

-- no mmr substring.
mmr :: TestInput -> Result
mmr t
 | member_str "mmr" (w t) = message t "found 'mmr' substring"
 | otherwise                         = pass


nnt :: TestInput -> Result
nnt t
 | isSuffixOf "nnt" (w t) = message t "found 'nnt' suffix"
 | isSuffixOf "nnte" (w t) = message t "found 'nnte' suffix"
 | otherwise                         = pass

-- Noun Rules
pos_noun_rules = [decl1,decl2,decl3,decl4,decl5,decl7,missing_noun_cases,paradigm_gender,plural_def]

neg_noun_rules = [decl0,no_sing, gender_d,medial_compound,gender_u,gender_n]

no_sing :: TestInput -> Result
no_sing t
 | is_a_word t && (tcat t == "nn" || tcat t == "nnm") && (gender t 'p' || gender t 'd') && param t ["sg"] = message t "invalid singular"
 | otherwise = pass


plural_def :: TestInput -> Result
plural_def t 
 | gender t 'u' && elem '7' (tpara t) = pass
 | Set.member (tpara t) (Set.fromList ["nn_6n_frx", "nn_vu_scarf", "nn_6u_gås","nn_6u_mus","nn_6u_man","nn_6u_vaktman","nn_vu_trio","nn_vu_yard","nn_6u_tum","nn_6u_iktus","nn_vu_romkom","nn_vu_tortilla",
                                       "nn_vu_promovend", "nn_ou_emeritus", "nn_vu_playboy","nn_vu_partner","nn_vu_blinker","nn_6u_yen",
                                       "nn_ou_penny","nn_vu_bagis","nn_vu_glass","nn_vu_mikron","nn_vu_kart"]) = pass 
 | is_a_word t && (tcat t == "nn") && param t ["def","pl","nom"] && 
   gender t 'u' && not (isSuffixOf "na" (w t)) = message t $ "invalid definite plural"
 | is_a_word t && (tcat t == "nn") && param t ["def","pl","nom"] && 
   gender t 'n' && not (isSuffixOf "a" (w t) || isSuffixOf "en" (w t)) = message t $ "invalid definite plural"
 | is_a_word t && param t ["pl"] && (isSuffixOf "aor" (w t) || isSuffixOf "aorna" (w t)) = message t $ "invalid 'a'"
 -- | is_a_word t && param t ["pl"] && (isSuffixOf "ear" (w t) || isSuffixOf "earna" (w t)) = message t $ "invalid 'e'"
 | otherwise = pass

in_declension :: TestInput -> Char -> String -> Result
in_declension t c suff
 | is_a_word t && (tcat t == "nn") && decl t c && param t ["indef","pl","nom"] && not (isSuffixOf suff (w t)) = message t $ "invalid plural in declension " ++ [c]
 | otherwise = pass

not_in_declension :: TestInput -> Char -> [String] -> Result
not_in_declension t c xs
 | is_a_word t && (tcat t == "nn") && decl t c && param t xs = message t $ "invalid \"" ++ unwords xs ++ "\" in declension " ++ [c]
 | otherwise = pass

decl1 t = in_declension t '1' "or"
decl2 t = in_declension t '2' "ar"
decl3 t = in_declension t '3' "er"
decl4 t = in_declension t '4' "r"
decl5 t = in_declension t '5' "n"
decl7 t = in_declension t '7' "s"

decl0 t 
 | tcat t == "nn" = not_in_declension t '0' ["pl"]
 | otherwise      = pass

gender_d t
 | is_a_word t && gender t 'd' && not (param t ["pl","def"]) = message t  "gender 'd' implies pl def"
 | otherwise                                                 = pass

gender_u t
 | elem (tpara t) ["nn_0u_praxis", "nn_0u_samverkan"] = pass
 | last (tcat t) == 'm' = pass 
 | is_a_word t && gender t 'u' && (param t ["sg","def","nom"]) && (last (w t) == 't') = message t  " invalid sg def form"
 | otherwise                                                   =   pass


gender_n t
 | elem (tpara t) ["nn_6n_deponens","nn_6n_aber","nn_3n_dominion","nn_0n_gluten","nn_0u_praxis","nn_0n_bitumen"] = pass
 | last (tcat t) == 'm' = pass 
 | is_a_word t && gender t 'n' && (param t ["sg","def","nom"]) && (last (w t) == 'n') = message t  " invalid sg def form"
 | otherwise                                                   =   pass


medial_compound t 
  | is_a_word t && param t ["cm"] &&  last (w t) == 's' && bad_medials (w t) = message t  "invalid binding s"
  | otherwise                                        = pass
 where bad_medials = f . reverse . take 2 . reverse . init
       f [_,'x'] = True
       f [_,'z'] = True
       f ['s',x] = is_consonant x
       f ['x',x] = is_consonant x
       f _       = False

sms_missing_hyphen t
 | is_a_word t && param t ["sms"] && not (last (w t) == '-') = message t "missing hyphen in sms"
 | otherwise                                                 = pass


-- (x:y:_) | ((is_consonant x) && y == 's') || ((is_consonant x) && y == 'x') || [y,x] == "ch" || x=='x' || x =='z' -> []
-- decli t = not_in_declension t 'i' ["gen"]

missing_noun_cases :: TestInput -> Result
missing_noun_cases t
 -- | param t ["ci"] || param t ["cm"] = pass
  | elem (tpara t) ["nna_6n_kg","nn_6u_mat"] = pass 
  | not_a_word t && (tcat t == "nn" || tcat t == "nna") &&  
    elem (head (p_annotation t)) "1234567" && (not (gender t 'p' || gender t 'd')) = message t "missing noun case"
  | otherwise                                = pass

paradigm_gender :: TestInput -> Result
paradigm_gender t
 | elem (tcat t) ["nn","nna","nnm"] = if gender t (head (head (tinhs t))) then pass else message t "paradigm gender-gender mismatch"
 | otherwise = pass

--- Verb Rules
pos_verb_rules = [conj1, conj2, conj3, pret_part,konj]
neg_verb_rules = [no_pret_part, deponens,mms,end_with_h,konj_e, konj_2_es,verb_ending]

in_conjugation :: TestInput -> Char -> String -> String -> Result
in_conjugation t c suff suff2
 | is_a_word t && (tcat t == "vb") && conj t c && param t ["pres","ind","aktiv"] && not (isSuffixOf suff (w t))  = message t $ "invalid ending in conjugation " ++ [c]
 | is_a_word t && (tcat t == "vb") && conj t c && param t ["pret","ind","aktiv"] && not (isSuffixOf suff2 (w t)) = message t $ "invalid ending in conjugation " ++ [c]
 | otherwise = pass

conj1 t = in_conjugation t '1' "ar" "ade"
conj2 t 
 | elem (tid t) ["tåla..vb.1","må..vb.2"] = pass
 | otherwise = in_conjugation t '2' "r"  ""
conj3 t = in_conjugation t '3' "r"  "de"
conj4 t = in_conjugation t '4' "er" ""

konj :: TestInput -> Result
konj t
 | Set.member (tpara t) (Set.fromList ["vb_4m_förevara","vb_4m_angå","vb_4m_le","vb_4m_stå","vb_vm_undvara","vb_vm_samvara",
                                       "vb_va_gälla_kastrera",
                                       "vb_vm_drösa","vb_va_utlöpa","vb_va_träda","vb_va_snusmala","vb_va_nästa","vb_va_mala",
                                       "vb_4a_slå","vb_4a_se","vb_4a_emotstå","vb_4a_bestå","vb_va_förse","vb_vm_avvara", "vb_va_tälja",
                                      "vb_va_två","vb_va_förmäla","vb_va_tala","vb_va_koka","vb_va_klä","vb_va_bringa"]) = pass
 | not_a_word t && tcat t == "vb" && (conj t '4' || conj t 'v') && param t ["konj", "aktiv"] && not (is_verb_sd t) = message t "missing konj"
 | otherwise                            = pass

konj_e :: TestInput -> Result
konj_e t
 | is_a_word t &&  tcat t == "vb" && param t ["konj", "aktiv"]  && (last (w t) /= 'e') = message t "missing 'e' on konj"
 | otherwise                            = pass

end_with_h :: TestInput -> Result
end_with_h t
 | is_a_word t && tcat t == "vb" &&  elem (dp 2 (w t)) ["ch","sh"] = pass
 | is_a_word t && tcat t == "vb" && last (w t) == 'h' = message t "word ending with h"
 | otherwise                        = pass

verb_ending :: TestInput -> Result
verb_ending t
 | tpara t == "vb_0d_lyster" = pass 
 | is_a_word t && tcat t == "vb" &&  not (is_vowel (last (thead t)) || (last (thead t)) == 's') = message t "verb baseform not ending with vowel or 's'"
 | otherwise                        = pass

konj_2_es :: TestInput -> Result
konj_2_es t
 | is_a_word t && tcat t == "vb" && conj t '2' && (param t ["s-form","pres"]) && 
   ((dp 2 (w t)) /= "es") && (dp 1 (tk 1 (thead t)) == "s") = message t "s-form not ending with 'es' in conj. 2"
 | otherwise                        = pass

deponens t 
 | param t ["pret_part"] || param t ["pres_part"] || param t ["imper"] = pass
 | is_a_word t && tcat t == "vb" = case p_annotation t of
                     (_:'s':_) | not (param t ["s-form"]) -> message t $ "invalid deponent"
                     _ -> pass
 | otherwise = pass

is_deponens t =  case p_annotation t of
                   (_:'s':_) -> True
                   _        -> False

no_pret_part :: TestInput -> Result
no_pret_part t
 | is_a_word t && is_no_pret_part t && param t ["pret_part"]  = message t "invalid participle"
 | otherwise = pass

pret_part :: TestInput -> Result
pret_part t
 | not_a_word t && is_pret_part t && param t ["pret_part"] = message t "missing participle"
 | otherwise = pass

vbm_paradigm :: TestInput -> Result
vbm_paradigm t
 | tcat t == "vbm" = 
     case p_annotation t of
       (x:y:a:_) | elem x "01234ov" && elem y "asmd" && elem a "pldztq" -> pass
       _ -> message t "invalid vbm paradigm identifier"
 | otherwise = pass

-- no mms suffix.
mms :: TestInput -> Result
mms t
 | (tcat t == "vb") && isSuffixOf "mms" (w t) = message t "mms suffix"
 | otherwise                                  = pass

-- Adjective Rules
pos_adj_rules = [komp]
neg_adj_rules = [no_komp,no_genitive_avm]

no_komp :: TestInput -> Result
no_komp t
 | is_a_word t && is_no_komp t && not (null [x | x <- (tparam t), elem x ["komp","super"]]) = message t "invalid comparative"
 | otherwise                            = pass

komp :: TestInput -> Result
komp t
 | elem (tpara t) ["avm_1p1_bred","avm_1p1_akut"] && param t ["gen"] = pass
 | not_a_word t && is_komp t && not (null [x | x <- (tparam t), elem x ["komp","super"]]) = message t "missing comparative"
 | otherwise                            = pass

no_genitive_avm :: TestInput -> Result
no_genitive_avm t
 | is_a_word t && tcat t == "avm" = 
     case p_annotation t of
       (_:'p':_) | elem "gen" (tparam t) -> message t "invalid genitive"
       _ -> pass
 | otherwise = pass