BNF和EBNF

BNF和EBNF

BNF:Backus-Naur Form
描述语言的数学方法,是定义语言的语法,非常精确,没有歧义;

BNF
从一个符号开始,起始标志,给出替换前面符号的规则;
这些规则叫做书写规范,形式如下:
symbol := alternative1 | alternative2 ...
:=左侧的符号必须被右侧某一个可选项代替;
替换项通常有两个符号和终结符构成,终结符代表书写过程终止;
另一种变化,把终止符放在引号中,与符号区分开;
@表示符号可以去掉;

例子:代表分数的语法

S  := '-' FN | FN
FN := DL |  DL '.' DL
DL := D | D DL
D  := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'

EBNF
DL中用到了递归,EBNF引入下面的操作符,解决递归问题

? :一个都不满足,或者更多
* :0或更多
+ :至少一个

EBNF例子:

S := '-'? D+ ('.' D+)?
D := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'

EBNF只是更方便

一般用法
EBNF可以定义语言,这样的语言没有争议,可以利用编译器自动生成;
也可以定义XML,SGML这样的标记语言;

解析

自上而下的解析(LL)
LL解析,对每一段代码找出代码开始的非终端标记(初始集)
从起始符开始,比较不同的代码段,

LL语法通常按数字分类:
比如:LL(1), LL(0)
括号中的数字是在语法中的任何一点选择适当符号时需要同时考虑的最大终端数
LL(0)不需要终止符,意味着语言只有一个字符串,没有意义;
最常见的是LL(1),通过检查输入的第一个终止符,总能够找到替换符;
LL(2)检查两个符号

一个LL分析实例
再看例子

S  := '-' FN | FN
FN := DL |  DL '.' DL
DL := D | D DL
D  := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'

D符号把10个数字组成的集合作为初始集,至少有LL(1)语法,需要一个终端符;
DL两个替换符都以D开头,因此都有相同的初始集,LL(2);

一个LL转换实例
多数非LL(k)语法可以容易地转换成了LL(1)语法;
需要转换两个符号:FN和DL
FN的问题是两个替换项都以DL开头,但是第二个替换项后接一个.和另一个DL
可以把FN变成只有一个DL开头的替换项,后跟一个FP(分数部分),FP可以是空或者.后跟一个DL

FN := DL FP
FP := @ | '.' DL

因为两个替换项有不同的初始集,分别是输入的结尾和.
DL问题出在递归,需要从DL中得到一个D;
给DL一个单独的替换项,一个D后接一个DR(其余的数字);
这时DR就有两个替换项:D和DR或@,第一个替换项以所有数字为初始集,第二个含有.和输入的结尾作为初始集,从而解决问题;

S  := '-' FN | FN
FN := DL FP
FP := @ | '.' DL
DL := D DR
DR := D DR | @
D  := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'

http://www.garshol.priv.no/download/text/bnf.html

posted @ 2016-11-29 20:07  zhangshihai1232  阅读(1538)  评论(0)    收藏  举报