增强 Backus–Naur 范式

来自GSXAB的知识库
(重定向自RFC 4234
增强巴科斯–诺尔范式
术语名称 增强巴科斯–诺尔范式
英语名称 augmented Backus–Naur form
别名 ABNF, 增强巴克斯–瑙尔范式, 扩展BNF, augmented BNF

增强巴科斯诺尔范式(augmented Backus–Naur form)或增强 BNF ,缩写为 ABNF ,指为上下文无关文法设计的形式元语言语法 BNF 的扩展。 ABNF 是 RFC 文档中最长使用的语法表述方式,并且作为 RFC 5234 被列在 RFC 文档中,且有 RFC 7405 作为补充。

由于 ABNF 去除了繁杂的尖括号并补充了一些常用表示,比起 BNF 更加好读。 ABNF 修改了原来 BNF 中的多数符号,更加适用于其设计目的,即表示双向通信协议中使用的语言规范。 但这些符号上的修改也使得 ABNF 的格式偏离了教学上经常使用的 BNF ,且由于与 BNF 相对兼容且经常混入自然语言解释的 EBNF 的存在, ABNF 尽管是 RFC 文档中的标准,却在其他场合很少使用。

形式语言定义

定义形式语言的字母表和规则如下:

字母表

ABNF 中用小写字母表示非终结符,用二进制等字面量表示终结符。 但是还有一些常用规则,被使用字面可识别的大写字母表示。 与其他 BNF 中往往只表达句法层次的结构不同,作为描述双向通信协议的语言, ABNF 关注到字节差异,终结符都是字符、字符类型以及特定的字符组合,虽然也使用类似 BNF 中的双引号字面量,但是在 ABNF 中这些字面量不是看作最小的不可分的字符组合,而是看作连续字符表示的另一种简写,而且默认同时按基本拉丁字母对照关系兼容大小写两套字符。

规则

ABNF 定义

本节摘抄自相关的 RFC 文档。

  • RFC 7405: Case-Sensitive String Support in ABNF[1]
  • RFC 5234: Augmented BNF for Syntax Specifications: ABNF[2]
         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       =  case-insensitive-string /
                           case-sensitive-string

         case-insensitive-string =
                           [ "%i" ] quoted-string

         case-sensitive-string =
                           "%s" quoted-string

         quoted-string  =  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

核心 ABNF ,使用大写字母表示,并且有固定含义,可以作为终结符出现在其他规则中。

         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

BNF 定义

<rulelist>     ::= <rule> | <rule> <rulelist>
<rule>         ::= <rulename> <defined-as> <elements> <CRLF>

<defined-as>   ::= <al-one-c-wsp> "=" <al-one-c-wsp> | <al-one-c-wsp> "=/" <al-one-c-wsp>
<elements>     ::= <alternation> <al-one-c-swp>

<any-c-wsp>    ::= ε | <c-wsp> <al-one-c-swp>
<c-swp>        ::= <WSP> | <c-nl> <WSP>
<c-nl>         ::= <comment> | <CRLF>
<comment>      ::= ";" <com-content> <CRLF>
<com-content>  ::= ε | <WSP> <com-content> | <VCHAR> <com-content>

<alternation>  ::= <concatenation> | <concatenation> <any-c-wsp> "/" <any-c-wsp> <alternative>
<concatenation> ::= <repetition> | <repetition> <c-swp> <any-c-swp> <concatenation>  
<repetition>   ::= <opt-repeat> <element>

<opt-repeat>   ::= ε | <repeat>
<repeat>       ::= <number> "*" <number>
                 | <number> "*"
                 | "*" <number>
                 | "*"
                 | <number>

<element>      ::= <rulename>
                 | <group>
                 | <option>
                 | <char-val>
                 | <num-val>
                 | <prose-val>

<group>        ::= "(" <al-one-c-swp> <alternation> <al-one-c-swp> ")"
<option>       ::= "[" <al-one-c-swp> <alternation> <al-one-c-swp> "]"

<char-val>     ::= <case-insensitive-string>
                 | <case-sensitive-string>

<case-insensitive-string> ::= <case-insensitive-prefix> <quoted-string>
<case-insensitive-prefix> ::= "%i" | ε
<case-sensitive-string>   ::= <case-sensitive-prefix> <quoted-string>
<case-sensitive-prefix>   ::= "%s"

<quoted-string> ::= '"' <q-content> '"'
<q-content>    ::= ε | <QCHAR> <q-content>

<num-val>     ::= "%b" <bin-val> | "%d" <dec-val> | "%x" <hex-val>

<bin-val>      ::= <bit-string> | <bit-string> <more-bit-string> | <bit-string> "-" <bit-string>
<more-bit-string> ::= "." <bit-string> | "." <bit-string> <more-bit-string>
<bit-string>   ::= <BIT> | <BIT> <bit-string>

<dec-val>      ::= <dec-string> | <dec-string> <more-dec-string> | <dec-string> "-" <dec-string>
<more-dec-string> ::= "." <dec-string> | "." <dec-string> <more-dec-string>
<dec-string>   ::= <DIGIT> | <DIGIT> <dec-string>

<hex-val>      ::= <hex-string> | <hex-string> <more-hex-string> | <hex-string> "-" <hex-string>
<more-hex-string> ::= "." <hex-string> | "." <hex-string> <more-hex-string-series>
<hex-string>   ::= <HEXDIG> | <HEXDIG> <bit-string>

<prose-val>    ::= "<" <p-content> ">"
<p-content>    ::= ε | <PCHAR> <p-content>

<WSP>          ::= " " | "\t"
<CRLF>         ::= "\r\n"
<BIT>          ::= "0" | "1"
<DIGIT>        ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
<HEXDIG>       ::= <DIGIT> | "A" | "B" | "C" | "D" | "E" | "F"
<VCHAR>        ::= ...
<QCHAR>        ::= ...
<PCHAR>        ::= ...

最后的 VCHAR,QCHAR,PCHAR 指任意可见字符、双引号外的可见字符或空格、右尖括号外的可见字符或空格。 因为标准 BNF 没有字符范围表示,直接表示过于冗长就省略了。

语义

优先级 运算符 举例 说明
空白类终结符 空格 SP 匹配字节流中一个值为空格的字节。
空格 HTAB (水平制表符) 匹配字节流中一个值为水平指标符的字节。
空白字符 WSP 空格或水平制表符 匹配字节流中一个值为空格或水平制表符的字节。
回车换行 CRLF 连续出现的回车符、换行符 匹配连续的 13 和 10 两个数值,也就是一个回车换行。
注释 comment ; comment 任何以分号(;)开始到回车换行位置的空白字符或可见字符。不参与构成规则。
其他核心规则(仅常用例子) 可见字符 VCHAR 一个 ASCII 可见字符,也就是一个 21H7EH 的字符。或者说控制字符再排除空格。
二进制位 BIT 、 十进制位 DIGIT 、 十六进制位 HEXDIG 一个指定的 0~9 或大写的 A~F 中的字符。
数字类字面量终结符 num_val 数字字面量 %b01001010
%d74
%x4A
匹配一个值为 74 的数值( b 为二进制、 d 为十进制、 x 为十六进制),或者说字节流中一个值为字母 J 的字节。
数字字面量范围 %d65-80 匹配一个值在 65 到 80 范围内的数值。
数字串 %d13.10
%x41.62.43
连续匹配一些字节。第一个例子匹配连续的 13 和 10 两个数值,也就是一个回车换行。第一个例子匹配 aBc 三个字节,且大小写敏感。
文本类字面量终结符 num_val 大小写敏感字面字符串 %s"aBc" 匹配字节流中三个连续的值分别为字母 a 、 B 、 c 的字节。
大小写不敏感字面字符串 %i"aBc"
"aBc"
匹配字节流中三个连续的值分别为字母 A 或 a 、 B 或 b 、 C 或 c 的字节。
含运算符的非终结符(优先级升序) 选择 alternative "a" / "b" 表示可以生成左侧的文法符号或生成右侧的文法符号。例子大小写不敏感地匹配一个值为字母 A 或 a 或 B 或 b 的字节。
连接 concatenation "a" "b"
rule1 "a" 多个文法符号中间至少一个空白字符
连续生成左右的文法符号。如第一个例子就相当于 "ab" ,大小写不敏感地匹配两个连续的值分别为字母 A 或 a 、 B 或 b 的字节。第二个例子则是匹配完 rule1 后再匹配一个值为字母 A 或 a 的字节。
重复 repetition 3"a"
1*3"a"
1*"a"
*3"a"
*"a"
这一部分生成括号内的文法符号,且生成时按照指定次数范围中选择一个次数进行重复。指定范围时上下限可省略,省略下限表示最少 0 次,省略上限代表最多不限次,上下限相同时只写一个数字不写星号。例子从上到下表示可以生成 "aaa" (三个 a )、一至三个 a 、一至任意个 a 、零至三个 a 、零至任意个 a 。
可选 option ["a"] "b" 这一部分可以展开生成空串,也可以生成括号内的内容。相当于重复次数 *10*1 。例子可以生成 "b" 或 "ab" 。
分组 group ("a" / "b") "c" 将括号里的作为一个整体,使表达式中括号内的部分优先结合。例子可以生成 "ac" 或 "bc" 。
规则类非终结符 rule 定义为 "=" rule = "a" 表示左侧的非终结符可以替换为右侧。例子表示文法符号 rule 可以生成 "a" 。
增量选择 "=/" rule = "a" / "b"
rule =/ "c"
表示向这个非终结符中添加可以生成的其他选择项。如例子相当于 rule = "a" / "b" / "c" ,只是写成了两个选择后又向其中添加一个的格式。