2.5.3 文法二义性的消除
(1 )不改变文法中原有的语法规则,仅加进一些语法的非形式规定。
例如,对于上例文法 G [ E ],不改变已有的 4 条规则,仅加进运算符的优先顺序和结合规则,即 * 优先于 + ; + , * 服从左结合。这样,对于文法 G [ E ]中的句子 i * i + i 只有唯一的一棵语法树(见图 2.6 ),从而避免了文法的二义性.
(2 )构造一个等价的无二义性文法,即把排除二义性的规则合并到原有文法中,改写原有的文法。
例如,对于上例文法 G [ E ],将运算符的优先顺序和结合规则( * 优先于 + ; + , * 左结合)加到原有文法中,可构造出无二义性文法 G’ [ E ]如下:
E → E + T | T
T → T * F | F
F → ( E ) | i
则句子 i * i + i 只有唯一一棵语法树,见图 2.8 。
可见,改写后的文法与原文法等价且为无二义性文法。此例告诉我们,对于由二义性文法描述的语言,有时可以找到等价的无二义性文法来描述它。
【例 2.15 】
定义某程序语言条件语句的文法 G 为
S →if b S
| if b S else S
| A (其他语句)
试证明该文法是二义性的,并消除它的二义性。
分析 该文法的句子 if b if b A else A 对应图 2.9 中两棵不同的语法树。
图 2.8 G’ 的句子 i * i + i 的语法树
图 2.9 复合 if 语句的两棵语法树
所以该文法是二义性的。消除文法的二义性可采用下面两种方法。
(1 )不改变已有规则,仅加进一项非形式的语法规定: else 与前面最接近的不带 else 的 if相对应。这样,文法 G 的句子 if b if b A else A 只对应唯一的一棵语法树(见图 2.9 ( a )),由此消除了二义性。
(2 )改写文法 G 为 G’ :
S → S1 | S2
S 1 →if b S1 else S1 | A
S 2 →if b S |if b S1 else S2
这是因为,通过分析得知引起二义性的原因是 if-else 语句的 if 后可以是 if 型,因此改写文法时规定 if 和 else 之间只能是 if-else 语句或其他语句。这样,对改写后的文法,句子 if b if bA
else A 只对应唯一的一棵语法树,如图 2.10 所示。
图 2.10 G’ 的复合 if 语句的语法树
应该指出的是,文法的二义性和语言的二义性是两个不同的概念。通常我们只说文法的二义性,而不说语言的二义性,这是因为可能有两个不同的文法 G 和 G’ ,而且其中一个是二义性的,另一个是无二义性的,但却有L ( G ) = L ( G’ ),即这两个文法所产生的语言是相同的。而将一个语言说成是二义性的,是指对它不存在无二义性的文法,这样的语言称为先天二义性的语言,例如 L = {aibjck |i= j 或 j = k , i , j , k ≥1 }便是这种语言。
人们已经证明,不存在一个算法,它能在有限步骤内确切地判定任给的一个上下文无关文法是否为二义性文法,或它是否产生一个先天二义性的上下文无关语言。