Week 3 Lecture 2
hs
1import Control.Applicative (Alternative (empty, many, some), asum)2import Control.Monad (ap, liftM, void)3import Data.Char (isAlpha, isSpace)4import GHC.Exts.Heap (StgTSOProfInfo)5import GHC.Internal.Base (Alternative ((<|>)))67data BExp8 = Lit Bool9 | Not BExp10 | Var String11 | And BExp BExp12 | Or BExp BExp13 deriving (Eq, Ord, Show)1415-- var = ? any non empty sequence of alphabhetic characters ?16-- bexp ::= "true"17-- | "false"18-- | var19-- | "not" bexp20-- | bexp "and" bexp21-- | bexp "or" bexp2223data Parser a = Parser ((Int, String) -> Either (Int, String) (a, (Int, String)))2425instance Functor Parser where26 fmap :: (a -> b) -> Parser a -> Parser b27 fmap = liftM2829instance Applicative Parser where30 pure a = Parser $ \s -> Right (a, s)31 (<*>) = ap3233instance Monad Parser where34 Parser a >>= f = Parser $ \s -> do35 (a', s') <- a s36 let (Parser b) = f a'37 b s'3839instance Alternative Parser where40 empty = Parser $ \(pos, s) -> Left (pos, "All branches exhausted")41 (Parser p1) <|> (Parser p2) = Parser $ \s -> case p1 s of42 Left err -> p2 s43 Right a -> pure a4445satisfy :: (Char -> Bool) -> Parser Char46satisfy p = Parser $ \(pos, s) ->47 case s of48 "" -> Left (pos, "Empty input")49 c : (cs) ->50 if p c51 then52 pure (c, (pos + 1, cs))53 else Left (pos, "Invalid character: " ++ [c])5455eof :: Parser ()56eof = Parser end57 where58 end :: (Int, String) -> Either (Int, String) ((), (Int, String))59 end s@(_, "") = pure ((), s)60 end (pos, _) = Left (pos, "EOF expected")6162instance MonadFail Parser where63 fail s = Parser (\(pos, _) -> Left (pos, s))6465spaces :: Parser ()66spaces = (many $ satisfy isSpace) *> pure ()6768lexeme :: Parser a -> Parser a69lexeme p = do70 x <- p71 spaces72 pure x7374parseString :: String -> Parser ()75parseString "" = pure ()76parseString (c : cs) = do77 satisfy (== c)78 parseString cs7980lString :: String -> Parser ()81lString s = lexeme $ loop s82 where83 loop "" = pure ()84 loop (c : cs) = satisfy (== c) *> loop cs8586parseBool :: Parser Bool87parseBool =88 do89 parseString "true"90 spaces91 pure True92 <|> do93 parseString "false"94 spaces95 pure False9697fails :: (Alternative f) => f a -> f Bool98fails a = (False <$ a) <|> (pure True)99100notFollowedBy :: (Alternative m, MonadFail m) => m a -> m b -> m a101notFollowedBy a b = do102 ra <- a103 rb <- fails b104 if rb then pure ra else fail "notFollowedBy violation"105106-- notFollowedBy2 :: Parser a -> Parser ()107-- notFollowedBy2 a = do108-- a' <- a109-- Parser (\b -> )110111lKeyword :: String -> Parser ()112lKeyword s = lexeme $ notFollowedBy (loop s) (satisfy isAlpha)113 where114 loop "" = pure ()115 loop (c : cs) = satisfy (== c) *> loop cs116117pTrue :: Parser ()118pTrue = lKeyword "true"119120pFalse :: Parser ()121pFalse = lKeyword "false"122123pAnd :: Parser ()124pAnd = lKeyword "and"125126pOr :: Parser ()127pOr = lKeyword "or"128129pNot :: Parser ()130pNot = lKeyword "not"131132pBool :: Parser Bool133pBool = (pTrue *> pure True) <|> (pFalse *> pure False)134135keywords :: [String]136keywords = ["true", "false", "and", "or", "not"]137138pVar :: Parser String139pVar = lexeme $ do140 s <- some $ satisfy isAlpha141 if elem s keywords142 then143 fail ""144 else pure s145146-- atom :== "true"147-- | "false"148-- | var149-- | not bexp150151-- bexp' ::= epsilon152-- | "and" atom bexp'153-- | "or" atom bexp'154--155-- bexp ::= atom bexp'156157-- delim? either, or he just does- this, yes158-- for now, yes, also assoc is not mentioned yet159160lLParen :: Parser ()161lLParen = lexeme $ void $ satisfy (== '(')162lRParen :: Parser ()163lRParen = lexeme $ void $ satisfy (== '(')164165parens :: Parser a -> Parser a166parens a = lLParen *> a <* lRParen167168pAtom :: Parser BExp169pAtom =170 asum171 [ (pBool >>= pure . Lit)172 , (pVar >>= pure . Var)173 , (Not <$> (pNot *> pAtom))174 , -- ( :3 ) -- Invalid character: :175 parens pBExp176 ]177178pBExp' :: BExp -> Parser BExp179pBExp' x =180 asum181 [ (And x <$> (pAnd *> pAtom))182 , (Or x <$> (pOr *> pAtom))183 , pure x184 ]185186-- pAtom < pAnd < pOr187188pBExpAnd :: BExp -> Parser BExp189pBExpAnd x =190 ( do191 y <- pAnd *> pAtom192 pBExpAnd (And x y)193 )194 <|> pure x195196pBExpOr :: BExp -> Parser BExp197pBExpOr x =198 ( do199 y <- pOr *> pBExpAnd x200 pBExpOr (Or x y)201 )202 <|> pure x203204pBExp :: Parser BExp205pBExp = do206 x <- pAtom207 -- pBExp' x208 pBExpOr x