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