编译原理大复习

发布时间 2023-05-31 22:54:38作者: Appletree24

Todo:代码优化

消除左递归及提取左公因式题型

中南大学徐德智老师PPT内容
一图解决问题。不再赘述

由语言构造文法

虽然有五种方法,但是把卷子做完一遍以后,最有效的应该还是分解法,能用到的两种方法记录一下。

分解法


这个分解法已经写的很清楚了,但是还是拿一个卷子上的例题来记一下:

\[S->a^m(ab)^nb^m(m>=1,n>=0) \]

首先把中间括号拆开,变为am+n以及bm+n,此时将整个产生式分为前后两个部分,分别对其进行进一步拆解,记为A、B
A->a^m+n,这个产生式很好拆解,可以拆解为A->aA|a
同理,B->b^m+n,也按照同样方式拆解,拆解为B->bB|b
最后将二者拼接在一起,形成L即可

对称法


上图说的很清楚了,不再赘述

等价法

image.png
首先不难发现,在语言中,a和b的数量应该一样多,于是乎可以先写一层
image.png
那么按照数量关系,当以a开头时,S中已经有了一个a,此时需要一个b,那么就创建一个非终结符来完成。下面当以b开头时也是如此。
接下来就分析S、A、B各产生式中非终结符的数量关系:
S中,a和b的数量应该相同。A中,b的数量应该比a的数量多一,弥补a开头的差距。B中,a的数量应该比b的数量多一,弥补b开头的差距。
下一步就是根据数量关系,进一步构造产生式:

  • 首先是A产生式,A产生式的职责在上面已经分析完毕了,就是要负责产生b相关的字符串。首先第一个能想到的非常简单,就是不进行递归产生,只弥补一个a开头时数量的差距。也就是只产生一个b。之后就要考虑递归产生问题,和构造S产生式一样,只需要以b开头,然后递归回S就可以了。但是此时A也是可以以a开头的,这样就产生了两个a,根据数量关系,aA构成一个S,此时S中a和b数量相同,只需要考虑把a开头的一个差距弥补,所以最后末尾再补一个A负责产生b即可,最终结果如下图image.png
  • 同理,B的产生式也很好构建,即为aS,a,bBBimage.png

NFA确定及最小化

写几个自己错误过的点,简单记录一下:

  • 首先是转换表第一格,直接求个开始状态的ε闭包。求ε闭包记得要把自身也加进去。image.png
  • 之后就是求第一列相对应的Ia、Ib闭包,步骤为先寻找通过第一列对应ε闭包中某一状态节点出发经过一条弧可以到达的状态节点的全体,注意是一条arc
  • 之后就要进行第二步,求解Ia或Ib闭包的ε闭包,将结果填写至表格中
  • 最终将含有终态的状态集合记为终态,不含有终态的状态集合记为普通状态画图即可
    之后是将DFA最小化的流程:
  • 首先将整个状态按照终态与非终态的标准划分为两部分集合,之后各对两个集合内部进行进一步划分
  • 按照接受某字符到达状态类型是否相同的标准进行进一步划分

逆波兰及三元式

题目一般都很简单,主要重点就是——逆波兰要按计算优先级倒着来,三元式则按计算优先级正着来。

LR(1)文法分析器

其实这想都不用想就知道肯定考LR(1)分析器,因为可以直接把所有的自底向上分析方式全考了。
LR(1)分析是为了解决SLR(1)无法解决的规约/规约冲突类型。有几点需要注意:

  • 首先需要拓展文法,加入新的开始符号
  • 在创建项目集过程中,读取符号如果扫描到了非终结符,就要将该非终结符的所有产生式都加入项目集中