Haskell atopassec中的条件前瞻

Haskell atopassec中的条件前瞻,haskell,attoparsec,Haskell,Attoparsec,假设有一个数据结构,它表示一个包含注释的文本 data TWC = T Text TWC -- text | C Text TWC -- comment | E -- end deriving Show 就这样一串 "Text, {-comment-}, and something else" 可以被编码为 T "Text, " (C "comment" (T ", and something else" E)) 注释块和E的解析器非常简单: twcP :: Parser

假设有一个数据结构,它表示一个包含注释的文本

data TWC
  = T Text TWC -- text
  | C Text TWC -- comment
  | E -- end
  deriving Show
就这样一串

"Text, {-comment-}, and something else"
可以被编码为

T "Text, " (C "comment" (T ", and something else" E))
注释块和
E
的解析器非常简单:

twcP :: Parser TWC
twcP = eP <|> cP <|> tP

cP :: Parser TWC
cP = do
  _ <- string "{-"
  c <- manyTill anyChar (string "-}")
  rest <- cP <|> tP <|> eP
  return (C (pack c) rest)

eP :: Parser TWC
eP = do
  endOfInput
  return E

所以,问题是如何表达直到输入结束或注释部分的解析逻辑?换句话说,如何实现条件先行解析器?

没错,有问题的代码是
tP
的第一行,它贪婪地解析文本而不停在注释处:

tP = do
  t <- many1 anyChar
为了实现前瞻,我们可以使用combinator,它在不使用输入的情况下应用解析器。这允许我们进行
文本
解析,直到它到达
注释
(而不使用它),或
endOfInput

-- Parse one non-comment text string (working implementation)
text :: Parser Text
text = textTill anyChar (void (lookAhead comment) <|> endOfInput)
tP = do
  t <- many1 anyChar
-- Like manyTill, but pack the result to Text.
textTill :: Alternative f => f Char -> f b -> f Text
textTill p end = pack <$> manyTill p end

-- Parse one comment string
comment :: Parser Text
comment = string "{-" *> textTill anyChar (string "-}")

-- Parse one non-comment text string (problematic implementation)
text :: Parser Text
text = pack <$> many1 anyChar

-- TWC parsers:

twcP :: Parser TWC
twcP = eP <|> cP <|> tP

cP :: Parser TWC
cP = C <$> comment <*> twcP

eP :: Parser TWC
eP = E <$ endOfInput

tP :: Parser TWC
tP = T <$> text <*> twcP
-- Parse one non-comment text string (working implementation)
text :: Parser Text
text = textTill anyChar (void (lookAhead comment) <|> endOfInput)
ghci> parseOnly twcP "text{-comment-} post"
Right (T "text" (C "comment" (T " post" E)))