Haskell Parsec-';许多';和错误消息

Haskell Parsec-';许多';和错误消息,haskell,parsec,Haskell,Parsec,当我尝试解析多个p时,我没有收到“预期p”消息: > parse (many (char '.') >> eof) "" "a" Left (line 1, column 1): unexpected 'a' expecting end of input 比照 > parse (sepBy (char '.') (char ',') >> eof) "" "a" Left (line 1, column 1): unexpected 'a' expectin

当我尝试解析
多个p
时,我没有收到“预期p”消息:

> parse (many (char '.') >> eof) "" "a"
Left (line 1, column 1):
unexpected 'a'
expecting end of input
比照

> parse (sepBy (char '.') (char ',') >> eof) "" "a"
Left (line 1, column 1):
unexpected 'a'
expecting "." or end of input
正如我所预料的那样
many1p return[]
同样有效

所有这些函数都接受空输入,那么为什么许多函数不报告它所期望的内容呢?这是一个bug还是一个功能?

来自

许多p应用解析器p 0或 更多次。返回所选对象的列表 返回p的值

所以空字符串是
many
combinator的有效输入

[补充]


啊,现在我明白你的意思了<当使用
(选择组合器)时,会报告预期为a或b的代码>
many
是在不使用
的情况下实现的,但是
Sebby
在内部使用它。

从某种表面上看,行为差异的原因是
many
是一个函数,而
Sebby
是为重新实现的
many
构造的。在后一种情况下,“expecting…”消息是基于导致解析失败的路径上可用的备选方案构建的;由于
many
没有这样的选择,它只是无条件地成功了


我不知道我是否会将其描述为一个bug或一个特性,这只是Parsec如何工作的一种怪癖。错误处理并不是Parsec的强项,这似乎不是我在这方面首先要担心的事情。如果它让您非常困扰,那么您可以通过查看其他解析库来获得更好的服务。例如,我听说了一些好消息。

通过
manyTill
,您将获得更好的错误消息:

> parse (manyTill (char '.') eof) "" "a"
Left (line 1, column 1):
unexpected 'a'
expecting end of input or "."
这是由于您与
>
的链接方式。如果第一个解析器成功,那么将运行第二个解析器
many
成功,因此尝试了
eof
eof
失败,因此您只会收到
eof
的错误消息

使用
manyTill
,它会尝试两个解析器(第二个第一个),如果两者都失败,则会合并错误消息(这是因为它在内部使用

但总的来说,使用
定义自己的错误更容易:

>解析(许多(字符)>>eof“许多点”)“a”
左(第1行第1列):
意外的“a”
期待有很多圆点

这是parsec-3.1中引入的一个错误。如果使用以前的版本进行测试,您应该会收到如下错误消息:

> parse (many (char '.') >> eof) "" "a"
Left (line 1, column 1):
unexpected 'a'
expecting "." or end of input

至少,这是我修复错误后得到的结果:-)

这不是重点。空字符串也是sebby的有效输入,但sebby报告其参数中的错误。是的,这似乎是正确的。我想知道我是否因为想要这种行为而滥用了库,或者这是Parsec中的一个bug。好吧,错误报告没有明确的文档记录(至少在haddock文档中),所以它不是一个“bug”。错误报告依赖于实现——没有保证。这不应该是一个隐藏的实现细节吗<代码>许多也可以使用
来定义,从我看来,出于性能原因,它没有以这种方式定义。@hmp:可能应该是,是的。尽管我希望您最好在这两种情况下都使用
()
来提供您自己的消息。这不是因为我链接解析器的方式,因为其他解析器(使用
)也会在空输入时成功,并收集错误。(问题是,
在(sym{)(sym})$many stmt
,我想看到关于错误的“expecting'}”或“statement”)。这就是问题所在,错误消息只针对当前解析器-获得“x或y”消息的唯一原因是,
组合器专门从两个子解析器收集消息<代码>在之间,只需像您的示例那样使用
>
链接即可。因此,如果您编写的between版本使用了
,则可以得到“}或语句”错误:例如,有关如何合并错误消息的信息,请参见
实现:好的,我理解为什么这不起作用。但我不相信为什么
许多
不收集错误(如果它不使用
,它可以手动实现)是“正确的”。正如其他人所说,错误报告没有明确的文档记录,但对我来说,这似乎仍然违反了一些约定。好吧,在示例代码中,错误报告的问题是,当解析失败时,错误不在
many
,因为
many
实际上已经成功(它没有解析任何内容)。在此之后,将运行
eof
解析器,该解析器将失败。(这就是我在第二段中试图解释的。)解析器从不回溯到
>
之前。这就是为什么我建议使用
manyTill
,因为它的语义更适合这种情况-使用
>
表示“运行第一个解析器,如果成功,则无条件运行第二个”。在我的破解版parsec 3.1和parsec-3.0中,两个解析器都会收到相同的错误消息-您提到的行为仅在parsec-3.1中出现。我编辑了我的评论。
> parse (many (char '.') >> eof) "" "a"
Left (line 1, column 1):
unexpected 'a'
expecting "." or end of input