{-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE TupleSections #-} module Main where import LojbanTools import Prolog2 import Language.Lojban.Parser hiding (LA, Brivla, KOhA, GOhA, NA, LerfuString) import qualified Language.Lojban.Parser as P import System.Environment import Data.Maybe import Data.Either import Data.List import Control.Monad import Control.Arrow import Control.Applicative import System.IO main :: IO () main = do [fn] <- getArgs src <- readFile fn let Right p = parse src rules = map readSentence $ getSentences p whileJust getAsk $ flip ask1 rules whileJust :: IO (Maybe a) -> (a -> IO b) -> IO () whileJust test action = do p <- test case p of Just x -> action x >> whileJust test action Nothing -> return () getAsk :: IO (Maybe (Fact Scope Atom)) getAsk = do putStr ".i " hFlush stdout p <- (either (error . show) id . parse) `fmap` getLine let Left q = readSentenceFact p return $ if isCOhO p then Nothing else Just q isCOhO (TopText _ _ [VocativeSumti [(_, "co'o", _)] _ _] _ _ _) = True isCOhO _ = False ask1 :: Fact Scope Atom -> [Rule Scope Atom] -> IO () ask1 q rules = do let answer = ask [] [] q rules let answer2_1 = unwords $ intersperse ".ija" $ map unwords $ filter ((> 2) . length) $ map ((\ret -> intersperse ".ije" ret) . 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 putStr ".i " putStr $ case answer of [] -> "nago'i\n" _ -> case intersperse ".a" $ catMaybes $ (flip map) (map maValue answer) $ (showAtom <$>) of [] -> if null answer2 then "go'i\n" else "" m -> unwords m ++ "\n" if null answer2 then return () else if length answer == 1 then putStrLn answer2_1 else putStrLn answer2 showAtom :: Atom -> String showAtom (LA n) = "la " ++ n showAtom (LO n) = "lo " ++ n maValue :: Result Scope Atom -> Maybe Atom maValue r = case filter (not . null . fst) $ map (first $ filter isMA) r of [] -> Nothing ((_, tv) : _) -> (\(Con v) -> v) <$> tv isMA :: Term Scope Atom -> Bool isMA (Var [_] (KOhA "ma")) = True isMA _ = False showAnswerAll a = if null a then "nago'i" else intercalate " .a " $ map showAnswer $ map (lookupMA . onlyTop) a 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 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 lookupMA = map snd . filter ((Var "top" (KOhA "ma") `elem`) . fst) showAnswer as = if null as then "go'i" else showLA $ head as showLA (Just (Con (LA n))) = "la " ++ n showLA (Just (Con (LO n))) = "lo " ++ n onlyTop = filter (not . null . fst) . map (\(vars, val) -> (filter isTop vars, val)) isTop :: Term String s -> Bool isTop (Var "top" _) = True isTop _ = False data Atom = LA String | LO String | KOhA String | Brivla String | GOhA String | LerfuString String deriving (Show, Eq) type Scope = [Int] instance TwoD [Int] where next (n : ns) = n + 1 : ns down ns = 0 : ns readSumti :: Scope -> Sumti -> Term Scope Atom readSumti sc (P.LA (_, "la", _) _ _ ns _) = Con $ LA $ intercalate "." $ map snd3 ns readSumti sc (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 readSumtiTail :: SumtiTail -> String readSumtiTail (SelbriRelativeClauses (P.Brivla (_, n, _) _) _) = n readSumtiTail st = show st readSelbriAtom (P.GOhA (_, n, _) _ _) = GOhA n readSelbri :: Selbri -> Either (Term Scope Atom) (Term Scope Atom) 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 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 getRule (_, Jek _ _ (_, "ja", _) (Just (_, "nai", _)), _, Just t) = lefts $ readTUhE t getNotRule (_, Jek _ _ (_, "ja", _) (Just (_, "nai", _)), _, Just t) = rights $ readTUhE t readTUhE (TUhE _ _ _ t _ _) = map readSentenceFact $ getSentences t