BNF(Backus-Naur Form)是描述编程语言的文法。巴科斯范式是一种用于表示上下文无关文法的语言,上下文无关文法描述了一类形式语言。

自然语言存在不同程度的二义性。这种模糊、不确定的方式无法精确定义一门程序设计语言。必须设计一种准确无误地描述程序设计语言的语法结构,这种严谨、简洁、易读的形式规则描述的语言结构模型称为文法

BNF规定是推导规则(产生式)的集合,写为:

符号 ::= <使用符号的表达式>

这里的 <符号> 是非终结符,而表达式由一个符号序列,或用指示选择的竖杠 '|' 分隔的多个符号序列构成,每个符号序列整体都是左端的符号的一种可能的替代。从未在左端出现的符号叫做终结符。

终结符和非终结符

终结符:终结符是一个形式语言的基本符号。就是说,它们能在一个形式语法的推到规则的输入或输出字符串存在,而且他们不能被分解为更小的单位。确切的说,一个语法的规则不能改变终结符。一个形式语法所推导的形式语言必须完全由终结符组成。

非终结符:非终结符是可以被取代的符号。一个形式文法中必须有一个起始符号,这个起始符号属于非终结符的集合。在上下文无关文法中,每个推到规则的左边只能有一个非终结符而不能有两个以上的非终结符或中介符。(并非所有的语言都可以被上下文无关文法产生)

BNF范式的语法

在BNF中,双引号中的字(“word”)代表着这些字符本身。而double_quote用来代表双引号。

在双引号外的字(有可能有下划线)代表着语法部分。

< >     : 内包含的为必选项。
[ ]     : 内包含的为可选项。
{ }     : 内包含的为可重复0至无数次的项。
|       : 表示在其左右两边任选一项,相当于"OR"的意思。
::=     : 是“被定义为”的意思
"..."   : 术语符号
[...]   : 选项,最多出现一次
{...}   : 重复项,任意次数,包括 0 次
(...)   : 分组
|       : 并列选项,只能选一个

例如,Java语言总的for语句的BNF范式定义如下:

FOR_STATEMENT ::=
    "for" "(" ( variable_declaration |
    ( expression ";" ) | ";" )
    [ expression ] ";"
    [ expression ]
    ")" statement

ABBF

RFC2234 定义了扩展的巴科斯范式(ABNF)。近年来在Internet的定义中 ABNF 被广泛使用。扩充巴科斯-诺尔范式(ABNF)基于了巴科斯-诺尔范式(BNF),但由它自己的语法和推导规则构成。这种元语言的发起原则是描述作为通信协议(双向规范)的语言的形式系统。

ABNF 规定是一组推导规则,写为:

规则 = 定义 ; 注释 CR LF

这里的规则是大小写敏感的非终止符,定义由定义这个规则的符号序列,一个文档注释组成,并结束于回车换行。

规则名字是大小写不敏感的: <rulename>, <Rulename>, <RULENAME><rUlENamE> 都提及同一个规则。规则名字由开始于一个字母的字母、数字和连字符组成。不要求用尖括号(“<”, “>”) (如 BNF 那样)包围规则名字。但是它们可以用来界定规则名字,比如在冗文中识别出规则名字的时候。ABNF 使用 7-位 ASCII 编码,在 8-位域中把高位置零。

终结符由一个或多个数值字符指定。数值字符可以指定为跟随着基数(b = 二进制, d = 十进制, x = 十六进制)的一个百分号“%”,随后是这个数值,或数值的串联(用“.” 来指示)。例如回车可以指定为十进制的 %d13 或十六进制的 %x0D。回车换行可以指定为 %d13.10。

文字正文通过使用包围在引号(“)中字符串来指定。这些字符串是大小写不敏感的,使用的字符集是 US-ASCII。所以字符串“abc”将匹配“abc”, “Abc”, “aBc”, “abC”, “ABc”, “AbC”, “aBC” 和 “ABC”。对于大小写敏感匹配,必须定义明确的字符: 要匹配 “aBc” 定义将是 %d97 %d66 %d99。

EBNF

参考

  1. RFC 4234Augmented BNF for Syntax Specifications: ABNF
  2. 理解巴科斯-诺尔范式 (BNF) 语法