> module WeberLogic.Parser ( > Letter(Name, Variable), > LogicExp( > Not, Or, Xor, And, Implies, Iff, Nand, Nor, Predicate, Universal, > Existential), > readExp, readArg) > where > import Prelude hiding (and, or) > import Data.List (union) > import Text.Printf > import Text.Parsec as Parsec > import Text.Parsec hiding (Error) > import Text.Parsec.String > import Text.Parsec.Expr > import Text.Parsec.Token > import Text.Parsec.Language > import qualified Data.List as List > data Letter > = Name Char > | Variable Char > data LogicExp > = Not LogicExp > | Or LogicExp LogicExp > | Xor LogicExp LogicExp > | And LogicExp LogicExp > | Implies LogicExp LogicExp > | Iff LogicExp LogicExp > | Nand LogicExp LogicExp > | Nor LogicExp LogicExp > | Predicate Char [Letter] > | Universal Letter LogicExp > | Existential LogicExp > readExp :: String -> Either String LogicExp > readExp str = case parse parseExp0 "readExp" str of > Right val -> Right val > Left val -> Left $ show val > readArg :: String -> Either String [LogicExp] > readArg str = case parse parseArg "readArg" str of > Right val -> Right val > Left val -> Left $ show val > parseExp0 :: Parser LogicExp > parseExp0 = do > x <- parseExp1 > eof > return x > parseExp1 :: Parser LogicExp > parseExp1 = try $ do > x <- parseExp2 > x' <- parseExp1' x > return x' > parseExp1' :: LogicExp -> Parser LogicExp > parseExp1' x = try $ do > string "<->" > y <- parseExp2 > return $ Iff x y > <|> do > return x > parseExp2 :: Parser LogicExp > parseExp2 = try $ do > x <- parseExp3 > x' <- parseExp2' x > return x' > parseExp2' :: LogicExp -> Parser LogicExp > parseExp2' x = try $ do > string "->" > y <- parseExp2 > return $ Implies x y > <|> do > return x > parseExp3 :: Parser LogicExp > parseExp3 = try $ do > lhs <- parseExp4 > rhs <- parseExp3' lhs > return rhs > <|> do > lhs <- parseExp4 > return lhs > parseOperator3 :: (LogicExp -> LogicExp -> LogicExp) -> > String -> LogicExp -> Parser (LogicExp) > parseOperator3 connective symbol lhs > = try $ do > string symbol > rhs <- parseExp4 > exp2 <- parseExp3' $ connective lhs rhs > return exp2 > parseExp3' :: LogicExp -> Parser (LogicExp) > parseExp3' lhs = parseOperator3 And "&" lhs > <|> parseOperator3 Or "+" lhs > <|> parseOperator3 Nand "|" lhs > <|> parseOperator3 Nor "/" lhs > <|> parseOperator3 Xor "⊕" lhs > <|> do > return lhs > parseExp4 :: Parser LogicExp > parseExp4 = try $ do > string "~" > x <- parseExp4 > return $ Not x > <|> (try $ do > p <- upper > xs <- parsePredicateLetters > return $ Predicate p xs) > <|> do > char '(' > x <- parseExp1 > char ')' > return $ x > parsePredicateLetters :: Parser ([Letter]) > parsePredicateLetters > = try $ do > x <- oneOf "abcefghijklmnopqrst" > xs <- parsePredicateLetters > return ((Name x):xs) > <|> (try $ do > x <- oneOf "uvwxyz" > xs <- parsePredicateLetters > return ((Variable x):xs)) > <|> do > return [] > parseArg :: Parser [LogicExp] > parseArg = try $ do > xs <- parseArg' > return xs > <|> do > x <- parseExp1 > spaces > xs <- parseArg' > return $ x : xs > parseArg' :: Parser [LogicExp] > parseArg' = try $ do > string "|-" > spaces > x <- parseExp1 > return [x] > <|> do > char ',' > spaces > x <- parseExp1 > spaces > xs <- parseArg' > return $ x : xs