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?
evaluateonly evaluates a value to WHNF (i.e., to match(:)or[], but not further), but your error is hidden inside an element of the list. The following function forces all elements of a list (or use the deepseq library for a more general interface).However hiding exceptions in elements is a questionable methodology to begin with, consider refactoring the lexer to not use exceptions, producing an informative
Eitherthat relays all possible errors, instead of usingMaybewhoseJustdoesn't even guarantee a successful parse.