After reading about monads in chapter 14 of Real World Haskell I thought I understood them to some extant. Then I read the section of the Happy user guide on threaded lexers and I was still confused on how to create a threaded lexer.
After looking at the threaded lexers section and not understanding it, I looked at the Haskell code that Happy generates when it runs. It turns out that the regular parser generator without a threaded lexer passes the token that caused the parse error as the first token in the token list to the “parseError” function. They DO NOT mention this in the documentation.
To grab the token, line and, column# that caused the parse error use the following function
parseError :: [Token] -> a parseError tokenList = let pos = tokenPosn(head(tokenList)) in error ("parse error at " ++ show (head(tokenList))++ show(getLineNum(pos)) ++ ":" ++ show(getColumnNum(pos)))
The key point is the call to “head(tokenList)” this grabs the first token in the tokenList which is the token that caused the parse error.
You can download the source code and check it out here. To test the error reporting run “make” and then
bbell@bbell-desktop:~/NewL-Compiler/parser_with_error_reporting$ cat ../test_files/test1.txt | ./newl newl: parse error at line 3 and column 9