使用秒差:
-- parser for the rest of the line
rest = manyTill anyChar (eof <|> char '\n' *> return ()) <* optional (char '\n')
-- change this to accept lines, but Just the valid ones
valid :: Parser (Maybe String)
valid = (Just <$> string "valid" <|> const Nothing <$> anyChar) <* rest
-- filter out Nothing
valids = catMaybes <$> many valid
-- Run
*Foo> runParser valids () "input" "valid1\ninvvalid2\nvalid3"
Right ["valid","valid"]
*Foo> runParser valids () "input" "valid1\nvalid2\nvalid3"
Right ["valid","valid","valid"]
在这里我必须做一个错误的破解:const Nothing <$> anyChar
所以valid
总是至少消耗一些东西,否则我不能把它交给many
. 但是,Maybe
您可以根据需要重写解析器(例如强制换行)
非常相似的方法适用于 attoparsec,抱歉破坏了自己制作的乐趣。
{-# LANGUAGE OverloadedStrings #-}
import Data.Attoparsec.Text
import Control.Applicative
import Data.Maybe
import Data.Text
-- parser for the rest of the line
rest = skipWhile (/= '\n') <* optional endOfLine
-- change this to accept lines, but Just the valid ones
valid :: Parser (Maybe Text)
valid = (Just <$> string "valid" <|> const Nothing <$> anyChar) <* rest
-- filter out Nothing
valids = catMaybes <$> many valid
*Main> parseOnly valids "valid1\nvalid2\nvalid3"
Right ["valid","valid","valid"]
*Main> parseOnly valids "valid1\ninvalid2\nvalid3"
Right ["valid","valid"]