1 介绍
因特网技术规范常常需要定义一个正式的语法,并且可以自由使用作者们认为有用的任何符号。多年来。一个修改的巴科斯诺尔范式 (BNF) 版本,称为扩展的 BNF (ABNF),已在许多因特网规范中被广泛使用。它权衡了紧凑性和简单性并具有合理的表征能力。在阿帕网 (Arpanet) 早期,每个规范都包含了各自的 ABNF 定义。这包含了 email 规范,[RFC733] 以及后来的 [RFC822],都成为了定义 ABNF 的常见引用。现在的文档将这些定义分隔开,允许选择性引用。可以预见的是,它还提供了一些修改和增强。
标准 BNF 和 ABNF 之前的区别涉及命名规则,重复 (repetition),选择 (alternative),顺序独立,和值范围。附录 B 提供了对几种因特网规范常见的核心词汇分析器的规则定义和编码。它提供了便利的方式并独立于文档正文中定义的元语言,且与其正式地位相独立。
2 规则定义
2.1 规则命名
一个规则的名称就是很简单的名称本身,也就是一序列字符,以字母符号开始,后面接着的是任意字母,数字,和连字符(横杠)的组合。
注意:
规则名称是大小写不敏感的。
这些名称
与原始 BNF 不一样的是,尖括号 ("<", ">") 不是必要的。然而,当它们的存在有助于识别规则名的使用时,就可能会用到尖括号。这通常局限于在自由形式的文档中使用的规则名称引用,或者用于区分部分没有使用空白符而组成一个字符串的规则,比如在下面讨论的重复中所示。
2.2 规则格式
规则是通过以下序列定义:
name = elements crlf
出于视觉考虑,规则定义是左对齐的。当一个规则需要多行的时候,后续的行是缩进的。左对齐和缩进与 ABNF 规则的首行相对,而没必要与文档的左边距相配。
2.3 终端值
规则被解析为终端值的字符串,有时也称作字符。在 ABNF 中,一个字符只是一个非负整形数字。在特定环境中,会指定值和字符集(比如 ASCII)的映射(编码)。
终端是由一个或多个数字字符指定的,这些字符的基本解释是显式的。以下的基本终端是当前定义的:
b = binary
d = decimal
x = hexadecimal
因此:
CR = %d13
CR = %x0D
分别指定了 [US-ASCII] 中回车的十进制和十六进制的表示形式。
出于紧凑性考虑,值可以组成一个串联的字符串,使用点号 (".") 在值中指示出字符的分隔。因此:
CRLF = %d13.10
ABNF 允许直接使用字面量文本字符串规范,使用引号包围。因此:
command = "command string"
字面量文本字符串可理解为一个串联的可打印的字符集。
注意:
ABNF 是大小写不敏感的并且这些字符集是 US-ASCII。
因此:
rulename = "abc"
以及:
rulename = "aBc"
会匹配 "abc", "Abc", "aBc", "abC", "ABc", "aBC", "AbC", 和
"ABC"。
想要指定大小写敏感的规则,那么需要单独地指定每一个字符。
举个例子:
rulename = %d97 %d98 %d99
或者
rulename = %d97.98.99
仅会匹配由小写形式字符组成的字符串,abc。
2.4 外部编码
因此,同样基于 ABNF 的语法可能有多种外部编码,比如一个用于 7-bit US-ASCII 环境,另一个用于二进制 8-bit 环境,使用 16-bit Unicode 的情况又有一个不一样的。编码细节已超出了 ABNF 所讨论的范围,然而附录 B 为 7-bit US-ASCII 环境提供了定义,这是因为它常见于多数因特网规范。
将语法和外部编码分隔开,目的是为了对于同样的语法可以选择使用不同的编码环境。
3 操作符
3.1 串联:Rule1 Rule2
通过排列一个规则名称序列,一个规则可以定义一个简单的,有序的值的字符串(比如,连续字符的串联)。举个例子:
foo = %x61 ; a
bar = %x62 ; b
mumble = foo bar foo
因此,规则
线性空白:串联是 ABNF 解析模型的核心。连续字符(值)字符串是根据 ABNF 中定义的规则解析的。对于因特网规范,因为某些历史原因而允许线性空白(空白和水平制表符)能够自由地,隐式地散落在主要结构中,比如界定特殊字符或原子字符串
注意:
此 ABNF 规范没有为线性空白提供隐式的规范。
任何想要允许在分隔符或字符串片段上使用线性空白的语法必须显式地指定它。在“核心”规则中提供这样的空白常常是有用的,这些规则会在更高级别的规则中使用。“核心”规则可能形成词法分析器,或者简单地成为主要规则集的一部分。
3.2 选择:Rule1 / Rule2
由斜杠 ("/") 分隔的元素则具有选择性。因此,
foo / bar
将接受
注意:
包含字母字符的使用引用包围的字符串是一种特殊的形式用于指定选择性字符,它被解释为一个非终端,用于表示包含字符的组合字符串集,具有规定的顺序,但是可以使用任意大小写混合的形式。
3.3 增量选择:Rule1 =/ Rule2
有时在分段中指定一个选择列表是比较方便的。这也就是说,初始规则可能匹配一个或多个选择,后续的规则定义将会添加到选择集中。对于其他继承自同一父级规则集的独立规范来说这是相当有用的,参数列表常常就使用这种方式。ABNF 允许通过以下结构实现这样的增量定义:
oldrule =/ additional-alternatives
所以这样的规则集
ruleset = alt1 / alt2
ruleset =/ alt3
ruleset =/ alt4 / alt5
与此规则等同
ruleset = alt1 / alt2 / alt3 / alt4 / alt5
3.4 值范围选择:%c##-##
选择性数字值的范围可以通过紧凑的方式指定,这使用一个连字符 ("-") 来指示选择性值的范围。因此:
DIGIT = %x30-39
这与下面的定义等同:
DIGIT = "0" / "1" / "2" / "3" / "4" / "5" / "6" /
"7" / "8" / "9"
串联的数字值和数字值范围不能在同一个字符串中指定。数字值可能使用点号来串联或可能使用连字符来指定一个之范围。因此,想要在行结束符 (end-of-line) 序列间指定一个可打印的字符,那么这样的规范可以是:
char-line = %x0D.0A %x20-7E %x0D.0A
3.5 序列组:(Rule1 Rule2)
圆括号中的元素可作为一个独立地元素对待,其内容是严格有序的。因此,
elem (foo / bar) blat
匹配 (elem foo blat) 或 (elem bar blat),而
elem foo / bar blat
匹配 (elem foo) 或 (bar blat)。
注意:
强烈建议使用分组记号,而不是依赖于对选择的正确阅读,特别是在选择由多个规则名或字面量组成的时候。
因此,推荐使用下面的形式:
(elem foo) / (bar blat)
这能更好地避免读者的误解。
序列组记号也用在自由文本中,以便在文中设置元素序列。
3.6 变量重复:*Rule
一个元素前的 "*" 操作符指的就是重复。完整的格式为:
*element
当 和 为可选的十进制数值的时候,表示至少有 个至多 个这样的 element。
默认值是 0 和无穷,所以 *
3*3
3.7 具体重复:nRule
规则格式:
element
等同于
*element
这也就是说,会出现
3.8 可选序列:[RULE]
可选元素序列使用方括号包围:
[foo bar]
等同于
*1(foo bar).
3.9 注释:; Comment
注释由一个分号开始,一直持续到行结束。这是一种简单的方式用于包含与规范相关的有用标注。
3.10 操作符优先级
上面描述的多个机制具有以下的优先级,从顶上的最高(绑定最紧)到底下的最低(最松):
Rule name, prose-val, Terminal value
Comment
Value range
Repetition
Grouping, Optional
Concatenation
Alternative
在使用选择操作符的时候如果随意混合串联可能会导致误解。
同样,推荐使用分组操作符来完成显式的串联分组。
4 ABNF 的 ABNF 定义
注意:
- 这个语法需要一种相对严格的规则格式。因此,一个规范包含的规则集版本可能需要预处理来确保它能够被一个 ABNF 解析器解析。
- 这个语法使用了 附录 B 中提供的规则。
rulelist = 1*( rule / (*c-wsp c-nl) )
rule = rulename defined-as elements c-nl
; continues if next line starts
; with white space
rulename = ALPHA *(ALPHA / DIGIT / "-")
defined-as = *c-wsp ("=" / "=/") *c-wsp
; basic rules definition and
; incremental alternatives
elements = alternation *c-wsp
c-wsp = WSP / (c-nl WSP)
c-nl = comment / CRLF
; comment or newline
comment = ";" *(WSP / VCHAR) CRLF
alternation = concatenation
*(*c-wsp "/" *c-wsp concatenation)
concatenation = repetition *(1*c-wsp repetition)
repetition = [repeat] element
repeat = 1*DIGIT / (*DIGIT "*" *DIGIT)
element = rulename / group / option /
char-val / num-val / prose-val
group = "(" *c-wsp alternation *c-wsp ")"
option = "[" *c-wsp alternation *c-wsp "]"
char-val = DQUOTE *(%x20-21 / %x23-7E) DQUOTE
; quoted string of SP and VCHAR
; without DQUOTE
num-val = "%" (bin-val / dec-val / hex-val)
bin-val = "b" 1*BIT
[ 1*("." 1*BIT) / ("-" 1*BIT) ]
; series of concatenated bit values
; or single ONEOF range
dec-val = "d" 1*DIGIT
[ 1*("." 1*DIGIT) / ("-" 1*DIGIT) ]
hex-val = "x" 1*HEXDIG
[ 1*("." 1*HEXDIG) / ("-" 1*HEXDIG) ]
prose-val = "<" *(%x20-3D / %x3F-7E) ">"
; bracketed string of SP and VCHAR
; without angles
; prose description, to be used as
; last resort
5 安全考量
本文档不涉及安全问题。
6 引用
6.1 标准化引用
- [US-ASCII] 美国国家标准协会,“编码字符集——7-bit 美国信息交换标准码”,ANSI X3.4,1986。
6.2 资料性引用
- [RFC733] Crocker, D., Vittal, J., Pogran, K., 和 D. Henderson,“ARPA 网络文本消息格式标准”,RFC 733,1977 年 11 月。
- [RFC822] Crocker, D.,“ARPA 因特网文本消息格式标准”,STD 11, RFC 822,1982 年 8 月。
附录 A 致谢
ABNF 语法原本指定在 RFC 733 中。SRI International 的 Ken L. Harrenstien 负责了重新将 BNF 编码为扩展的 BNF 的工作,这使得它的表示形式更加小且易于理解。
这个项目的开始只是为了剔除那些被 non-email 规范编写者反复引用的 RFC 822 的一部分,也就是扩展的 BNF 的描述。与其简单地将现有的文本转换成单独的文档,工作组还选择仔细考虑过去 15 年中所提供的现有规范和相关规范的不足和好处,并因此进行改进。这使得这个项目变成了比最初设想的更加具有雄心的项目。有趣的是,结果与最初的结果并没有很大的不同,尽管诸如移除列表符号这样的决定令人吃惊。
本规范“分开的”版本是 DRUMS 工作组的一部分,Jerome Abela, Harald Alvestrand, Robert Elz, Roger Fajman, Aviva Garrett, Tom Harsch, Dan Kohn, Bill McQuillan, Keith Moore, Chris Newman, Pete Resnick, 和 Henning Schulzrinne 做出了巨大额贡献。
还要特别感谢 Julian Reschke 将标准版本的草案转换成 XML 源格式。
附录 B ABNF 的核心 ABNF
本附录包含了一个常用的基础规则。基础规则名称采用大写形式。注意这些规则仅在采用 7-bit ASCII 或字符集是 7-bit ASCII 超集的情况下才是合法的 ABNF。
B.1 核心规则
某些基础规则名称采用大写形式,比如 SP, HTAB, CRLF, DIGIT, ALPHA,等等。
ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
BIT = "0" / "1"
CHAR = %x01-7F
; any 7-bit US-ASCII character,
; excluding NUL
CR = %x0D
; carriage return
CRLF = CR LF
; Internet standard newline
CTL = %x00-1F / %x7F
; controls
DIGIT = %x30-39
; 0-9
DQUOTE = %x22
; " (Double Quote)
HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
HTAB = %x09
; horizontal tab
LF = %x0A
; linefeed
LWSP = *(WSP / CRLF WSP)
; Use of this linear-white-space rule
; permits lines containing only white
; space that are no longer legal in
; mail headers and have caused
; interoperability problems in other
; contexts.
; Do not use when defining mail
; headers and use with caution in
; other contexts.
OCTET = %x00-FF
; 8 bits of data
SP = %x20
VCHAR = %x21-7E
; visible (printing) characters
WSP = SP / HTAB
; white space
B.2 常用编码
外部地,数据表示为“网络虚拟 ASCII”(也就是,7-bit US-ASCII 占用一个 8-bit 字段),高比特位 (8th) 设置为 0。字符串值使用“网络字节顺序”,较高值的字节在左边表示并且首先通过网络发送。