10

Is it possible somehow to get parse error of some custom type? It would be cool to get more information about parsing context from error for example. And it seems not very convenient to have error info just in the form of text message.

sergeyz
  • 1,308
  • 2
  • 14
  • 23
  • 1
    It doesn't seem to be possible. [`Text.Parsec.Error`](http://hackage.haskell.org/packages/archive/parsec/3.1.1/doc/html/Text-Parsec-Error.html) seems to hint that every kind of error response is eventually a `String`, and even the [`(>)`](http://hackage.haskell.org/packages/archive/parsec/3.1.1/doc/html/Text-Parsec-Prim.html#v:-60--63--62-) operator takes only strings. –  May 16 '13 at 19:29
  • Just noting: The error output isn't "just a text message". It contains a source position, and some information about what the parser was expecting to see next, and so on. But yes, sometimes it would be nice to get more... – MathematicalOrchid May 17 '13 at 18:37

1 Answers1

8

As Rhymoid observes, it is not possible directly, unfortunately.

Combining Parsec with your own Either-like monad won't help, too — it will exit too soon (ParsecT over Either) or too late (EitherT over ParsecT).

If you want it badly, you can do it like this: use ParsecT over State (SourcePos, YourErrorType). (You can't use Parsec's user state because then the error will be backtracked.)

Every time you'd like to emit a structured error value, record it in the state with the current location, but only if the current location is farther than the already recorded one. (If locations are equal, you may want to merge the errors somehow. Maybe keep a list of them.)

Finally, when you run your monad stack, you'll be given the final state and a ParseError that contains a SourcePos. Just check that the two locations coincide. If they don't (i.e. the Parsec's SourcePos is farther), then you don't have an error value for this error.

Roman Cheplyaka
  • 37,738
  • 7
  • 72
  • 121