gpt4 book ai didi

parsing - Haskell Parsec 组合器 'many' 应用于接受空字符串的解析器

转载 作者:行者123 更新时间:2023-12-02 15:17:12 26 4
gpt4 key购买 nike

import Text.ParserCombinators.Parsec

delimiter :: Parser ()
delimiter = do char '|'
return ()
<?> "delimiter"


eol :: Parser ()
eol = do oneOf "\n\r"
return ()
<?> "end of line"

item :: Parser String
item = do entry <- manyTill anyChar (try eol <|> try delimiter <|> eof)
return entry

items :: Parser [String]
items = do result <- many item
return result

当我使用上面的代码运行 parseTest items "a|b|c" 时,出现以下错误:

*** Exception: Text.ParserCombinators.Parsec.Prim.many: 
combinator 'many' is applied to a parser that accepts an empty string.

我相信它与eofmany item有关,如果我删除eof,那么我可以让它工作只要该行不以 eof 结尾,这使得它毫无用处。

我意识到我可以只使用 sepBy 但我感兴趣的是为什么这段代码不起作用以及如何让它起作用。

最佳答案

many这样的解析器确实不能应用于接受空字符串的解析器,因为这使得语法变得模糊:你多久解析一次空字符串?选择不同的数字可能会导致不同的解析结果...

您认为许多项目是有问题的组合是正确的。 item 是根据 manyTill 定义的。 (游览:顺便说一句,您可以将 manyTill 简化为

item :: Parser String
item = manyTill anyChar (eol <|> delimiter <|> eof)

不需要 doreturn,也不需要 try,因为三个解析器中的每一个都因此,解析器 manyTill 会解析任意数量的字符,后跟 eoldelimitereof。现在,eoldelimiter 在成功时实际上会消耗至少一个字符,但 eof 不会。解析器 eof 在输入结束时成功,但可以多次应用。例如,

ghci> parseTest (do { eof; eof }) ""
()

它不消耗任何输入,因此使 item 在空字符串(在输入末尾)上成功成为可能,从而导致歧义。

要解决此问题,您确实可以重写语法并转向诸如 sepBy 之类的内容,或者您​​可以尝试区分正常的 item(其中 eof 不允许作为最终 item 中的结束标记(其中允许 eof)。

关于parsing - Haskell Parsec 组合器 'many' 应用于接受空字符串的解析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19899931/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com