考虑这个parsec解析器(放入文件parsec-eof-test.hs
):
import Text.Parsec
import Text.Parsec.String
main = do
x <- parse (manyTill anyChar eof >> fail "forced fail") "" <$> readFile "parsec-eof-test.hs"
print (x :: Either ParseError String)
如果你运行它,你会得到:
Left (line 7, column 1):
unexpected end of input
expecting end of input
forced fail
意外的输入结束 - 期望输入结束
- 这没有任何意义,这是一个矛盾。
这是怎么回事?
这是秒差距的一个错误默认值,还是我正在查看的实际上是秒差距在解析时出现的一些潜在错误?
由于我的解析器 manyTill anyChar eof
消耗输入,我希望发出的唯一错误消息是强制失败
。我错过了什么?
最佳答案
按预期与 Megaparsec 配合使用:
module Main (main) where
import Data.Void
import Text.Megaparsec
import Text.Megaparsec.Char
type Parser = Parsec Void String
main :: IO ()
main = do
parseTest' (manyTill anyChar eof >> fail "forced fail" :: Parser String)
"somethingsomething"
当我运行它时,我得到:
1:19:
|
1 | somethingsomething
| ^
forced fail
您收到秒差距错误消息的原因是(如果我没记错的话)秒差距内部使用了很多有问题的“约定”。一种这样的约定是“意外的输入结束”由不存在其他意外的项目来表示。当然,这只会带来麻烦。当我开始将 Parsec 转换为 Megaparsec 时,我很害怕这是 Haskell 的“工业实力”解析库。
为什么你没有得到其他意想不到的组件?因为 fail
实际上会导致您的解析器失败(正如您所期望的),因此不会生成任何它们。它也不会生成预期的组件,但由于此功能,这些组件(在您的情况下是“预期输入结束”部分)会被拾取并合并到您的 fail
错误消息中:
λ> parseTest (many (char 'a') *> many (char 'b') *> empty) ""
parse error at (line 1, column 1):
unexpected end of input
expecting "a" or "b"
秒差距足够聪明,可以发现“a”和“b”在这里仍然是可能的。在这种情况下是有道理的,但会让你失望失败
。
秒差距中的错误消息是一件疯狂的事情,如果你开始批判性地阅读代码,那绝对是疯狂的。
附注我无意刻薄,但我们就称铲子为铲子吧。
关于haskell - "Unexpected end of input - expecting end of input"(秒差距),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47514596/