module Tcidu(parse) where import Control.Arrow(first, second) import Data.Maybe(catMaybes) import Data.Char(isSpace, toLower) import qualified Language.Lojban.Parser as P( parse, Text, Clause, Sentence(..), Gek(..), Free(..), IntervalProperty(..), Selbri(..), Linkargs(..), Tag(..), Sumti(..), SumtiTail(..), RelativeClause(..), Operand(..)) import Klesi( Text(..), Selbri(..), Tag(..), Sumti(..), Mex(..), RelativeClause(..)) import Liste(mezofatcidu, mezosetcidu, mezopatcidu) -------------------------------------------------------------------------------- parse :: String -> Text parse = either (ParseError . show) (snd . process 1) . P.parse process :: Int -> P.Text -> (Int, Text) process n ptext = second flipText $ proc n ptext where flipText (Bridi (NA (SE i selbri)) terms) = flipText $ Bridi (NA selbri) $ flipTerms i terms flipText (Bridi (SE i selbri) terms) = flipText $ Bridi selbri $ flipTerms i terms flipText text = text flipTerms i = map $ first flipTag where flipTag (FA f) | f == 1 = FA i | f == i = FA 1 flipTag t = t some :: (a -> b -> (a, c)) -> a -> [b] -> (a, [c]) some _ x0 [] = (x0, []) some f x0 (y : ys) = let (x1, z) = f x0 y (x', zs) = some f x1 ys in (x', z : zs) proc :: Int -> P.Text -> (Int, Text) proc n (P.TopText _ _ _ _ (Just t) _) = proc n t proc n (P.TopText _ _ [P.VocativeSumti [(_, v, _)] _ _] _ _ _) = (n, Vocative v) proc n (P.TopText _ _ fs@(_ : _) _ _ _) = (n, Free fs) proc n (P.IText_1 _ _ _ _ (Just t)) = proc n t proc n (P.IText_1 _ _ _ [P.VocativeSumti [(_, v, _)] _ _] _) = (n, Vocative v) proc n (P.IText_1 _ _ _ fs@(_ : _) _) = (n, Free fs) proc n (P.StatementI ptext iptexts) = (0, MultiText $ map snd $ map (proc 1) $ ptext : ptexts) where ptexts = catMaybes $ map (\(_, _, t) -> t) iptexts proc n (P.Selbri selbri) = (n, Bridi (readSelbri selbri) []) proc n (P.SelbriTailTerms pselbri pterms _ _) = (n', Bridi selbri terms) where selbri = readSelbri pselbri (n', terms) = processTagSumti n [] pterms proc n (P.TermsBridiTail pterms _ _ (P.Selbri pselbri)) = (n', Bridi selbri terms) where selbri = readSelbri pselbri (n', terms) = processTagSumti n pterms [] proc n (P.TermsBridiTail pterms1 _ _ (P.SelbriTailTerms pselbri pterms2 _ _)) = (n', Bridi selbri terms) where selbri = readSelbri pselbri (n', terms) = processTagSumti n pterms1 pterms2 proc n (P.Prenex psumti (_, "zo'u", _) _ t) = (n', Prenex sumti ret) where sumti = map readSumti psumti (n', ret) = process n t proc n (P.PrenexSentence psumti (_, "zo'u", _) _ t) = (n', Prenex sumti ret) where sumti = map readSumti psumti (n', ret) = process n t proc n (P.TermsBridiTail ss _ _ (P.GekSentence (P.STagGik (P.Time _ [((_, tense, _), _, _)] _ _) ((_, "gi", _), _, _)) t ((_, "gi", _), _, _) u _ _ _)) = (n2, TagGI tense ret1 ret2) where (n1, ret1) = process n $ P.TermsBridiTail ss undefined undefined t (n2, ret2) = process n1 $ P.TermsBridiTail ss undefined undefined u proc n (P.GekSentence (P.STagGik (P.Time _ [((_, tense, _), _, _)] _ _) ((_, "gi", _), _, _)) t ((_, "gi", _), _, _) u _ _ _) = (n, TagGI tense (snd $ process n t) (snd $ process n u)) proc n t = (n, UnknownText $ "proc: " ++ show t) processTagSumti :: Int -> [P.Sumti] -> [P.Sumti] -> (Int, [(Tag, Sumti)]) processTagSumti n = curry $ processCEhU n . uncurry pTagSumti where pTagSumti s t = let (n', e, r) = readTagSumti 1 [] [] s (_, _, r') = readTagSumti (if n' > 1 then n' else 2) e [] t in r ++ r' processCEhU :: Int -> [(Tag, Sumti)] -> (Int, [(Tag, Sumti)]) processCEhU n [] = (n, []) processCEhU n ((t, sumti) : rest) = (n', (t, ce'u n) : terms') where (b, ce'u) = pCEhU sumti (n', terms') = processCEhU (n + b) rest pCEhU :: Sumti -> (Int, Int -> Sumti) pCEhU CEhUPre = (1, CEhU) pCEhU (LO selbri (Just (POI (Bridi (ME sumti) ss)))) = let (b, s) = pCEhU sumti in (b, \n -> LO selbri $ Just $ POI $ Bridi (ME $ s n) ss) pCEhU (LO (BE selbri sumti) Nothing) = let (b, s) = pCEhU sumti in (b, \n -> LO (BE selbri $ s n) Nothing) pCEhU (SFIhO modal sumti) = let (b, s) = pCEhU sumti in (b, SFIhO modal . s) pCEhU (GOI sumti1 sumti2) = let (b1, s1) = pCEhU sumti1; (b2, s2) = pCEhU sumti2 in (b1 + b2, \n -> GOI (s1 n) (s2 $ b1 + n)) pCEhU (LA (Right (ME sumti))) = let (b, s) = pCEhU sumti in (b, LA . Right . ME . s) pCEhU (Relative sumti r) = let (b, s) = pCEhU sumti in (b, flip Relative r . s) pCEhU (LAhE sumti) = let (b, s) = pCEhU sumti in (b, LAhE . s) pCEhU sumti = (0, const sumti) readTagSumti :: Int -> [Int] -> [(Tag, Sumti)] -> [P.Sumti] -> (Int, [Int], [(Tag, Sumti)]) readTagSumti n e r [] = (n, e, reverse r) readTagSumti n e r (P.TagSumti t s : rest) = case readTag t of (Just i, tag) -> readTagSumti (next i e) (i : e) ((tag, sumti) : r) rest (_, tag) -> readTagSumti n e ((tag, sumti) : r) rest where sumti = readSumti s readTagSumti n e r (s : rest) = readTagSumti (next n e) (n : e) ((FA n, readSumti s) : r) rest readTag :: P.Tag -> (Maybe Int, Tag) readTag (P.FA (_, f, _) _) = (Just $ mezofatcidu f, FA $ mezofatcidu f) readTag (P.BAI _ Nothing (_, b, _) _ _) = (Nothing, BAI 1 b) readTag (P.BAI _ (Just (_, s, _)) (_, b, _) _ _) = (Nothing, BAI (mezosetcidu s) b) readTag (P.Time _ [((_, t, _), Nothing, Nothing)] _ _) = (Nothing, Time [t]) readTag (P.Time _ _ _ ts) = (Nothing, Time $ map readTime ts) readTag t = (Nothing, UnknownTag $ "readTag: " ++ show t) readTime :: P.IntervalProperty -> String readTime (P.ZAhO (_, z, _) _) = z readTime ip = "readTime: " ++ show ip readSumti :: P.Sumti -> Sumti readSumti (P.KOhA (_, "ce'u", _) [P.XINumber (_, "xi", _) _ [([], pa, [])] _]) = CEhU $ round $ mezopatcidu [pa] readSumti (P.KOhA (_, "ce'u", _) []) = CEhUPre readSumti s@(P.KOhA (_, "ce'u", _) f) = UnknownSumti $ show s ++ " " ++ show f readSumti (P.KOhA (_, k, _) _) = KOhA k readSumti (P.LALE (_, "lo", _) _ st _ _) = LO selbri relative where (selbri, relative) = readSumtiTail st readSumti (P.LALE (_, "la", _) _ st _ _) = LA $ Right selbri where (selbri, _relative) = readSumtiTail st readSumti (P.LA (_, "la", _) _ _ [(_, n, _)] _) = LA $ Left n readSumti (P.LI _ _ m _ _) = LI $ readMex m readSumti (P.KU _ _) = KU readSumti (P.TagSumti (P.FIhO (_, "fi'o", _) _ selbri _ _) sumti) = SFIhO (readSelbri selbri) (readSumti sumti) readSumti (P.ZOI _ "zoi" ws _ _) = ZOI $ processZOI $ concat ws readSumti (P.LAhE_NAhE (_, "tu'a", _) _ _ _ s _ _) = TUhA $ readSumti s readSumti (P.OuterQuantifier _ s (Just (P.GOI (_, "goi", _) _ t _ _))) = GOI (readSumti s) (readSumti t) readSumti (P.OuterQuantifier _ s (Just r)) = Relative (readSumti s) (readRelativeClauses r) readSumti (P.LerfuString ls _ _) = LerfuString $ concatMap (\(_, s, _) -> s) ls readSumti (P.GekSumti (P.STagGik (P.Time _ [((_, pu, _), _, _)] _ _) ((_, "gi", _), _, _)) s ((_, "gi", _), _, _) t) = STense pu (readSumti s) (readSumti t) readSumti (P.LAhE_NAhE (_, "la'e", _) _ _ _ s _ _) = LAhE $ readSumti s readSumti s = UnknownSumti $ "readSumti: " ++ show s processZOI :: String -> String processZOI ('.' : str) = let ('.' : s) = reverse str in dropWhile isSpace $ reverse $ dropWhile isSpace s processZOI str = let ('.' : s) = reverse str in dropWhile isSpace $ reverse $ dropWhile isSpace s readMex :: P.Operand -> Mex readMex (P.Number n _ _) = readNumber n readMex (P.JOhI (_, "jo'i", _) _ ns _ _) = JOhI $ map readMex ns readMex o = UnknownMex $ "readMex: " ++ show o readNumber :: [P.Clause] -> Mex readNumber = Number . mezopatcidu . map (\(_, p, _) -> p) readSumtiTail :: P.SumtiTail -> (Selbri, Maybe RelativeClause) readSumtiTail (P.SelbriRelativeClauses s Nothing) = (readSelbri s, Nothing) readSumtiTail (P.SelbriRelativeClauses s (Just r)) = (readSelbri s, Just $ readRelativeClauses r) readSumtiTail st = (UnknownSelbri $ "readSumtiTail: " ++ show st, Nothing) readRelativeClauses :: P.RelativeClause -> RelativeClause readRelativeClauses (P.NOI (_, "poi", _) _ bridi _ _) = POI $ snd $ process 1 bridi readRelativeClauses r = UnknownRelativeClause $ show r readSelbri :: P.Selbri -> Selbri readSelbri (P.Brivla (_, b, _) _) = Brivla $ map toLower b readSelbri (P.Linkargs selbri (P.BE (_, "be", _) _ sumti _ _ _)) = BE (readSelbri selbri) (readSumti sumti) readSelbri (P.NU (_, "nu", _) _ _ _ bridi _ _) = NU $ snd $ process 1 bridi readSelbri (P.NU (_, "du'u", _) _ _ _ bridi _ _) = DUhU $ snd $ process 1 bridi readSelbri (P.NA (_, "na", _) _ s) = NA $ readSelbri s readSelbri (P.ME (_, "me", _) _ s _ _ _ _) = ME $ readSumti s readSelbri (P.SE (_, se, _) _ s) = SE (mezosetcidu se) $ readSelbri s readSelbri s = UnknownSelbri $ "readSelbri: " ++ show s next :: Int -> [Int] -> Int next n e | (n + 1) `elem` e = next (n + 1) e | otherwise = n + 1