Skip to content

Instantly share code, notes, and snippets.

@nsanmartin
Created March 30, 2023 03:05
Show Gist options
  • Save nsanmartin/e7edd30d3689a14a0edfa4caab0098e2 to your computer and use it in GitHub Desktop.
Save nsanmartin/e7edd30d3689a14a0edfa4caab0098e2 to your computer and use it in GitHub Desktop.
propositional logic parser using Parsec
import System.IO
import Control.Monad
import Text.ParserCombinators.Parsec
import Text.ParserCombinators.Parsec.Expr
import Text.ParserCombinators.Parsec.Language
import qualified Text.ParserCombinators.Parsec.Token as Token
data Formula = Or Formula Formula
| And Formula Formula
| Impl Formula Formula
| Iff Formula Formula
| Not Formula
| Var String
| Verdad
| Mentira
deriving (Eq, Show)
lexer = Token.makeTokenParser emptyDef
{ Token.identStart = letter
, Token.identLetter = alphaNum
, Token.reservedOpNames = ["<->", "->", "|", "&", "!"]
, Token.reservedNames = [ "Posta", "Chamuyo" ]
}
identifier = Token.identifier lexer
keyword = Token.reserved lexer
op = Token.reservedOp lexer
roundBrackets = Token.parens lexer
whiteSpace = Token.whiteSpace lexer
formulaParser = whiteSpace >> formula
formula = conFormula <|> formulaTerm
formulaTerm = roundBrackets formula <|> laPosta <|> elChamuyo <|> unaVariable
conFormula = buildExpressionParser
[ [prefix "!" Not]
, [binary "<->" (Iff) AssocLeft, binary "->" (Impl) AssocLeft]
, [binary "|" (Or) AssocLeft, binary "&" (And) AssocLeft]
]
formulaTerm
prefix name f = Prefix $ op name >> return f
postfix name f = Postfix $ op name >> return f
binary name f assoc = Infix (op name >> return f) assoc
laPosta = keyword "Posta" >> return Verdad
elChamuyo = keyword "Chamuyo" >> return Mentira
unaVariable = Var <$> identifier
calcular s =
case ret of
Left e -> "Error: " ++ (show e)
Right n -> "Interpreted as: " ++ (show n)
where
ret = parse formulaParser "" s
main = do
contents <- getContents
mapM (putStrLn . calcular) $ lines contents
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment