【编译原理】如何编写BNF?

此篇文章承接上一篇:【编译原理】理解BNF


前言

理解了BNF,就能实现代码解析了吗?还有点早,因为理解了BNF,还要会写BNF。实际上,BNF实现有固定的模式,也有现成的工具,比如可以使用yacc、bison等工具自动化进行。所以把实现先放一放,看一看BNF是怎么写的。


编写BNF

上一篇文章中,我们介绍了如何编写四则运算的BNF,我们需要遵循几个原则:

  • 优先级越高的产生式越接近终端节点;
  • 有左递归要消除左递归。

是否所有的BNF都可以这么来写呢?下面我们尝试对其他语法的BNF进行编写。

如C语言中枚举类型的定义:

enum EnumName
{
	A, B, C
};

枚举类型的定义语法,用语言描述出来是:

以一个enum开头,后面可以跟一个标识符,也可以省略不写。
接着是一个左大括号;
接着是枚举值列表,枚举值列表可以为空,不为空时,枚举值之间用逗号隔开。
枚举值可以只写出标识符名称,也可以给它赋值,如A和A=1都是正确的;
接着是一个右大括号和一个分号。

其BNF可以尝试写出来:

enum_decl=‘enum’ + option_identifier + ‘{’ + value_list + ‘};’
option_identifier=identifier | ‘’
value_list=’’ | value_list + ‘,’ + indentifier | value_list + ‘,’ + indentifier + ‘=’ + Num

写到最后的value_list会发现,不管怎么写都会多出一个逗号。
因为BNF里面的控制命令太少了,想要表达出我们想要表达的规则,我们得求助于EBNF。


EBNF介绍

下面是EBNF的介绍:

EBNF,E即Extended,EBNF即扩展BNF范式。
它最初由尼古拉斯·沃斯开发,最常用的 EBNF 变体由标准,特别是 ISO-14977 所定义。 ——来自维基百科
更详细的介绍可以参考维基百科: 扩展巴科斯范式(可能需要FQ)
ISO-14977标准文档获取方法,参考文章:去哪查阅ISO国际标准?

下图列举了EBNF包含的符号:
EBNF包含的公式符号
可见EBNF中包含了更多的控制命令。相对于BNF来说,它的描述能力更为强大。


重写

我们现在使用EBNF重写上面的枚举声明语法。

enum_decl = 'enum'[id]'{'[id'='num]{','id'='num}'}';

可见上面用一个EBNF语句即描述BNF很多条语句才能描述的内容。
以此类推,可以自己尝试编写。


欢迎专注【编译原理】专栏!

posted @ 2022-05-22 11:22  撬动未来的支点  阅读(196)  评论(0编辑  收藏  举报