9

我一直在使用 parsec,但在调试代码时遇到了麻烦。例如,我可以在 ghci 中设置断点,但我不确定如何查看消耗了多少输入,或者类似的东西。

是否有工具/指南可以帮助调试 parsec 代码?

4

3 回答 3

9

页面可能会有所帮助。

Debug.trace是您的朋友,它允许您从本质上进行一些printf调试。它计算并打印它的第一个参数,然后返回它的第二个。所以如果你有类似的东西

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

foo您可以通过更改为以下内容来调试 foo 参数的“值” :

import Debug.Trace(trace)

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

foo 现在将像以前一样工作,但是当你调用foo 1它时,它现在会在评估时打印x is: 1到 stderr。

要进行更深入的调试,您需要使用 GHCI 的调试命令。具体来说,听起来您正在寻找:force命令,该命令会强制评估变量并将其打印出来。(替代方法是:print命令,它打印已评估的尽可能多的变量,不再评估。)

请注意,这:force对找出变量的内容更有帮助,但也可能会改变程序的语义(如果您的程序依赖于惰性)。

一般的 GHCI 调试工作流程如下所示:

  • 用于:break设置断点
  • 使用:listand:show context检查您在代码中的位置
  • 用于:show bindings检查变量绑定
  • 尝试使用:print查看当前绑定的内容
  • :force如有必要,请使用检查您的绑定

如果您正在尝试调试无限循环,它也有助于使用

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

然后你可以Ctrl-C在循环中点击并使用:history来查看循环的内容。

于 2012-02-28T16:43:40.437 回答
5

您可以使用Text.Parsec.Prim 中<?>运算符为您和您的用户提供更好的错误消息。Real World Haskell 中有一些例子。如果您的解析器具有良好的子部分,那么您可以设置一些简单的测试(或使用HUnit)以确保它们按预期单独工作。

于 2012-02-28T18:04:19.170 回答
1

另一个有用的技巧:

_ <- many anyChar >>= fail这将产生一个错误(Left):

unexpected end of input
the remaining 'string'

我认为这里提到的parserTraceparserTraced函数http://hackage.haskell.org/package/parsec-3.1.13.0/docs/Text-Parsec-Combinator.html#g:1做类似于上面的事情。

于 2018-02-25T15:04:17.123 回答