"Unexpected end of input - expecting end of input" 秒差距
"Unexpected end of input - expecting end of input" in parsec
考虑这个 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
unexpected end of input - expecting end of input
- 这没有任何意义,这是一个矛盾。
这是怎么回事?
它是 parsec 中的错误默认值,还是我正在查看的实际上是 parsec 在解析时出现的一些潜在错误堆栈?
由于我的解析器 manyTill anyChar eof
消耗输入,我希望发出的唯一错误消息是 forced fail
。我错过了什么?
按预期使用 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 错误消息的原因是(如果我没记错的话)Parsec 在内部使用了很多有问题的 "conventions"。一种这样的约定是 "unexpected end of input" 表示没有其他意外项目。当然,这只是自找麻烦。当我开始将 Parsec 变成 Megaparsec 时,我害怕这是 Haskell 的 "industrial strength" 解析库。
为什么你没有得到其他意想不到的成分?因为 fail
实际上会导致您的解析器失败(正如您所期望的那样),所以不会生成它们中的任何一个。它也不会生成预期的组件,但是那些(在你的情况下是 "expecting end of input" 部分)被拾取并合并到你的 fail
错误消息中,因为这个特性:
λ> parseTest (many (char 'a') *> many (char 'b') *> empty) ""
parse error at (line 1, column 1):
unexpected end of input
expecting "a" or "b"
Parsec 足够聪明,可以计算出 "a" 和 "b" 在这里仍然是可能的。在这种情况下是有道理的,但是 fail
.
让你失望了
Parsec 中的错误消息是一件疯狂的事情,如果你开始批判性地阅读代码,那绝对是疯狂的。
P.S。我不想刻薄,但让我们称铲子为铲子吧。
考虑这个 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
unexpected end of input - expecting end of input
- 这没有任何意义,这是一个矛盾。
这是怎么回事?
它是 parsec 中的错误默认值,还是我正在查看的实际上是 parsec 在解析时出现的一些潜在错误堆栈?
由于我的解析器 manyTill anyChar eof
消耗输入,我希望发出的唯一错误消息是 forced fail
。我错过了什么?
按预期使用 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 错误消息的原因是(如果我没记错的话)Parsec 在内部使用了很多有问题的 "conventions"。一种这样的约定是 "unexpected end of input" 表示没有其他意外项目。当然,这只是自找麻烦。当我开始将 Parsec 变成 Megaparsec 时,我害怕这是 Haskell 的 "industrial strength" 解析库。
为什么你没有得到其他意想不到的成分?因为 fail
实际上会导致您的解析器失败(正如您所期望的那样),所以不会生成它们中的任何一个。它也不会生成预期的组件,但是那些(在你的情况下是 "expecting end of input" 部分)被拾取并合并到你的 fail
错误消息中,因为这个特性:
λ> parseTest (many (char 'a') *> many (char 'b') *> empty) ""
parse error at (line 1, column 1):
unexpected end of input
expecting "a" or "b"
Parsec 足够聪明,可以计算出 "a" 和 "b" 在这里仍然是可能的。在这种情况下是有道理的,但是 fail
.
Parsec 中的错误消息是一件疯狂的事情,如果你开始批判性地阅读代码,那绝对是疯狂的。
P.S。我不想刻薄,但让我们称铲子为铲子吧。