作为练习,我尝试用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,或者我应该以某种方式压缩解析。但话又说回来,我怎么能这样做呢?
答案 0 :(得分:1)
最好将我之前的评论扩展为完整的答案。
你的语法基本上是由空格分隔(和结束)的术语列表的列表,而空格又由|分隔。使用sepBy1
的解决方案不起作用,因为在LITERAL
之后有一个尾随空格 - sepBy1
假设在该空格后面有另一个术语并尝试将term
应用于|,失败了。
如果您的alternativeTerm
保证以空白字符(或多个字符)结尾,请按以下方式重写alternativeTerm
:
alternativeTerm = (term `sepEndBy1` space) >>= return . AlternativeTerm