我正在尝试为配置文件编写解析器,并且我遇到了解析器刚冻结的奇怪错误。可以看到代码here。我在调试器中运行它,它似乎发生在行
中p_server_entry = many settings *> pure ()
评估" pure()"。也就是说,如果可以信任调试器行为,它似乎无法尝试从p_server_entry返回。我尝试删除" pure()"声明并简单地返回" [()]" (并明显调整类型签名)但它似乎挂在同一个地方。我知道Parsec不支持左递归,但我不知道这会发生在哪里?
我正在做的是,我正在使用Parsec通过用户状态为我填写一个记录。对于返回值,我只是从所有函数返回(),因为配置记录将从状态检索并作为解析的结果返回。导致挂起的示例文件是:
[server]
port = 80
我通过在ghci中运行Parser.hs文件来测试它(虽然编译程序并运行它会得到相同的结果)然后执行
:m + Data.Monoid
parseConfigFile "test.config" mempty
我感谢任何人都能提供的任何帮助。
编辑:我应该提一下,这几乎和以前一样。我将它从返回一个特殊的解析树改为直接更新配置结构。答案 0 :(得分:0)
ch = satisfy (notelem)
会发生什么(即`oneOf“某事”)会发生什么。
我想知道notelem是否可以匹配一个空字符串或者有一些奇怪的行为。
更一般地说,我知道这是一个痛苦的屁股,但尝试隔离你的问题(即重新创建解析器失败的最小状态)。就目前而言(200行代码),评估和解决它有点困难。
答案 1 :(得分: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
这是一个方便的小循环,不消耗任何输入。
获得的经验教训:如果你扔掉你的类型,你就会绑定编译器。