擴充巴科斯範式

在電腦科學中，擴充巴科斯-瑙爾範式（ABNF）是一種基於巴科斯-瑙爾範式（BNF）的拓展分支。該語言有自己的語法和派生規則。ABNF提供一種用於描述雙向通信協議的語言的形式系統並由 第68號網際網路標準 （"STD 68"，大小寫樣式按照原文）定義——RFC 5234。該語言經常用於網際網路工程任務組（IETF）通信協議的定義語言。

RFC 5234取代RFC 4234、2234、733。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`
```

一個規則可以通過用斜槓（「`/`」）分隔的可供選擇的子規則列表來定義。

要接受規則或規則可構造如下規則:

- `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##-##
- 重複*
- 組合、可選
- 串聯
- 選擇 /

選擇操作符與串聯一起使用會造成混淆，因此建議使用組合來確保串聯組的明確。

例如：

```
`我们 = 你 我/他 她`
```

會產生下面兩種歧義：

- `(<font color='blue'>你 我</font>)/(<font color='seagreen'>他 她</font>)`
- `(<font color='blue'>你</font>) (<font color='seagreen'>我/他</font>) (<font color='red'>她</font>)`

所以，使用組合來確保不會產生歧義：

```
`(你 我)/(他 她)`
```

### 核心規則

核心規則定義於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的警告，如下:

若使用該直線空白規則，將允許存在只包含空白字符的行，而這樣的行在郵件頭中已不再合法，並且已在其他環境中導致了互操作問題。

不要在定義郵件頭時使用它，在其他環境下使用時也要格外注意。