Epsilon

Using Alternative in the Parser

Posted on May 8, 2013

In this post we will briefly define Parser to have an Alternative instance. Alternative is used in a similar way, but it has some better named functions when looked at in terms of parsing.

Making the Data Type an Alternative

Since we defined Parser as a MonadPlus, we can use MonadPlus functions to implement Parser as an Alternative.

import Control.Applicative

instance Alternative Parser where
    empty = mzero
    (<|>) = mplus
    

In my opinion, empty is a little more explicit in terms of parsers, and <|> gives the idea that the parser is doing something close to that of an || operation. For the calculator we made before, this does not change much, but you will see how much easier it will be to read the parser for Hisp.

import Control.Applicative

data Expression = Expr Op Expression Expression | Number Int deriving Show
data Op = Add | Sub | Div | Mul deriving Show

-- keep these functions the same as they were before
spaces = many $ char ' '
digit = oneof "0123456789"
expression = expression' <|> integer

-- change these ones to return something useful after parsing.
operator = oneof "+*/-" >>= toOp

toOp '+' = Add
toOp '-' = Sub
toOp '/' = Div
toOp '*' = Mul

integer = Number . \s -> (read s :: Int) <$> many1 digit

expression' = Expr <$> (char '(' *> op <* spaces)
                   <*> (expression <* spaces)
                   <*> expression

There is also the nice addition of the many function that is given in Control.Applicative. This means we no longer need to define our own many, as it is just a more specific version of the same function! The code for this last post on building a parser can be found here.

comments powered by Disqus