Reputation: 150
For one of my courses last semester we were tasked with implementing a JSON parser that spits out formatted HTML. I ended up implementing it in what I felt was more of an iterative fashion than a functional one. Here's the main code snippet I have issues with:
stringToTokens (x:xs)
.....
| x == '\"' = StringLiteral (parseStringToken xs) : stringToTokens (advancePastString xs)
| startsNumeric x = Numeric (processNumeric (x:xs) takeWhile) : stringToTokens (processNumeric xs dropWhile)
| startsKeyword x = Keyword (processKeyword (x:xs) take) : stringToTokens (processKeyword (x:xs) drop)
.....
| otherwise = stringToTokens xs
....
advancePastString :: String -> String
advancePastString (x:xs)
| x == '\"' = xs
| x == '\\' = advancePastString (tail xs)
| otherwise = advancePastString xs
My issue with how I went about handling this is that it feels as if I've taken how I would implement it in a procedural language and just replaced the loop with recursion and drop functions. While this does work I'm wondering what would be a more idiomatic functional way of handling this.
Upvotes: 2
Views: 144
Reputation: 2214
I would try a parser combinator. This is a good place to start: Write You a Haskell: Parsing by Stephen Diehl. It gives you a simple example of what a parser combinator looks like. Then I would look at the available parser combinators like parsec
, attoparsec
and trifecta
. I personally like attoparsec
, but trifecta
has a lot more features.
I've also written a small tutorial on attoparsec
. It isn't complete but it should help you get started.
Upvotes: 2