Search code examples
parsinghaskellparsec

Transforming \" into " using Haskell / Parsec


I'm going through Write Yourself A Scheme tutorial and there's a exercise which I can't solve.

Our strings aren't quite R5RS compliant, because they don't support escaping of internal quotes within the string. Change parseString so that \" gives a literal quote character instead of terminating the string. You may want to replace noneOf "\"" with a new parser action that accepts either a non-quote character or a backslash followed by a quote mark.

The actual ParseString code function is:

parseString :: Parser LispVal
parseString = do
        char '"'
        x <- many (noneOf "\"")
        char '"'
        return $ String x

I've tried in many ways to do it. My attempted solution was:

parseString :: Parser LispVal
parseString = do
        char '"'
        x <- many (satisfy (/= '"') <|> (string "\"" >> return '"'))
        char '"'
        return $ String x

My rationale is that (string "\"" >> return '"') will consume a string formed \" and return a single double-quote character, but it's not working as expected. I also researched over the internet but didn't found a solution.


Solution

  • Writing "\"" in Haskell produces a string with a single element. That's because the Haskell parser is consuming the backslash and it never gets to your program. You need to double escape it, so that both Haskell and your parser are satisfied.

    noneOf "\"\\" <|> (string "\\\"" >> return '"')