BNF及其衍生

背景

在查看gRPC教程时,看到教程中为了说明一些头信息的内容,使用了ABNF语法.
于是看看ABNF的定义

巴科斯范式

历史

BNF是John Backus在20世纪90年代提出的用以简洁描述一种编程语言的语言.
是用来描述语法的一种形式体系.
(描述的是某种语言的语法是什么样,描述方法有多种形式,而他们这种形式能够自成一种体系)
基本结构为

1
<non-terminal> ::= <replacement>

::= 表示定义为,其左侧称为非终结符(意味还没有定义完),右侧称为终结符.
具有相同左部的规则可以共用一个左部,各右部之间以|隔开.
注:自然语言存在不同程度的歧义性质,模糊而不确定,无法精确定义一门程序的设计语言.

特点

  • 上下文无关
  • 语法简单
  • 表示明确

因此便于语法分析以及可能用来编译.

语法

1
2
3
4
5
6
7
"..." : 术语符号
::= : 定义为,不过书籍中常用→
<...> : 必选项
[...] : 选项:最多出现一次
{...} : 重复项: 任意次数,包括0次
(...) : 分组
| : 并列选项,只能选一个

双引号中代表固定字符,之外的内容则是关键字.
尖括号包含必选项
方括号包含可选项
大括号包含可重复0到N次的项目

举例

定义java中for语句

1
2
3
4
5
FOR_STATEMENT ::=
"for" "(" ( variable_declaration | ( expression ";" ) | ";" )
[ expression ] ";"
[ expression ] ";"
")" statement

EBNF

简介

Extended BNF.
加入了一些新的语法,但具体加入什么,没有统一标准.
每个作者或程序都定义了自己的稍有不同的EBNF变体.

新增或变化的语法举例

1
2
3
4
5
6
    =   : 定义为
, : 字符串连接,相当于python的+
; : 终止,表示一个定义语句结束了
(*...*) : 注释
?...? : 特殊序列
- : 排除

ABNF

简介

augmented BNF,
更加标准化,利于解析器翻译,但不利于阅读.
基本的语法是

1
规则 = 定义 ; 注释 CR LF

变化语法

  1. 推导规则

    1
    规则 = 定义; 注释

    注释语法也改得像lisp

  2. 字符串连接

    1
    规则1 规则2

    举例

    1
    2
    3
    fu = %x61; a
    bar = %x62; b
    mumble = fu bar fu

    结果mumbel的值是"aba"

  3. 改为 /

  4. 递增的或

    1
    2
    3
    4
    5
    fubar = fu / bar
    fubar =/ foo

    ; 等效于
    fubar = fu / bar / foo
  5. 数值范围

    1
    2
    3
    4
    OCTAL = %d0-7

    ; 相当于
    OCTAL = "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7"
  6. 重复

    1
    2
    2规则 ; 表示规则重复2次
    2*4规则; 表示规则重复2-4次,*左侧默认0,右侧默认正无穷

对比

三者的表达能力是等效的,只是语法上的差异.

  • 定义符,BNF是 ::=,而EBNF和ABNF是 =
  • BNF和EBNF中,并列符号都是 |, 是ABNF中是 /
  • EBNF和ABNF中有了许多快捷语法,到BNF中可能要用多条语句
    BNF更适合教学,EBNF和ABNF常用于解析器解析(但ABNF更适合).

参考

  1. 比较全面
  2. 表述简洁