0

我正在尝试为配置文件编写解析器,但遇到了一个奇怪的错误,解析器只是冻结了。代码可以在这里看到。我已经在调试器中运行它,它似乎发生在行中

p_server_entry = many settings *> pure ()

在“纯()”的评价。也就是说,如果可以信任调试器的行为,则尝试从 p_server_entry 返回似乎会失败。我尝试删除“纯()”语句并简单地返回“[()]”(并显然调整类型签名)但它似乎挂在同一个地方。我知道 Parsec 不支持左递归,但我看不到这里发生了什么?

我正在做的是,我正在使用 Parsec 通过用户状态为我填写一条记录。对于返回值,我只是从所有函数中返回 (),因为配置记录将从状态中检索并作为解析结果返回。导致挂起的示例文件是:

[server]
port = 80

我通过在 ghci 中运行 Parser.hs 文件来测试这一点(尽管编译程序并运行它会得到相同的结果)然后执行

:m + Data.Monoid
parseConfigFile "test.config" mempty

我感谢任何人可以提供的任何帮助。

编辑:我应该提到这几乎和以前一样工作。我将它从返回一个特殊的解析树更改为直接更新配置结构。

4

2 回答 2

0

疯狂的猜测:如果你尝试ch = satisfy (notelem)用其他东西改变它会发生什么(即`oneOf“某物”)。我想知道 notelem 是否可以匹配一个空字符串或有一些奇怪的行为。

更一般地说,我知道这很麻烦,但请尝试隔离您的问题(即重新创建解析器失败的最小状态)。就目前而言(200 行代码),评估和解决它有点困难。

于 2013-03-12T00:41:48.347 回答
0

我明白了。我将删除代码链接,因为该分支不应该发布,但它的要点是:我有一个类似的记录

data Config = { port :: Int, {- ... -} }  -- "Save edits" doesn't seem to always save edits!

我创建了一个解析器来解析输入并更新其中一个结构。它丢弃了实际的解析数据,因为无论如何我想要的只是更新的记录。问题是,这丢弃了类型信息,也阻碍了编译器指出我的逻辑错误。对于每个实际产生数据的语句,都会有一个

*> pure ()

在语句结束时,丢弃已解析的数据。我决定我可能不应该丢弃数据,即使我现在不需要它,所以我创建了新类型来对解析的内容进行编码,并最终返回解析树以及更新的配置结构。

完成此操作后,问题立即变得明显。我有这样的声明

p_server_settings = case someVar of
    "server" -> many p_serverSettings
    _        -> many p_siteSettings

并且这两个组合器都被定义为

p_serverSettings = many settings *> pure ()
    where settings = {- bunch of possible settings -}

一旦我删除 () 返回并使用生成的内容,我立即看到 p_server_settings 试图返回 [[Setting]] 而不是 [Setting],这是因为我有

many many settings

这是一个方便的小循环,不消耗任何输入。

经验教训:如果你扔掉你的类型,你就会束缚编译器的手。

于 2013-03-12T08:18:33.583 回答