如何消除文法二义性、如何判断二义文法—编译原理

30 篇文章 16 订阅
26 篇文章 2 订阅

系列文章戳这里👇

  1. 什么是上下文无关文法、最左推导和最右推导
  2. 如何判断二义文法及消除文法二义性
  3. 何时需要消除左递归
  4. 什么是句柄、什么是自上而下、自下而上分析
  5. 什么是LL(1)、LR(0)、LR(1)文法、LR分析表
  6. LR(0)、SLR(1)、LR(1)、LALR(1)文法之间的关系
  7. 编译原理第三章习题
  8. 词法分析、构建DFA、上下文无关文法、LL(1)分析、提取正规式
  9. 证明LL(1)、SLR(1)、LALR(1)文法
  10. 翻译方案、属性栈代码
  11. 【运行时环境】什么是活动记录、 活动记录与汇编代码的关系

如何判断二义文法

给定一个文法 G G G,如果这个文法 G G G的一些句子中存在不止一棵分析树,或者这些句子存在不止一种最左(最右推导), 我们就称该文法为二义性的, G G G也叫二义性文法。

注意:文法二义并不代表语言一定是二义的,只有当产生一个语言的所有文法都是二义时,这个语言才成为二义的。

举个栗子

S → a S b S   ∣   b S a S   ∣   ϵ S→aSbS\ |\ bSaS\ |\ \epsilon SaSbS  bSaS  ϵ
( a ) (a) (a)为句子 a b a b abab abab构造两个不同的最左推导,以此说明该文法是二义的
第一种最左推导:
S → a S b S → a b S a S b S → a b a S b S → a b a b S → a b a b S→aSbS→abSaSbS→abaSbS→ababS→abab SaSbSabSaSbSabaSbSababSabab
第二种最左推导:
S → a S b S → a b S → a b a S b S → a b a b S → a b a b S→aSbS→abS→abaSbS→ababS→abab SaSbSabSabaSbSababSabab
因此该文法是二义的

如何消除文法二义性

举个栗子

有下列描述命题演算公式的二义文法,为它写一个等价的非二义文法
S → S   a n d   S ∣ S   o r   S ∣ n o t   S ∣   p   ∣   q   ∣ ( S ) S→S\ and\ S|S\ or\ S|not\ S|\ p\ |\ q\ |(S) SS and SS or Snot S p  q (S)
由于该文法没有体现算符 a n d 、 o r 、 n o t and、or、not andornot的优先次序和结合规则,因此该文法二义。如 p   a n d   q   o r   p p\ and\ q\ or\ p p and q or p可以分解成两个子表达式,见下图的两棵不同语法树。
在这里插入图片描述
从我的理解来看,消除二义性,无非就是体现出各算符的优先次序,因此我总结如上形式的消除二义方法如下:

  1. 将最低优先级的运算提至第一层产生式
  2. 最后一层上的各层产生式添加 ′ ∣ ′ '|' 单独推导向下一层
  3. 其余按照优先级高低逐层向下写
  4. 使用新的非终结符代替原终结符
  5. 最后一层产生式要能够推回第一层产生式
    则上述二义文法消除二义性如下
    E → E   o r   T   ∣   T T → T   a n d   F   ∣   F F → n o t   F ∣   p   ∣   q   ∣ ( E ) E→E\ or\ T\ | \ T\\ T→T\ and\ F\ |\ F\\ F→not\ F|\ p\ |\ q\ |(E) EE or T  TTT and F  FFnot F p  q (E)
    做一个简要的解释

因为 o r or or的优先级是最低的, n o t not not最高,所以第一层是 o r or or运算的产生式,可以看到最后一层存在 ( E ) (E) (E),括号保证了 o r or or运算的分解是唯一的

以下是书本中的解释
在这里插入图片描述
在这里插入图片描述

再举个栗子

改写二义文法
E → E + E ∣ E ∗ E ∣ ( E ) ∣ − E ∣ i d E→E+E | E*E |(E)| -E | id EE+EEEEEid

优先级从低到高: [ + ] ; [ ∗ ] ; [ ( ) , − , i d ] [+];[*];[( ), -, id] [+][][(),,id]
结合性:
左结合: [ + , ∗ ] [+, *] [+,]
右结合: [ − ] [-] []
无结合: [ i d ] [id] [id]
非终结符与运算:
E : + E:+ E:+ E E E产生式,左递归)
T : ∗ T:* T: T T T产生式,左递归)
F : − , ( ) , i d F:-,( ),id F:,(),id F F F产生式,右递归)
得到:
E → E + T ∣ T T → T ∗ F ∣ F F → ( E ) ∣ − F ∣ i d E → E + T | T\\ T → T * F | F\\ F → (E) | -F | id EE+TTTTFFF(E)Fid

何时要消除二义性

有些类型的分析器,它希望处理的文法是无二义性的,否则它不能唯一确定对某个句子应选择哪棵分析树。出于某些需要也可以构造允许二义文法的分析器,不过这样的文法要附带消除二义性的规则,以便分析器扔掉不希望的分析树,为每个句子只留一棵分析树。
但大多数编程语言都不用无二义的文法,而是采用二义文法,因为一般来讲,二义文法较无二义文法会更加简洁(下面的例子可以让你看到这一点)。定义语言语法的文法有二义性并不可怕,只要有消除二义性的规则就可以了。
并且,LL(1)文法既不是二义性的,也不含左递归,在什么是LL(1)、LR(0)、LR(1)文法有相关介绍。

  • 65
    点赞
  • 245
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
设计和使用无二义性文法是在语言处理领域中非常重要的任务。以下是一些方法和技巧来设计和使用无二义性文法: 1. 上下文无关文法(Context-Free Grammar, CFG):使用上下文无关文法可以避免一些二义性情况。确保产生式规则的左部只有一个非终结符号,右部也只包含终结符号和非终结符号的组合。 2. 限制产生式规则:合理限制产生式规则的形式,避免产生二义性。例如,避免左递归产生式、嵌套产生式等。 3. 明确运算符优先级和结合性:对于涉及运算符的文法,明确定义运算符的优先级和结合性,避免产生二义性。可以使用算符优先文法或者算符结合文法来处理运算符的优先级和结合性。 4. 引入括号或其他限定符:通过引入括号或其他限定符,明确表达式中的结构和优先级,避免二义性。例如,在算符优先文法中,使用括号来明确运算次序。 5. 上下文限制:在语义层面引入上下文限制来消除二义性。通过上下文信息来解析具有二义性的语法结构,确保正确的解析结果。 6. 使用语义动作:在分析过程中,使用语义动作来根据上下文信息解决歧义。语义动作可以在语法分析树的构建过程中进行,根据上下文信息选择正确的语法规则。 这些方法和技巧可以帮助设计和使用无二义性文法,但在某些复杂的语言中,完全消除二义性可能是困难的。因此,在实际应用中,需要综合考虑语言的需求和复杂度,选择合适的方法来处理二义性
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

之墨_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值