ABNF规则“零= [“ 0”]“ 0”`匹配`00`,但不匹配`0`

时间:2019-06-21 16:04:24

标签: grammar abnf

我有以下ABNF语法:

zero = ["0"] "0"

我希望它与字符串000匹配,但似乎只匹配00?为什么?

演示示例:https://repl.it/@DanStevens/abnf-rule-zero-0-0-matches-00-but-not-0

1 个答案:

答案 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的粉丝。因此上述答案可能并非毫无偏见。)