"(1+2)*3"
⟹
showExpr
from last time?
showExpr :: Expr -> String
readExpr :: String -> Expr
1+2*3
Value: 7
Expression? (1+2)*3
Value: 9
eval :: Expr -> Integer
readExpr :: String -> Expr
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)
showExpr
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
readExpr :: String -> Expr
showExpr :: Expr -> String
rExpr :: Gen Expr
deriving
(Read,Show)
is an example
of parsers and printers generated automatically from a particular
kind of grammar (a data
declaration)
String
prop_correct_parseX x = parseX (showX x) == x
Expr->String
String->Expr
a
String -> Maybe (a,String)
Maybe
data Maybe a = Nothing | Just a
Nothing
Just (x,r)
x
r
Gen a
Parser a
do
-- Running a parser
parse :: Parser a -> String -> Maybe (a,String)
number ::= digit {digit}
,
number :: Parser Integer
parse number "42" == Just (42,"")
parse number "xyz42" == Nothing
parse number "42xyz" == Just (42,"xyz")
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
do
+
, 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 | term
expr ::= expr "+" term | term
Expr
expr
term
[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 Add t ts
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))
addition
apply :: Parser (a->b) -> Parser a -> Parser b apply (P pf) (P pb) = 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
do
Monad
class Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
do
do x <- m; more ; stuff
m >>= (\x -> do more ; stuff)
Enum
[x..y]
enumFromTo x y
return :: a -> Parser a (>>=) :: Parser a -> (a -> Parser b) -> Parser b
return
(>>=)
apply
instance Monad Parser where return x = P (\ s -> Just (x,s)) P p >>= f = P (\ s -> case p s of Nothing -> Nothing Just (a,r) -> parse (f a) r)
return
(>>=)
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: symbolic expressions, more about monads!