作为一种练习项目,我想实现一个解析IRC消息的库。我需要解析的一件事是短名,由BNF给出:
shortname = ( letter / digit ) *( letter / digit / "-" ) *( letter / digit )
我有解析器alphaNum
和(alphaNum <|> char '-')
,对应于这些元素,这很容易。但是,我很难将它们组合起来以符合规范。 between alphaNum alphaNum (alphaNum <|> char '-')
无效,我无法将lookAhead
纳入其中,使其按照我的意愿行事。
答案 0 :(得分:2)
问题是前一部分消耗了最后一部分(字母或数字,但不是破折号)。我建议将语法改为
短名=(字母/数字)*(*(“ - ”)(字母/数字))
或者更高效
shortname = +(字母/数字)*(+(“ - ”)+(字母/数字))
这确保了虽然内部部分可以包含字母,数字和短划线,但任何短划线必须始终后跟字母/数字。一个parsec解决方案可能是
shortName :: Stream s m Char => ParsecT s u m String
shortName = (++) <$> many1 alphaNum
<*> (concat <$> many ((++) <$> many1 (char '-')
<*> many1 alphaNum))