有什么方法可以用 Parsec 来表达结尾吗?

Is there any way to express end with in Parsec?

我正在尝试实现一些解析函数,该函数仅接受此字符串末尾的某些特定字符,如果给定字符是 ! 使用正则表达式,则为 .*!$

我试过使用下面的函数,但是它不起作用,因为它会在匹配结束之前消耗字符。

endWith :: Char -> Parser ()
endWith x = many anyChar >> char x >> return ()

需要注意的一件事是:"ab!cd!" 的预期输出是 ("ab!cd!", "") 并且 "ab!cd" 根本不应被此解析器使用,因为它不是以 !。使用 <|>

时,all 或 northing 非常重要

是否可以使用秒差距?我想需要一些高级组合。

manyTill 这样做。

endWith :: Char -> Parser String
endWith x = anyChar `manyTill` char x

这是您要找的吗?

import Text.Parsec
import Text.Parsec.String

endWith :: Char -> Parser String
endWith x = do cs <- many anyChar -- consume rest of input
               case cs of
                 [] -> fail "expecting !"
                 _  -> if last cs == '!' then return cs
                                         else fail "did not end in !"

test1 = parseTest (endWith '!') "This is a test!"
test2 = parseTest (endWith '!') "ab!cd!"
test3 = parseTest (endWith '!') "ab!cd"

这是成功解析 "ab!""ab!cd!" 但拒绝 "ab""ab!cd" 的一个:

import Text.Parsec
import Text.Parsec.String

endWith :: Char -> Parser String
endWith c = manyTill anyChar (try $ char c <* eof)

(注意返回的结果不包括结尾的c):

"ab!"      Succeeds with "ab"
"ab!cd!"   Succeeds with "ab!cd"
"ab"       Fails
"ab!cd"    Fails