"(1+2)*3"
⟹
showExpr
from last time?
showExpr :: Expr -> String
readExpr :: String -> Expr
1+2*3
Value: 7
Expression? (1+2)*3
Value: 9
data Expr = Num Integer | Add Expr Expr | Mul Expr Expr deriving (Show,Read) ex1 = Mul (Add (Num 1) (Num 2)) (Num 3)
show ex1
"Mul (Add (Num 1) (Num 2)) (Num 3)"
read "Mul (Add (Num 1) (Num 2)) (Num 3)"::Expr
Mul (Add (Num 1) (Num 2)) (Num 3)
infixl 6 :+ infixl 7 :* data Expr = C Integer | Expr :+ Expr | Expr :* Expr deriving (Show,Read) ex1 = (C 1 :+ C 2) :* C 3
read "C 1 :+ C 2 :* C 3" :: Expr
C 1 :+ C 2 :* C 3
read "(C 1 :+ C 2) :* C 3" :: Expr
(C 1 :+ C 2) :* C 3
deriving
(Read,Show)
is an example
of parsers and printers generated automatically from a particular
kind of grammar (a data
declaration)
parseX :: String -> Maybe X
prop_correct_parseX :: X -> Bool prop_correct_parseX x = parseX (showX x) == Just x
Expr->StringÂ
String->ExprÂ
String -> Maybe (a,String)Â
MaybeÂ
data Maybe a = Nothing | Just a
Parser aÂ
-- Running a parser
parse :: Parser a -> String -> Maybe (a,String)
number ::= digit {digit}
,
number :: Parser Integer
parse :: Parser a -> String -> Maybe (a,String)
completeParse :: Parser a -> String -> Maybe a
data Parser a -- abstract type of parsers -- Parsing a single character char :: Char -> Parser Char sat :: (Char->Bool) -> Parser Char -- Choice (<|>) :: Parser a -> Parser a -> Parser a -- Repetition zeroOrMore, oneOrMore :: Parser a -> Parser [a]
-- Not included in the library
pair :: Parser a -> Parser b -> Parser (a,b)
ParserÂ
+
, and add them.
digit :: Parser Char
digit = sat isDigit
number :: Parser Integer
number = do s <- oneOrMore digit
return (read s)
addition :: Parser Integer
addition = do a <- number
char '+'
b <- number
return (a+b)
data Expr = Num Integer | Add Expr Expr | Mul Expr Expr
expr ::= term "+" expr | term
expr ::= expr "+" term | term
ExprÂ
[Expr]Â
ExprÂ
expr = do t <- term ts <- zeroOrMore (do char '+'; term) return (foldl Add t ts) term = do f <- factor fs <- zeroOrMore (do char '*'; factor) return (foldl Mul f fs) factor = (do n <- number; return (Num n)) <|> (do char '('; e <- expr; char ')'; return e)
foldl :: (b -> a -> b) -> b -> [a] -> b
-- foldl is like foldr, but it works from the left...
chain :: Parser item -> Parser sep -> Parser [item] chain item sep = do i <- item is <- zeroOrMore (do sep;item) return (i:is)
leftAssoc :: (t->t->t) -> Parser t -> Parser sep -> Parser t leftAssoc op item sep = do is <- chain item sep return (foldl1 op is)
(<*) :: Parser b -> Parser a -> Parser b (*>) :: Parser a -> Parser b -> Parser b
(<$>) :: (a->b) -> Parser a -> Parser b
expr, term, factor :: Parser Expr expr = leftAssoc Add term (char '+') term = leftAssoc Mul factor (char '*') factor = Num <$> number <|> char '(' *> expr <* char ')'
Parser aÂ
data Parser a = P (String -> Maybe (a,String)) parse :: Parser a -> String -> Maybe(a,String) parse (P f) s = f s
sat :: (Char->Bool) -> Parser Char sat p = P sat_p where sat_p (c:s) | p c = Just (c,s) sat_p _ = Nothing char :: Char -> Parser Char char c = sat (==c)
(<|>) :: Parser a -> Parser a -> Parser a P pf1 <|> P pf2 = P pf where pf s = case pf1 s of Nothing -> pf2 s r -> r
pair :: Parser a -> Parser b -> Parser (a,b) pair (P pa) (P pb) = P (\ s -> case pa s of Nothing -> Nothing Just (a,r) -> case pb r of Nothing -> Nothing Just (b,r) -> Just ((a,b),r))
apply :: Parser (a->b) -> Parser a -> Parser b apply (P pf) (P pa) = P (\ s -> case pf s of Nothing -> Nothing Just (f,r) -> case pa r of Nothing -> Nothing Just (a,r) -> Just (f a,r))
pair pa pb = return (,) `apply` pa `apply` pb
MonadÂ
class Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
EnumÂ
return :: a -> Parser a (>>=) :: Parser a -> (a -> Parser b) -> Parser b
instance Monad Parser where --return :: a -> Parser a return x = P (\ s -> Just (x,s)) -- (>>=) :: Parser a -> (a -> Parser b) -> Parser b P p >>= f = P (\ s -> case p s of Nothing -> Nothing Just (a,r) -> parse (f a) r)
ÂParser | ÂGen | ÂIO | |
---|---|---|---|
Building things | ‹sat› ‹char› ‹(<|>)› ... | ‹elements› ‹oneof› ‹frequency› ... | ‹putStr› ‹getLine› ‹readFile› ... |
Getting things out | ‹parse› | ‹sample› ‹generate› |
MaybeÂ
MonadÂ
Parsing module:
- Source code: Parsing.hs.
- Documentation: Parsing.
- Next week: more about monads!