我想使用Haskell的parsec库实现这个语法规则:
((a | b | c)* (a | b))?
Run Code Online (Sandbox Code Playgroud)
哪个是接受可选(即可能为空)字符串的解析器规则.如果它所接受的字符串不为空,则可以通过传递零次或多次出现的a b或者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
Run Code Online (Sandbox Code Playgroud)
第一次尝试可能如下所示:
myParser = option "" $ do
str <- many (a <|> b <|> c)
ch <- a <|> b
return (str ++ [ch])
Run Code Online (Sandbox Code Playgroud)
但是many在每个测试用例中只消耗所有"a","b"和"c"字符,a <|> b不会消耗任何字符.
问题:
使用parsec组合器,((a | b | c)* (a | b))?定义的正确实现是myParser什么?
我们还可以稍微不同地说明这一点:c在您的解析器中,只有在后面跟有任何标记时才可能成功,这可以通过单个来完成lookAhead:
myParser = many (a <|> b <|> (c <* (lookAhead anyToken <?> "non C token"))) <* eof
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
268 次 |
| 最近记录: |