Parsec:如何消除有关空格的解析器错误

Parsec: How to silence parser errors about white spaces

我有以下解析器来解析包含重定向的 BASH 类行。

lineRedirect :: P.Parsec String () String
lineRedirect = do
  lcmd <- P.spaces *> (P.many1 command P.<?> "command")
  P.char '>'
  rcmd <- P.spaces *> (P.many1 command P.<?> "redirection target")
  return $ (intercalate ";" lcmd) ++ " ++ " ++ (intercalate ";" rcmd)   
  where
    command :: P.Parsec String () String
    command = P.many1 P.alphaNum <* P.spaces

它似乎工作得很好,但我想关闭任何出现的 "expecting space" 或 "expecting whitespace"。

例如:

> P.parseTest lineRedirect "   > target"
parse error at (line 1, column 4):
unexpected ">"
expecting space or command

我只想 "expecting command" 这里。

> P.parseTest lineRedirect "invalid! > target"
parse error at (line 1, column 8):
unexpected "!"
expecting letter or digit, white space or ">"

此处相同,但没有 "white space"。

这似乎有效

lineRedirect = do
  lcmd <- P.try (P.spaces *> P.many1 command) P.<?> "command"
  ...

不过我不喜欢 try

意识到 spaces 已经是一个带有自己的错误消息的复合解析器后,一切都变得简单了...

这是我想出的:

lineRedirect :: P.Parsec String () (String, String)
lineRedirect = do
  cmd <- spaces' *> command
  P.char '>'
  tgt <- spaces' *> target
  return (cmd, tgt)

  where
    command :: P.Parsec String () String
    command = (P.many1 (P.noneOf ">") P.<?> "command")  <* spaces'

    target :: P.Parsec String () String
    target = (P.many1 P.anyChar P.<?> "redirection target") <* spaces' <* P.eof

    spaces' = P.skipMany (P.space P.<?> "")