packages feed

lojysamban-0.0.8.1: src/LojysambanLib.hs

{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE PatternGuards #-}

module LojysambanLib (ask, readRules, end) where

import LojbanTools
import Prolog2 hiding (ask)
import qualified Prolog2 as P
import Language.Lojban.Parser hiding (LA, Brivla, KOhA, GOhA, NA, LerfuString, LI, Term)
import qualified Language.Lojban.Parser as P
import Data.Maybe
import Data.Either
import Data.List
import Control.Arrow
import Control.Applicative

end :: String -> Bool
end = isFAhO
ask :: String -> [Rule Scope Atom] -> Maybe String
ask = question

isFAhO :: String -> Bool
isFAhO src
	| Right (TopText _ _ _ _ _ (Just (_, "fa'o"))) <- parse src = True
	| otherwise = False

readRules :: String -> [Rule Scope Atom]
readRules = map readSentence . getSentences . (\(Right p) -> p) . parse

readQuestion :: String -> Fact Scope Atom
readQuestion =
	(\(Left q) -> q) . readSentenceFact . either (error . show) id . parse

isCOhO :: String -> Bool
isCOhO = isCOhO' . either (error . show) id . parse

isCOhO' :: Sentence -> Bool
isCOhO' (TopText _ _ [VocativeSumti [(_, "co'o", _)] _ _] _ _ _) = True
isCOhO' _ = False

question :: String -> [Rule Scope Atom] -> Maybe String
question q r = if isCOhO q then Nothing else Just $ question' q r

question' :: String -> [Rule Scope Atom] -> String
question' = ask1 . readQuestion

ask1 :: Fact Scope Atom -> [Rule Scope Atom] -> String
ask1 q rules =
	let	answer = P.ask [] [] q rules
		answer2_1 = unwords $ intersperse ".ija" $ map unwords $ filter ((> 2) . length) $
			map (intersperse ".ije" . map showPair .
			filter (not . isMA . fst) . regularization . onlyTopVars) answer
		answer2 = unwords $ intersperse ".ija" $ map unwords $ filter ((> 2) . length) $
			map ((\ret -> "tu'e" : intersperse ".ije" ret ++ ["tu'u"]) .
				map showPair . filter (not . isMA . fst) .
					regularization . onlyTopVars) answer
--	print answer
--	print answer2_1
--	print answer2
--	putStr ".i "
		result1 = ".i " ++ case answer of
			[] -> "nago'i"
			_ -> case intersperse ".a" $ mapMaybe
				((showAtom <$>) . maValue) answer of
				[] -> if null answer2 then "go'i" else ""
				m -> unwords m
	in
--	show answer ++ "\n" ++
--	show (q []) ++
	result1 ++ if null answer2 then "" else
		"\n.i " ++ if length answer == 1 then answer2_1 else answer2

showAtom :: Atom -> String
showAtom (LA n) = "la " ++ n
showAtom (LO n) = "lo " ++ n
showAtom (LI n) = "li " ++ show n
showAtom (ListA []) = "lo kunti"
showAtom (ListA ns) = unwords $ intersperse "ce'o" $ map showAtom ns
showAtom o = error $ "showAtom: " ++ show o

maValue :: Result Scope Atom -> Maybe Atom
maValue r = case filter (not . null . fst) $ map (first $ filter isMA) r of
	[] -> Nothing
	((_, tv) : _) -> flip (<$>) tv $ \tv' -> case tv' of
		Con v -> v
		List vs -> ListA $ map (\(Con v) -> v) $ vs
		c@(Cons _ _) -> ListA $ map (\(Con v) -> v) $
			(\(List vs) -> vs) $ getList c r
		o -> error $ "maValue: " ++ show o ++ " r = " ++ show r

getList :: (Show sc, Show s, Eq sc, Eq s) => Term sc s -> Result sc s -> Term sc s
getList l@(List _) _ = l
getList (Cons v var@(Var _ _)) r
--	| List vs <- var = List $
--		v : vs
	| c@(Cons _ _) <- var,
		List vs <- getList c r = List $ v : vs
getList (Cons v (List vs)) _ = List $ v : vs
getList o _ = error $ "getList: not implemented" ++ show o

isMA :: Term Scope Atom -> Bool
isMA (Var [_] (KOhA "ma")) = True
isMA _ = False

showPair :: (Term Scope Atom, Term Scope Atom) -> String
showPair (Var _ (KOhA k), Con (LO n)) = k ++ " du lo " ++ n
showPair (Var _ (LerfuString l), Con (LO n)) = l ++ " du lo " ++ n
showPair (Var _ (KOhA k), Con (LA n)) = k ++ " du la " ++ n
showPair (Var _ (LerfuString l), Con (LA n)) = l ++ " du la " ++ n
showPair (Var _ (KOhA k), Con (LI n)) = k ++ " du li " ++ show n
showPair (Var _ (LerfuString l), Con (LI n)) = l ++ " du li " ++ show n
showPair (Var _ (LerfuString l), List vs) = l ++ " du " ++ unwords (intersperse "ce'o" $ map showTerm vs)
showPair o = show o

showTerm :: Term Scope Atom -> String
showTerm (Con (LI n)) = "li " ++ show n
showTerm (Con (LA n)) = "la " ++ n
showTerm o = error $ "showTerm: " ++ show o

regularization :: Result sc s -> [(Term sc s, Term sc s)]
regularization [] = []
regularization ((_, Nothing) : rest) = regularization rest
regularization ((vars, Just val) : rest) = map (, val) vars ++ regularization rest

onlyTopVars :: Result Scope s -> Result Scope s
onlyTopVars = filter (not . null . fst) . map (first $ filter isTopVar)

isTopVar :: Term Scope s -> Bool
isTopVar (Var [_] _) = True
isTopVar _ = False

data Atom
	= LA String
	| LO String
	| KOhA String
	| Brivla String
	| GOhA String
	| LerfuString String
	| LI Int
	| ListA [Atom]
	deriving (Show, Eq)

addLI, divLI :: Atom -> Atom -> Atom
addLI (LI x) (LI y) = LI $ x + y
addLI _ _ = error "not number"
divLI (LI x) (LI y) = LI $ x `div` y
divLI _ _ = error "not number"

type Scope = [Int]

readSumti :: Scope -> Sumti -> Term Scope Atom
readSumti _ (P.LA (_, "la", _) _ _ ns _) = Con $ LA $ intercalate "." $ map snd3 ns
readSumti sc (P.LALE (_, "lo", _) _ (SelbriRelativeClauses (Linkargs (P.Brivla
	(_, "terziljmina", _) _) (BE (_, "be", _) _ s1
	(Just (BEI (_, "bei", _) _ s2 _)) _ _)) _) _ _) =
	ApplyOp addLI (readSumti sc s1) (readSumti sc s2)
readSumti sc (P.LALE (_, "lo", _) _ (SelbriRelativeClauses (Linkargs (P.Brivla
	(_, "dilcu", _) _) (BE (_, "be", _) _ s1
	(Just (BEI (_, "bei", _) _ s2 _)) _ _)) _) _ _) =
	ApplyOp divLI (readSumti sc s1) (readSumti sc s2)
readSumti _ (P.LALE (_, "lo", _) _ (SelbriRelativeClauses
	(P.Brivla (_, "kunti", _) _) _) _ _) = List []
readSumti sc (P.LALE (_, "lo", _) _ (SelbriRelativeClauses (Linkargs (P.Brivla
	(_, "selzilvi'u", _) _) (BE (_, "be", _) _ s1
	(Just (BEI (_, "bei", _) _ s2 _)) _ _)) _) _ _) =
	Cons (readSumti sc s1) (readSumti sc s2)
readSumti _ (P.LALE (_, "lo", _) _ st _ _) = Con $ LO $ readSumtiTail st
readSumti sc (P.KOhA (_, k, _) _) = Var sc $ KOhA k
readSumti sc (P.LerfuString s _ _) = Var sc $ LerfuString $ concatMap snd3 s
readSumti _ (P.LI (_, "li", _) _ (Number ns _ _) _ _) = Con $ LI $ readNumber ns
readSumti sc (JoikEkSumti s ss) = List $ readSumti sc s : readCEhOTail sc ss
readSumti _ o = error $ show o

readCEhOTail :: Scope -> [(JoikJek, [Free], Sumti)] -> [Term Scope Atom]
readCEhOTail _ [] = []
readCEhOTail sc ((JOI _ (_, "ce'o", _) _, _, s) : rest) =
	readSumti sc s : readCEhOTail sc rest
readCEhOTail _ o = error $ "readCEhOTail: " ++ show o

readNumber :: [([String], String, [[([String], String)]])] -> Int
readNumber = readTen 0 . map snd3

paList :: [(String, Int)]
paList = [
	("no", 0), ("pa", 1), ("re", 2), ("ci", 3), ("vo", 4),
	("0", 0), ("1", 1), ("2", 2), ("3", 3), ("4", 4)]

readTen :: Int -> [String] -> Int
readTen = foldl (\r n -> r * 10 + fromJust (lookup n paList))

readSumtiTail :: SumtiTail -> String
readSumtiTail (SelbriRelativeClauses (P.Brivla (_, "terziljmina", _) _) _) =
	error "readSumtiTail: terziljmina"
readSumtiTail (SelbriRelativeClauses (P.Brivla (_, n, _) _) _) = n
readSumtiTail st = show st

readSelbriAtom :: Selbri -> Atom
readSelbriAtom (P.GOhA (_, n, _) _ _) = GOhA n
readSelbriAtom o = error $ "readSelbriAtom: " ++ show o

readSelbri :: Selbri -> Either (Term Scope Atom) (Term Scope Atom)
readSelbri (P.Brivla (_, "binxo", _) _) = Left Is
readSelbri (P.Brivla (_, n, _) _) = Left $ Con $ Brivla n
readSelbri (P.GOhA (_, n, _) _ _) = Left $ Con $ GOhA n
readSelbri (P.NA (_, "na", _) _ s) = Right $ Con $ readSelbriAtom s
readSelbri o = error $ "readSelbri: " ++ show o

readSentenceFact :: Sentence -> Either (Fact Scope Atom) (Fact Scope Atom)
readSentenceFact s@(TermsBridiTail{}) =
	either (\lf -> Left $ \sc -> lf : (h sc ++ t sc))
		(\rf -> Right $ \sc -> rf : (h sc ++ t sc)) f
	where
	h sc = map (readSumti sc) $ headTerms s
	f = readSelbri $ selbri $ bridiTail s
	t sc = map (readSumti sc) $ tailTerms $ bridiTail s
readSentenceFact (TopText _ _ _ _ (Just s) _) = readSentenceFact s
readSentenceFact o = error $ show o

readSentence :: Sentence -> Rule Scope Atom
readSentence s@(TermsBridiTail{}) = Rule (\sc -> f : h sc ++ t sc) [] [] []
	where
	h sc = map (readSumti sc) $ headTerms s
	Left f = readSelbri $ selbri $ bridiTail s
	t sc = map (readSumti sc) $ tailTerms $ bridiTail s
readSentence (IJoikJek s [r]) = Rule f [] (getRule r) (getNotRule r)
	where
	Left f = readSentenceFact s
readSentence o = error $ "readSentence: " ++ show o

getRule :: (Show s, Show t) =>
	(s, JoikJek, t, Maybe Sentence) -> [Fact Scope Atom]
getRule (_, Jek _ _ (_, "ja", _) (Just (_, "nai", _)), _, Just t) =
	lefts $ readRule t
getRule o = error $ "getRule: " ++ show o

getNotRule :: (Show s, Show t) =>
	(s, JoikJek, t, Maybe Sentence) -> [Fact Scope Atom]
getNotRule (_, Jek _ _ (_, "ja", _) (Just (_, "nai", _)), _, Just t) =
	rights $ readRule t
getNotRule o = error $ "getNotRule: " ++ show o

readRule :: Sentence -> [Either (Fact Scope Atom) (Fact Scope Atom)]
readRule t@(TUhE {}) = readTUhE t
readRule t = [readSentenceFact t]

readTUhE :: Sentence -> [Either (Fact Scope Atom) (Fact Scope Atom)]
readTUhE (TUhE _ _ _ t _ _) = map readSentenceFact $ getSentences t
readTUhE o = error $ show o