【发布时间】:2016-01-19 01:47:10
【问题描述】:
我想使用 Haskell 的 parsec 库来实现这个语法规则:
((a | b | c)* (a | b))?
这是一个接受可选(即可能为空)字符串的解析器规则。如果它接受的字符串不为空,则可以通过传递零次或多次出现的ab 或c 解析器来使用它,但最外面的? 可选解析器接受的字符串必须被解析器a 或b 使用,但不是c。这是一个例子:
module Main where
import Text.Parsec
import Text.Parsec.Text
a,b,c :: GenParser () Char
a = char 'a'
b = char 'b'
c = char 'c'
-- ((a | b | c)* (a | b))?
myParser = undefined
shouldParse1,shouldParse2,shouldParse3,
shouldParse4,shouldFail :: Either ParseError String
-- these should succeed
shouldParse1 = runParser myParser () "" "" -- because ? optional
shouldParse2 = runParser myParser () "" "b"
shouldParse3 = runParser myParser () "" "ccccccb"
shouldParse4 = runParser myParser () "" "aabccab"
-- this should fail because it ends with a 'c'
shouldFail = runParser myParser () "" "aabccac"
main = do
print shouldParse1
print shouldParse2
print shouldParse3
print shouldParse4
print shouldFail
第一次尝试可能如下所示:
myParser = option "" $ do
str <- many (a <|> b <|> c)
ch <- a <|> b
return (str ++ [ch])
但many 只消耗每个测试用例中的所有“a”、“b”和“c”字符,而a <|> b 没有可消耗的字符。
问题:
使用 parsec 组合子,((a | b | c)* (a | b))? 定义 myParser 的正确实现是什么?
【问题讨论】:
-
也许解析 (a|b|c)+ 并在以 c 结尾时拒绝它?