Consider the following Haskell code
try_lex_rgx :: String -> IO (Maybe [RgxToken])
try_lex_rgx rgx_str =
catch
(do
rgx_toks <- evaluate $ lex_rgx rgx_str
return $ Just rgx_toks)
(\(LexerErr err_msg remainder) -> disp_lex_error rgx_str (LexerErr err_msg remainder))
The way I intend for this code to work is to evaluate the expression lex_rgx rgx_str
, catching any exceptions when they occur, and then invoking disp_lex_error
to pretty-print the error.
(By the way, the code for disp_lex_error is the following
disp_lex_error :: String -> RgxLexerException -> IO (Maybe [RgxToken])
disp_lex_error rgx_str (LexerErr err_msg remainder) = let loc_str_frag = "In regex " ++ rgx_str ++ " at ..." in
do
hPutStrLn stderr ("Lexer error: " ++ err_msg ++ "\n" ++
loc_str_frag ++ remainder ++ "\n" ++
(replicate (length loc_str_frag - 1) ' ') ++ "^^")
evaluate Nothing
)
However, I think lazy evaluation is stopping this from happening. When I run the code in ghci with an input that invokes an error, I get the following message
*Rgx.RgxLexer> :l Rgx.RgxLexer
[1 of 2] Compiling Rgx.RgxTok ( Rgx/RgxTok.hs, interpreted )
[2 of 2] Compiling Rgx.RgxLexer ( Rgx/RgxLexer.hs, interpreted )
Ok, two modules loaded.
*Rgx.RgxLexer> try_lex_rgx "\\"
Just [*** Exception: LexerErr "Dangling \"\\\" is not allowed" ""
instead of a pretty printed error.
To me, it seems as though the code is not working as I intend it to because due to lazy evaluation, the system only actually calculates the expression evaluate $ lex_rgx rgx_str
once it has already started forming the parent expression Just x
.
Am I correct, and if so, is there any elegant way to circumvent this issue?