Implemented the program

This commit is contained in:
vegowotenks 2024-09-17 16:01:09 +02:00
parent ff37176966
commit 7075c52c9f
5 changed files with 144 additions and 4 deletions

View file

@ -1,6 +1,79 @@
module Lib
( someFunc
( parseFullString, evaluate, collectVariableNames, Expression, ParseError
) where
someFunc :: IO ()
someFunc = putStrLn "someFunc"
import Text.Parsec
import Text.Parsec.Expr
import Text.Parsec.Token
import Text.Parsec.Language
import Data.Set (Set)
import qualified Data.Set as Set
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Functor.Identity
data Expression = Constant Bool | Binary BinaryOperator Expression Expression | Unary UnaryOperator Expression | Variable String
deriving Show
data BinaryOperator = LogicalAnd | LogicalOr
deriving Show
data UnaryOperator = LogicalNot
deriving Show
def :: GenLanguageDef String u Identity
def = emptyDef{ commentStart = ""
, commentEnd = ""
, identStart = letter <|> char '_'
, identLetter = alphaNum <|> char '_'
, opStart = oneOf "&|~"
, opLetter = oneOf "&|~"
, reservedOpNames = ["&", "|", "~"]
, reservedNames = ["true", "false"]
}
TokenParser{ parens = m_parens
, identifier = m_identifier
, reservedOp = m_reservedOp
, reserved = m_reserved
, whiteSpace = m_whiteSpace } = makeTokenParser def
exprparser :: ParsecT String () Identity Expression
exprparser = buildExpressionParser table term <?> "expression"
table :: [[Operator String u Identity Expression]]
table = [
[
Prefix (m_reservedOp "~" >> return (Unary LogicalNot))
],
[
Infix (m_reservedOp "&" >> return (Binary LogicalAnd)) AssocLeft
],
[
Infix (m_reservedOp "|" >> return (Binary LogicalOr)) AssocLeft
]
]
term :: ParsecT String () Data.Functor.Identity.Identity Expression
term = m_parens exprparser
<|> fmap Variable (m_identifier)
<|> (m_reserved "true" >> return (Constant True))
<|> (m_reserved "false" >> return (Constant False))
<?> "logical expression"
parseFullString :: SourceName -> String -> Either ParseError Expression
parseFullString = parse (m_whiteSpace *> exprparser <* eof)
collectVariableNames :: Expression -> Set String
collectVariableNames (Constant _) = Set.empty
collectVariableNames (Binary _ left right) = Set.union (collectVariableNames left) (collectVariableNames right)
collectVariableNames (Unary _ right) = collectVariableNames right
collectVariableNames (Variable name) = Set.singleton name
evaluate :: Map String Bool -> Expression -> Bool
evaluate _ (Constant b) = b
evaluate vs (Unary LogicalNot e) = not (evaluate vs e)
evaluate vs (Binary LogicalAnd l r) = evaluate vs l && evaluate vs r
evaluate vs (Binary LogicalOr l r) = evaluate vs l || evaluate vs r
evaluate vs (Variable name) = maybe False id (Map.lookup name vs)