使用Megaparsec嵌套sepBy解析EBNF

时间:2017-05-23 11:39:23

标签: parsing haskell ebnf megaparsec

作为练习,我尝试用Megaparsec解析EBNF / ABNF语法。我得到了像终端和可选项一样的琐碎工作,但我正在努力寻找替代方案。用这个语法:

RewriteRule ^(en/news)/news/single/article/([\w-]+)\.html$ /$1/$2 [R=302,L]

这段代码:

S ::= 'hello' ['world'] IDENTIFIER LITERAL | 'test';

我收到此错误:

production :: Parser Production
production = sepBy1 alternativeTerm (char '|') >>= return . Production

alternativeTerm :: Parser AlternativeTerm
alternativeTerm = sepBy1 term space >>= return . AlternativeTerm

term :: Parser Term
term = terminal
    <|> optional
    <|> identifier
    <|> literal

我猜altTerm解析器在遇到无法解析的序列时会返回生产解析器而不会抛出错误。

我该怎么办?改变我的EBNF的ADT,或者我应该以某种方式压缩解析。但话又说回来,我怎么能这样做呢?

1 个答案:

答案 0 :(得分:1)

最好将我之前的评论扩展为完整的答案。

你的语法基本上是由空格分隔(和结束)的术语列表的列表,而空格又由|分隔。使用sepBy1的解决方案不起作用,因为在LITERAL之后有一个尾随空格 - sepBy1假设在该空格后面有另一个术语并尝试将term应用于|,失败了。

如果您的alternativeTerm保证以空白字符(或多个字符)结尾,请按以下方式重写alternativeTerm

alternativeTerm = (term `sepEndBy1` space) >>= return . AlternativeTerm