I would like to use Parsec’s makeTokenParser to build my parser, but I want to use my own definition of whiteSpace. Doing the following replaces whiteSpace with my definition, but all the lexeme parsers still use the old definition (e.g. P.identifier lexer will use the old whiteSpace).
...
lexer :: P.TokenParser ()
lexer = l { P.whiteSpace = myWhiteSpace }
where l = P.makeTokenParser myLanguageDef
...
Looking at the code for makeTokenParser I think I understand why it works this way. I want to know if there are any workarounds to avoid completely duplicating the code for makeTokenParser?
Sadly, I don’t think there is a way. The local definitions used in
makeTokenParserrefer recursively to themselves, and so, as you’ve noted,lexemeuseswhiteSpaceas defined there, rather than thewhiteSpacerecord member you replace in yourlexerobject.The code is taunting because it uses the same names as both local functions in
makeTokenParserand as record members of theTokenParserconstructor. They are in fact totally distinct entities.