Seems pretty good to me. (I know a little Haskell, but only a little.) I think you and the original author are using different standards of readability. Yours: "If I look at this code, starting without knowing anything about it, does it look familiar?" His: "Once I've taken a few minutes to get the hang of this, is it easy to read and write?".
Here, the <|> and <$> and <* are unfamiliar and weird-looking: fair enough. But once you know that <|> means "or", and <$> means "try to parse some of the input using the thing on the right, and then the thing on the left is the resulting value", and <* means "try to parse both of these, and return the result of parsing the first one", it's hard to see how it could be much simpler.
Even in that code block, <|> and <$> both have roughly the common meanings of | and $ elsewhere in Haskell, which is the "next case" operator for pattern matching expressions and the strictness operator for ensuring that a function is applied to a value correctly.
I think this is very readable. Out of curiousity, what would your ideal of the equivalent code look like, in your language of choice? (If you really can't read this to know what your code would have to do, it's either parsing some term t or consuming whitespace. In the case where it parses a term, that term is going to be one of IntTerm, FloatTerm, AtomTerm, etc. Each term has its own associated parsing function (specified after the <$>).
I don't think that block is that bad - it's just a combination of BNF and the normal pattern matching syntax, albeit with <_> operators.
There are examples of Haskell being needlessly hard to read - I'm not a fan of having optional significant whitespace in only some parts of the language, for example - but this isn't a great example.