我有以下ABNF语法:
zero = ["0"] "0"
我希望它与字符串0
和00
匹配,但似乎只匹配00
?为什么?
演示示例:https://repl.it/@DanStevens/abnf-rule-zero-0-0-matches-00-but-not-0
答案 0 :(得分:3)
好问题。
ABNF(“增强Backus Naur形式” 9由RFC 5234定义,{NF}是文档的当前版本,旨在阐明许多RFC使用的符号(带有变体)。
不幸的是,尽管RFC 5234详尽地描述了ABNF的语法,但它并没有以明确的方式表达语义的方式。特别是,它没有指定ABNF替换是无序的(如在BNF的正式语言定义中)还是有序的(如在"PEG" -- Parsing Expression Grammar中的符号)。请注意,选择性/重复仅仅是交替的类型,因此,如果您选择一种约定进行交替,则很可能也会为选择性和重复选择它。
在这种情况下,区别很重要。如果命令了交替,那么解析器将不会备份以在某些替代方法成功后尝试其他替代方法。在可选性方面,这意味着如果流中存在可选元素,则解析器将永远不会重新考虑接受可选元素的决定,即使某些后续元素无法匹配。如果您采用这种观点,那么交替不会在串联中分布。 ["0"]"0"
恰好是("0"/"")"0"
,与"00"/"0"
不同。后一个表达式将与单个0
匹配,因为第二个选择将在第一个失败后尝试。您使用的前一个表达式不会。
我不认为RFC 5234的作者会采用这种观点,尽管如果他们在文档中做出明确的决定会更有帮助。我唯一支持我的信念的真实证据是,如果认为重复是有序的,则RFC 5234中包含的用于描述ABNF本身的ABNF将会失败。特别是重复的规则:
repetition = [repeat] element
repeat = 1*DIGIT / (*DIGIT "*" *DIGIT)
无法匹配7*"0"
,因为7
将与repeat
的第一个替代项匹配,该替代项将被视为满足{{1}中的可选[repeat]
},然后repetition
将失败。
实际上,此示例(或与之类似的示例)以erratum in RFC 5234的形式报告给IETF,并且由于不需要验证,因此也拒绝了错误,因为验证者认为应该产生正确的解析,从而提供有证据表明,官方观点是ABNF不是PEG的变体。显然,APG解析器生成器的作者(也不似乎也没有记录其解释)的作者并不认同这种观点。建议的勘误选择了与您想到的大致相同的解决方案:
element
尽管严格说来并不一样;原始repeat = *DIGIT ["*" *DIGIT]
不能匹配空字符串,但是替换字符串可以。 (由于语法中repeat
的唯一使用是可选的,因此这没有任何实际区别。)
(公开说明:我不是PEG的粉丝。因此上述答案可能并非毫无偏见。)