2

作为练习,我尝试使用 Megaparsec 解析 EBNF/ABNF 语法。我得到了一些琐碎的东西,比如终端和可选的工作,但我正在努力寻找替代品。使用此语法:

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

我收到此错误:

unexpected '|'
expecting "IDENTIFIER", "LITERAL", ''', '[', or white space

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

我能做些什么呢?更改我的 EBNF 的 ADT,或者我应该以某种方式使解析变平。但话又说回来,我该怎么做呢?

4

1 回答 1

1

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

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

如果您alternativeTerm保证以空格字符(或多个)结尾,请将您的改写alternativeTerm如下:

alternativeTerm = (term `sepEndBy1` space) >>= return . AlternativeTerm
于 2017-05-23T14:41:07.297 回答