module Language.Lojban.Camxes.Parse (parse ,LojbanTree ,Expr ,Type ,Value) where import Data.Char import Data.List import Data.Tree import Text.ParserCombinators.Parsec hiding (parse) import qualified Text.ParserCombinators.Parsec as P import Control.Monad.Reader sample = " text=( text1=( paragraphs=( paragraph=( statement=( statement1=( statement2=( statement3=( sentence=( terms=( terms1=( terms2=( term=( term1=( sumti=( sumti1=( sumti2=( sumti3=( sumti4=( sumti5=( sumti6=( KOhAClause=( KOhAPre=( KOhA=( CMAVO=( KOhA=( mi ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) bridiTail=( bridiTail1=( bridiTail2=( bridiTail3=( selbri=( selbri1=( selbri2=( selbri3=( selbri4=( selbri5=( selbri6=( tanruUnit=( tanruUnit1=( tanruUnit2=( BRIVLAClause=( BRIVLAPre=( BRIVLA=( BRIVLA=( gismu=( dansu ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) " parse :: String -> Either ParseError LojbanTree parse = P.parse expr "" expr = do skipMany space sym <- symbol char '=' char '(' inner <- try innerExprs <|> fmap return lojbanic char ')' skipMany space return $ Node (Left sym) inner innerExprs :: Parser [LojbanTree] innerExprs = many1 (do e <- expr; skipMany space; return e) lojbanic :: Parser LojbanTree lojbanic = do skipMany space string <- many1 (letter <|> digit <|> oneOf "'") skipMany space return $ Node (Right (map toLower string)) [] symbol :: Parser Type symbol = fmap (map toLower) $ many1 (letter <|> digit) type LojbanTree = Tree Expr type Expr = Either Type Value type Type = String type Value = String prettyPrint :: LojbanTree -> String prettyPrint tree = runReader (go tree) "" where go (Node (Right value) []) = out value go (Node (Left value) []) = out value go (Node (Left label) (x:xs)) | isTree x = do indent <- ask inner <- local (' ':) $ mapM go (x:xs) return $ "\n" ++ indent ++ "(" ++ label ++ "" ++ concat inner ++ ")" | otherwise = do indent <- ask in' <- go x return $ "\n" ++ indent ++ "(" ++ label ++ " " ++ in' ++ ")" isTree (Node (Left _) (_:_)) = True isTree _ = False out = return