我有以下 ABNF 语法:
zero = ["0"] "0"
我希望这与字符串匹配0
,00
但它似乎只匹配00
?为什么?
repl-it 演示:https ://repl.it/@DanStevens/abnf-rule-zero-0-0-matches-00-but-not-0
我有以下 ABNF 语法:
zero = ["0"] "0"
我希望这与字符串匹配0
,00
但它似乎只匹配00
?为什么?
repl-it 演示:https ://repl.it/@DanStevens/abnf-rule-zero-0-0-matches-00-but-not-0
好问题。
ABNF(“Augmented Backus Naur Form”9 由RFC 5234定义,它是文档的当前版本,旨在阐明许多 RFC 使用(有变体)的符号。
不幸的是,虽然 RFC 5234 详尽地描述了ABNF 的语法,但它并没有提供太多清晰的语义声明。特别是,它没有指定 ABNF 交替是无序的(就像在 BNF 的正式语言定义中那样)还是有序的(就像在“PEG”——解析表达式语法——表示法中那样)。请注意,可选性/重复性只是交替的类型,因此如果您选择一种约定进行交替,您很可能也会选择它作为可选性和重复性。
在这种情况下,差异很重要。如果订购了交替,那么解析器将不会在某些替代成功后备份以尝试不同的替代。就可选性而言,这意味着如果流中存在可选元素,解析器将永远不会重新考虑接受可选元素的决定,即使某些后续元素无法匹配。如果您采取这种观点,那么交替不会分布在串联之上。 ["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
,这将被接受为满足 in 的可选项[repeat]
,repetition
并且element
随后将失败。
事实上,这个例子(或类似的例子)在 RFC 5234 中作为一个勘误表报告给了 IETF ,并且该勘误表被拒绝为不必要的,因为验证者认为应该产生正确的解析,从而提供证据证明官方观点是 ABNF 不是 PEG 的变体。显然,APG 解析器生成器的作者(他似乎也没有记录他们的解释)不同意这种观点。建议的勘误表选择了与您提出的大致相同的解决方案:
repeat = *DIGIT ["*" *DIGIT]
虽然严格来说并不相同;原来的repeat
不能匹配空字符串,但替换的可以。(由于repeat
语法中唯一的使用是可选的,因此这没有任何实际区别。)
(披露说明:我不是 PEG 的粉丝。因此,上述答案可能并非没有偏见。)