Search code examples
haskellmegaparsec

Adding string literals support in parser


Now I'w working on my university homework and one of the tasks is to add string literals support in my Haskell parser of dummy programming language (named "Hi").

I solved this task with that code:

parseString = do
   res <- char '\"' *> manyTill charLiteral (char '\"')
   return (HiValueString (pack res))

But I don't understand how to solve this task using between? I want to make code of this parser shorter, like:

parseString = do
   res <- between '\"' '\"'
   return (HiValueString (pack res))

Solution

  • between takes parsers, not characters, as arguments. You need two (trivial) parsers that each parse '"', as well as the parser for what you want between the quotes.

    parseString = do
        let quoted = between (char '"') (char '"')
        res <- quoted (many charLiteral)
        return (HiValueString (pack res))
    

    Not really any shorter (even ignoring the extra variable binding I introduce for readability), but it lets you separate more cleanly the quoting from the thing being quoted.

    Regardless, you can use <$> to replace your >>= followed immediately by return.

    parseString = (HiValueString . pack) <$> (char '"' *> manyTill charLiteral (char '"'))
    

    or

    parseString = (HiValueString . pack) <$> (between (char '"') (char '"') (many charLiteral))