Alex lexers are often used by
Happy parsers, for example in
GHC. While many of these applications are quite sophisticated,
it is still quite useful to combine the basic
Happy %monad
directive with the Alex
monad wrapper. By using monads for both,
the resulting parser and lexer can handle errors far more
gracefully than by throwing an exception.
The most straightforward way to use a monadic
Alex lexer is to simply use the
Alex monad as the
Happy monad:
Example 8.1. Lexer.x
{
module Lexer where
}
%wrapper "monad"
tokens :-
...
{
data Token = ... | EOF
deriving (Eq, Show)
alexEOF = return EOF
}Example 8.2. Parser.y
{
module Parser where
import Lexer
}
%name pFoo
%tokentype { Token }
%error { parseError }
%monad { Alex } { >>= } { return }
%lexer { lexer } { EOF }
%token
...
%%
...
parseError :: Token -> Alex a
parseError _ = do
((AlexPn _ line column), _, _, _) <- alexGetInput
alexError ("parse error at line " ++ (show line) ++ ", column " ++ (show column))
lexer :: (Token -> Alex a) -> Alex a
lexer = (alexMonadScan >>=)
}
We can then run the finished parser in the
Alex monad using
runAlex, which returns an
Either value rather than throwing an
exception in case of a parse or lexical error:
import qualified Lexer as Lexer import qualified Parser as Parser parseFoo :: String -> Either String Foo parseFoo s = Lexer.runAlex s Parser.pFoo