import Prelude hiding (lex) import Parser import Control.Applicative data ABin = Leaf | Node ABin ABin -- deriving Show -- we could derive Show automatically, but it will help to write it -- we use this to allow spaces before a token lex = ignoreSpaces . lexeme -- It helps, in order to encode the parser, to write the show function first showABin Leaf = "f" showABin (Node left right) = "(" ++ showABin left ++ "," ++ showABin right ++ ")" instance Show ABin where show = showABin {-- The parser is derived directly from the grammar for ABin, see the definition of data ABin. Also it is worthy to note how showABin and parseABin are symmetrical to each other, this is because they are inverse of each other, and parsing combinators allows to emphasize this relationship. --} -- we use (because Parser is in classes Functor and Applicative): -- (<$>) :: Functor f => (a -> b) -> f a -> f b -- (<*>) :: Applicative f => f (a -> b) -> f a -> f b parseABin :: Parser ABin parseABin = makeLeaf <$> lex "f" <|> makeNode <$> lex "(" <*> parseABin <*> lex "," <*> parseABin <*> lex ")" where makeLeaf _ = Leaf makeNode _ left _ right _ = Node left right {-- Comparing with yacc, one would write: ABin := "f" { return Leaf } | "(" ABin "," ABin ")" { return (Node $1 $2) } our solution is just a more verbose version of this. The main difference is that we do not need an external tool (yacc) to compile the grammar, we can do it directly from Haskell, allowing more flexibility. We use (<$>) to lift our action (a function) into a parser, then we use (<*>) to chain the item of a rule of the grammar, and (<|>) to give alternative rules for a non-terminal. So the syntax is: nonTerminal := action1 <$> symbol1 <*> symbol2 <*> ... <*> symbolK <|> action2 <$> symbol1' <*> ... <*> symbolK' ... <|> actionN <$> symbol1''' <*> ... <*> symbolK''' --} -- uses (>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b (because Maybe is a monad) keepParsedValue :: Maybe (parsedType,[Char]) -> Maybe parsedType keepParsedValue read = read >>= return . fst readABin :: [Char] -> Maybe ABin readABin = keepParsedValue . parse parseABin readABins :: [Char] -> Maybe [ABin] readABins = keepParsedValue . parse (many parseABin) -- this is many :: Alternative f => f a -> f [a], taking f = Parser