【神马东东】
巴克斯范式(又称巴科斯-诺尔范式,
BNF,short for
Backus-
Naur
Form)是由John Backus 和 Peter Naur 首次引入的一种与
上下文无关,使用
形式化符号来
描述给定语言的
语法,简单说就是 一种通用描述规则,用来描述各种计算机语言语法定义。
后来在RFC2234/RFC4234中又定义了
扩充
的巴科斯范式(
EBNF),再后来又在RFC
5234中再定义了 扩展的巴科斯范式(ABNF),RFC5234取代了RFC4234 和RFC2234。扩展的巴科斯使巴科斯范式更加完善。
现在,几乎所有的IT编程语言书籍 或 IETF在编写RFC等规范文档 等时候,你都可以看到作者使用
巴科斯范式及其扩展来定义某一个语法规则 或 变量格式。
下文对巴科斯范式或扩展的巴科斯范式,都称为 巴科斯范式 或 BNF 。
【举两个BNF例子先】
(例子1) 在MIME的RFC( http://tools.ietf.org/html/rfc2045)中,作者用BNF描述了一个叫 version 的定义,其BNF描述为:
version := "MIME-Version" ":" 1*DIGIT "." 1*DIGIT
于是你在实际生活中,就可以从一个MIME结构体中看到这个version定义,如从一封电子邮件的信头看到 MIME-Version: 1.0 。
为什么是“MIME-Version: 1.0”,而不是“MIME-Version: 1.0000”,或不是“MIME Version: 1.0”呢?
因为这个version字段的BNF已经描述好了,取值的格式一定要根据其描述来。
(例子2) 在HTTP的RFC( http://tools.ietf.org/html/rfc2616)中,作者用BNF描述了http Response的格式:
Response = Status-Line
; Section 6.1
*(( general-header
; Section 4.5
| response-header
; Section 6.2
| entity-header ) CRLF)
; Section 7.1
CRLF
[ message-body ]
; Section 7.2
文档中,作者又使用BNF来描述
Request-Line 等其他名词(如
Request-Line,
Method,
Request-URI等
):
Request-Line = Method SP Request-URI SP HTTP-Version CRLF
Method = "OPTIONS"
; Section 9.2
| "GET"
; Section 9.3
| "HEAD"
; Section 9.4
| "POST"
; Section 9.5
| "PUT"
; Section 9.6
| "DELETE"
; Section 9.7
| "TRACE"
; Section 9.8
| "CONNECT"
; Section 9.9
| extension-method
extension-method = token
Request-URI = "*" | absoluteURI | abs_path | authority
【范式说明】
BNF
基本要点(部分)
:
- BNF的基本语法: <符号> ::= <使用符号的表达式>
- 双引号(" ")中的字符串("word")代表这些字符本身,而double_quote代表双引号。
- 双引号外的字符串(有可能带下划线)代表语法部分。
- 尖括号(< >)中的内容为必选项。
- 方括号([ ])中的内容为可选项。
- 大括号({ })中的内容为可重复0至无限次的项。
- 竖线(|)表示其左右两侧任选一项,相当于 OR 的意思。
- ::= 符号表示 “被定义为”的意思。
ABNF 基本扩充要点(部分):
- ABNF的基本语法: name = elements crlf
- 用字符映射的ASCII码表示一个字符,格式为 %TYPE ,其中TYPE为进制(b/d/x三种), b for binary(二进制),d for decimal(十进制),x for hexadecimal(十六进制)。如 %d13 和 %x0D 都代表 CR。
- 用句号(.)相连,表示一串连续的字符,如 %d13.10 代表CRLF(即%d13和%d10相连接),再如 %x44.6f.6d.61.69.6e.3a 1*FWS 代表"Domain: "这一个字符串(注意最后还有一个空格)。
- ...
ABNF的核心规则:
- ALPHA = %x41-5A / %x61-7A ; A-Z / a-z,即 大写和小写 ASCII 字母 (A-Z, a-z)
- BIT = "0" / "1" ; 即二进制字符
- DQUOTE = %x22 ; " (Double Quote),即 双引号
- VCHAR = %x21-7E ; visible (printing) characters,即 可见字符
- CHAR = %x01-7F ; any 7-bit US-ASCII character, excluding NUL,7位
- OCTET = %x00-FF ; 8 bits of data,8位
- CTL = %x00-1F / %x7F ; controls,即 控制字符
- CR = %x0D ; carriage return,即 回车
- LF = %x0A ; linefeed,即 换行
- CRLF = CR LF ; Internet standard newline,即 互联网标准换行
- DIGIT = %x30-39 ; 0-9
- HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F" ;十六进制数字 (0-9, A-F, a-f)
- SP = %x20 ; 即 空行
- HTAB = %x09 ; horizontal tab,即 横向制表符(Tab)
- WSP = SP / HTAB ; white space,即 空格或横向制表符
- LWSP = *(WSP / CRLF WSP) ; 即 直线空白(晚于换行)
【再来几个例子】
(例子3) 下面是JAVA语言中For语句的定义:
FOR_STATEMENT ::= "for" "(" ( variable_declaration | ( expression ";" ) | ";" ) [ expression ] ";" [ expression ] ")" statement
(更多例子) 在BNF/ABNF等RFC中可以看到更多例子。。
【小结】
巴科斯范式真是一个好东西,语法简洁,但表达能力强,且不会产生二义性,难怪很多编程语言,IT规范文档都用它来描述某些定义。
也正是这些计算机行业先驱们创造的这无数规范(无论完善与否,无论实用与否),让现在的IT行业井然有序地服务着每一个人的生活,到处都是异构的系统,但到处都有规范的影子,感谢伟大的规范和创造推广这些规范的人们
!!
【相关RFC】
- BNF http://www.lrz.de/~bernhard/Algol-BNF.html
- ABNF 1 RFC 2234 http://tools.ietf.org/html/rfc2234
- ABNF 2 RFC 4234 http://tools.ietf.org/html/rfc4234
- ABNF 3(最新) RFC 5234 http://tools.ietf.org/html/rfc5234
- MIME RFC 2045 http://tools.ietf.org/html/rfc2045
- HTTP RFC 2616 http://tools.ietf.org/html/rfc2616