Search code examples
haskellparsec

Avoid repetition in lexing when using parsec


The Parsec documentation has an example of using makeTokenParser to build a lexer:

module Main where

 import Text.Parsec
 import qualified Text.Parsec.Token as P
 import Text.Parsec.Language (haskellDef)

 -- The parser
 ...

 expr  =   parens expr
       <|> identifier
       <|> ...


 -- The lexer
 lexer       = P.makeTokenParser haskellDef    

 parens      = P.parens lexer
 braces      = P.braces lexer
 identifier  = P.identifier lexer
 reserved    = P.reserved lexer
 ...

In "The lexer" block, every P.* is applied to lexer so that one can avoid repeating that in "The parser" block. However repeating that for every token is still tedious. Is there some way to avoid the repetition even more? I was thinking to implicitly apply lexer everywhere in "The parser", but am at lost how to.


Solution

  • There is a general syntax for pattern matching on records in Haskell (I started by noticing that all of P.parens, P.braces, etc. are record projection functions - you can see that by looking at the docs.) . You can use that here

    P.TokenParser { P.parens      = parens
                  , P.braces      = braces
                  , P.identifier  = identifier
                  , P.reserved    = reserved
                  } = P.makeTokenParser haskellDef 
    

    EDIT

    As ErikR has pointed out, it you don't just want some of the parsers, but you want all 29 of the GenTokenParser fields brought into global scope, you can enable the RecordWildCards extension and just write

     P.TokenParser {..} = P.makeTokenParser haskellDef