Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parsec debugging

I've been working with parsec and I have trouble debugging my code. For example, I can set a breakpoint in ghci, but I'm not sure how to see how much of the input has been consumed, or things like that.

Are there tools / guidelines to help with debugging parsec code?

like image 259
Xodarap Avatar asked Feb 28 '12 14:02

Xodarap


3 Answers

You might be able to use the <?> operator in Text.Parsec.Prim to make better error messages for you and your users. There are some examples in Real World Haskell. If your parser has good sub-parts then you could setup a few simple tests (or use HUnit) to ensure they work separately as expected.

like image 195
Chris Kuklewicz Avatar answered Nov 08 '22 12:11

Chris Kuklewicz


Another useful trick:

_ <- many anyChar >>= fail this will generate an error (Left) of:

unexpected end of input
the remaining 'string'

I think the parserTrace and parserTraced functions mentioned here http://hackage.haskell.org/package/parsec-3.1.13.0/docs/Text-Parsec-Combinator.html#g:1 do something similar to the above.

like image 35
Chris Stryczynski Avatar answered Nov 08 '22 12:11

Chris Stryczynski


This page might help.

Debug.trace is your friend, it allows you to essentially do some printf debugging. It evaluates and prints its first argument and then returns its second. So if you have something like

foo :: Show a => a -> a
foo = bar . quux

You can debug the 'value' of foo's parameter by changing foo to the following:

import Debug.Trace(trace)

foo :: Show a => a -> a
foo x = bar $ quux $ trace ("x is: " ++ show x) x

foo will now work the same way as it did before, but when you call foo 1 it will now print x is: 1 to stderr when evaluated.

For more in-depth debugging, you'll want to use GHCI's debugging commands. Specifically, it sounds like you're looking for the :force command, which forces the evaluation of a variable and prints it out. (The alternative is the :print command, which prints as much of the variable as has been evaluated, without evaluating any more.)

Note that :force is more helpful in figuring out the contents of a variable, but may also change the semantics of your program (if your program depends upon laziness).

A general GHCI debugging workflow looks something like this:

  • Use :break to set breakpoints
  • Use :list and :show context to check where you are in the code
  • Use :show bindings to check the variable bindings
  • Try using :print to see what's currently bound
  • Use :force if necessary to check your bindings

If you're trying to debug an infinite loop, it also helps to use

  • :set -fbreak-on-error
  • :trace myLoopingFunc x y

Then you can hit Ctrl-C during the loop and use :history to see what's looping.

like image 30
So8res Avatar answered Nov 08 '22 11:11

So8res