扩充巴科斯范式
在计算机科学中,扩充巴科斯-瑙尔范式(ABNF)是一种基于巴科斯-瑙尔范式(BNF)的元语言,但它有自己的语法和派生规则。ABNF的目的是提供一种用于描述双向通信协议的语言的形式系统。它是由第68号互联网标准 (页面存档备份,存于)("STD 68",大小写样式按照原文)定义的,也就是RFC 5234,经常用于互联网工程任务组(IETF)通信协议的定义语言。[1][2]
RFC 5234取代RFC 4234、2234、733。[3]RFC 7405为RFC 5234提供了支持区分大小写字符串的扩展。
介绍
一个ABNF规范是一些推导规则的集合,书写为:
规则 = 定义;注释CR LF
其中:
- “规则”是不区分大小写的非最终符号
- “定义”由定义该规则的一系列符号组成
- “注释”用于记录
- “CR LF”(回车、换行)用来结束
规则名字是不区分大小写的: <rulename>
, <Rulename>
, <RULENAME>
和<rUlENamE>
都指的是同一个规则。规则名字由一个字母以及后续的多个字母、数字和连字符(减号)组成。
用尖括号(“<
”,“>
”)包围规则名并不是必需的(如同它们在BNF里那样),但是它们可以用来在散文中界定规则名,以方便识别出规则名。
最终值
最终值由一个或多个数值字符指定。
数值字符可按下面的方式指定:先是一个百分号“%
”,紧跟着基数(b = 二进制, d = 十进制, x = 十六进制),再其后是这个数值或数值串(用“.
”来指示串联)。例如:“回车”可以用十进制的%d13
或十六进制的%x0D
来指定,而“回车换行”则可以用%d13.10
来指定。
字面文本是通过包含在在双引号("
)中字符串来指定的。这些字符串是不区分大小写的,使用的字符集是(US-)ASCII。所以字符串“abc”将匹配“abc”,“Abc”,“aBc”,“abC”,“ABc”,“AbC”,“aBC”和“ABC”。对于区分大小写的匹配,必须定义明确的字符,例如:若要匹配“aBc”,定义必须是%d97 %d66 %d99
。
操作符
空白字符
空白字符被用来分隔定义中的各个元素:要使空格被识别为分割符则必须明确的包含它。
串联
规则1规则2
规则可以通过列出一系列的规则名来定义。
要匹配字符串“aba”可以使用下列规则:
foo = %x61 ; a
bar = %x62 ; b
mumble = foo bar foo
选择 /
规则1 / 规则2
一个规则可以通过用斜杠(“/
”)分隔的可供选择的子规则列表来定义。
要接受规则<foo>或规则<bar>可构造如下规则:
foobar = foo / bar
增量选择 =/
规则1 =/ 规则2
可以通过在规则名和定义之间使用“=/
”来向一个规则增加补充选择。
规则
ruleset = alt1 / alt2 / alt3 / alt4 / alt5
等价于
ruleset = alt1 / alt2
ruleset =/ alt3
ruleset =/ alt4 / alt5
值范围%c##-##
%c##-##
数值范围可以通过使用连字符(“-
”)来指定。
规则
OCTAL = "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7"
等价于
OCTAL = %x30-37
序列组合 ()
(规则1规则2)
在定义中,元素可以放置在圆括号中来将规则组合起来,该组合视为单个元素。
要匹配“elem foobar snafoo”或“elem tarfoo snafoo”可以构造下列规则:
group = elem (foobar / tarfoo) snafoo
要匹配“elem foobar”或“tarfoo snafoo”可以构造下列规则:
group = elem foobar / tarfoo snafoo
group = (elem foobar) / (tarfoo snafoo)
不定量重复m*n
元素前面的星号*
表示重复,其完整形式是:
m*n规则
要表示一个元素的重复,就要使用<m>*<n>元素
形式。可选的<m>
给出要包含的元素的最小数目,默认为0;可选的<n>
给出要包含的元素的最大数目,默认为无穷大。
例子:
*元素
表示零个或更多元素1*元素
表示一个或更多元素2*4元素
表示两个至四个元素
定量重复n
n规则
要表示特定数目的元素可使用形式<n>元素
,相当于用不定量重复形式表示的<n>*<n>元素
。
使用2DIGIT
得到两个数字,使用3DIGIT
得到三个数字。(DIGIT在下面的核心规则中定义,也见例子中的zip-code)。
可选序列[]
[规则]
要表示可选元素,下列构造是等价的:
[foobar snafoo]
*1(foobar snafoo)
0*1(foobar snafoo)
注释;
;注释
注释从一个分号(“;
”)开始,并持续到此行的结束。
操作符优先级
下面的操作符给出了从高(结合最紧密)到低(结合最松散)的优先级:
- 规则名、最终值
- 注释;
- 值范围%c##-##
- 重复*
- 组合 ()、可选[]
- 串联
- 选择 /
选择操作符与串联一起使用会造成混淆,因此建议使用组合来确保串联组的明确。
例如:
我们 = 你 我/他 她
会产生下面两种歧义:
(你 我)/(他 她)
(你) (我/他) (她)
所以,使用组合来确保不会产生歧义:
(你 我)/(他 她)
核心规则
核心规则定义于ABNF标准中。
规则 | 形式定义 | 意义 |
---|---|---|
ALPHA | %x41-5A / %x61-7A | 大写和小写ASCII字母(A-Z, a-z) |
DIGIT | %x30-39 | 数字(0-9) |
HEXDIG | DIGIT / "A" / "B" / "C" / "D" / "E" / "F" | 十六进制数字(0-9, A-F, a-f) |
DQUOTE | %x22 | 双引号 |
SP | %x20 | 空格 |
HTAB | %x09 | 横向制表符 |
WSP | SP / HTAB | 空格或横向制表符 |
LWSP | *(WSP / CRLF WSP) | 直线空白(晚于换行) |
VCHAR | %x21-7E | 可见(打印)字符 |
CHAR | %x01-7F | 任何7-位US-ASCII字符,不包括NUL(%x00) |
OCTET | %x00-FF | 8位数据 |
CTL | %x00-1F / %x7F | 控制字符 |
CR | %x0D | 回车 |
LF | %x0A | 换行 |
CRLF | CR LF | 互联网标准换行 |
BIT | "0" / "1" | 二进制数字 |
例子
在巴科斯范式(BNF)条目中的邮政地址的例子可以被指定为:
postal-address = name-part street zip-part
name-part = *(personal-part SP) last-name [SP suffix] CRLF
name-part = / personal-part CRLF
personal-part = first-name / (initial ".")
first-name = *ALPHA
initial = ALPHA
last-name = *ALPHA
suffix = ("Jr." / "Sr." / 1*("I" / "V" / "X"))
street = [apt SP] house-num SP street-name CRLF
apt = 1*4DIGIT
house-num = 1*8(DIGIT / ALPHA)
street-name = 1*VCHAR
zip-part = town-name "," SP state 1*2SP zip-code CRLF
town-name = 1*(ALPHA / SP)
state = 2ALPHA
zip-code = 5DIGIT ["-" 4DIGIT]
隐患
RFC 5234 (页面存档备份,存于)加入了一条结合LWSP的警告,如下:
若使用该直线空白规则,将允许存在只包含空白字符的行,而这样的行在邮件头中已不再合法,并且已在其他环境中导致了互操作问题。 不要在定义邮件头时使用它,在其他环境下使用时也要格外注意。