编译原理考试大题分析【太原理工大学】
之前说错了,考试题型没有简答题和填空题,只有十个选择题是 20 分,其余全是大题。大题考点如下:
(1)给出文法,给出目标符号串 or 句型,要求写出它的最右推导 or 规范推导(同一个概念);
(2)根据语法树,求短语、简单短语和句柄;
(3)已知文法,将其改造为 LL(1) 文法(消除左递归);
(4)求文法的 Select 集,并构造 LL(1) 分析表;
(5)对给定符号串进行语法分析;
(6)构造相应文法的状态转换图;
(7)判断状态转换图是否是 DFA;
(8)NFA 转换成 DFA;
(9)给出文法,判断其是否有二义性,是否为正则文法,并解释原因;
(10)写出给定文法的语言通式(找规律);
(11)给出文法,构造其项目集的规范族;
(12)判断文法是 LR(0) 文法还是 SLR(1) 文法,请解释原因;
(13)构造 LR 分析表;
(14)给出语言,构造文法;
(15)根据已知语句,写出其三元式序列。
上面红色标注的内容我觉得是必考,百分之两百的必考,其余内容也有很大概率会考都看看吧,以下例题没有答案,自己随便写的,注释思路我认为已经写得很详细了,有大佬们如果发现错误的地方,辛苦帮忙指出,谢谢!
四、大题
1. 给定文法 G[S]:
S → aA
A → bA l c
(1)请构造该文法的项目集的规范族。
(2)该文法是 LR(0) 文法还是 SLR(1) 文法?为什么?
(3)请构造该文法的 LR 分析表。
项目的概念:
① 右部标有小三角的产生式称为一个项目;
② 若小三角后面是一个终结符,它就被称为移进项目;
③ 若小三角后面是一个非终结符,它就被称为待约项目;
④ 若小三角放在了最后面,则称该项目为归约项目。
第一问,如何构造规范族?抽象理论我不多说,我们直接盯着下面这张表看,表头有状态、项目集、后继符号以及后继状态。
首先第一步在状态栏写个初始状态 S0,项目集就一个,花括号里面写题目给出的初始文法,并在右部的开头写一个小三角形,后继符号就是小三角后面紧挨着的那个符号,此处为 a,后继状态我们给它起一个名字叫 S1,因为这一行的项目集中只有一个项目所以也就只有一个后继符号和一个后继项目,当项目集中有多个项目时,我们需要把每一个项目的后继符号和后继状态都写出来,后继状态就依次跟着叫 S2、S3、S4 等,比如第二行。但是当该后继状态与上面已经写出的某一个后继状态一致时,我们就不需要重新起名了,可以直接用之前的状态名即可。
再看表格第二行这里的状态写什么呢?我们把上一步产生的所有后继状态,都写在该行的状态栏,重复的就不用写了,状态栏不允许有重复的状态。所以第二行我们把 S2 加入状态栏中,项目集中有这么多项目是什么情况呢?我们继续往下看:
注意,这个小三角随着项目的进行是可以向右移动的,每进行一个状态小三角就会向右移动一位,由上面的 S → △aA 移动成 S → a△A,我们先将它写入到项目集中。
这里还有一个规则,当小三角后面的符号(也就是后继符号)为小写字母时,一切保持正常不用管,但是当小三角后面的符号是一个大写字母时,我们就需要把以该大写字母做为开始符号的所有文法都写进当前项目集中,这就是 Why 我们的项目集中会有这么多项目,S → a△A 小三角后面为大写字母 A,所以我们把以 A 开头的所有文法都找出来写进去,根据题目已知 A → △bA 和 A → △c,注意不要丢掉三角形,把这两个项目也写到项目集中。然后就是对应项目各自的后继符号和后继状态,后继状态还按顺序起名字就好。
okey 小三角移动的过程总得有个尽头吧?这个尽头是什么呢?没错就是文法末尾,既然它是末尾,那么肯定得有什么不一样的地方,Yes 后继符号不一样,我们后继符号统一写成这样 # 号加上去掉小三角的项目,来看 S2 状态栏,它的后继符号为 #S → aA。
后面就没什么了,原理相同,就是注意重复的后继状态我们写一个就行,不要重复的状态起两个名字。
第二问,如何判断一个文法是 LR(0) 文法还是 SLR(1) 文法?你就看项目集中是否出现了移进 — 归约 or 归约 — 归约冲突,如果出现了任意一个冲突,那么该文法就是 SLR(1) 文法,没出现就是 LR(0) 文法。抽象定义不讲,我们直接看小三角形,小三角形放在最后叫归约,小三角形后面是小写字母叫移进,也就是说这两种情况同时出现在同一个项目集中时,这就叫发生了冲突,或者一个项目集中同时出现了两个归约项目,这也是发生了冲突。而在本题中,我们并没有发现项目集中有任何的冲突问题,没有发生冲突所以它是 LR(0) 文法。
三小问是基于一小问来做的,表头如下图所示,其中 ACTION 栏填终结符(小写字母)和 # 号,GOTO 栏填非终结符(大写字母)。
首先把题目给出的文法都拆开,并且从 0 开始给每一条文法都标上序号,我们后续会用。
状态栏填入我们第一问写出来的所有状态,除了最终状态 S6 其他都填,ACTION 栏下填什么内容呢?这里填的其实也是项目状态,我拿第一行举个例子就知道了,我们横纵坐标一起看,跟我一起念:S0 通过 a 可以到达什么状态?接下来去看一小问的图,我们只看第一、三、四列,S0 通过后继状态 a 可以到达状态 S1,对咯所以第一行的 a 坐标下,我们直接填入 S1,后面道理一样。还有 GOTO 栏填啥呢,其实跟 ACTION栏的做法一样,只不过 GOTO 这里我们只填状态标号,前面不加 S。
不要忘了,还有一种特殊情况,就是上面说过的终止状态,有 S2、S4 和 S5,它们的后继符号并不是一个简单的字母,对于终止状态我们有特殊的处理方法。特中之特的是 S2,因为 S2 的开始符号是文法的开始符号 S,所以在下表中我们在它的 # 列直接填入规定好的 acc,其余列不填。对于 S4 我们还是去一小问的表中找它所对应的文法为 A → c,然后去我们前面展开的文法里面找它所对应的编号,可以看到为 2,再回到分析表中,把 ACTION栏的所有列都写上 r2,这个 r 是规定好的直接写就可以,此处的下标 2 正是我们的编号 2。S5 与 S4 同理,GOTO 栏不用写。
2. 已知文法 G[A]:
A → aBc
B → Bb|d
(1)消除文法的左递归;
(2)求出文法的 Select 集;
(3)构造 LL(1) 分析表;
(4)对符号串 #adbc# 进行语法分析。
LL(1) 分析表有两种写法,P74、P75 页,导致后面输入串的分析过程也不一样。
对符号串进行语法分析:从左到右以单个字母为单位分析符号串,要分析的符号依次进入分析栈,这里的余留输入符号即剩余的未被分析的符号串,所用产生式一栏填该步骤所用到的产生式,匹配删除这里填已经被分析完要出栈的符号。
首先开始符号 A 先进入分析栈,此时还未对其操作,然后 A → aBc 的右部倒着入栈,即 cBa,所用产生式自然就是 A → aBc,接下来观察余留符号串为 adbc,从左到右分析所以先分析 a,观察上一栏栈也中有 a,分析完毕匹配删除 a,这里的分析栈中仅剩 cB,而余留符号串也变为 dbc,这次要分析的是 d,所以我们将用到产生式 B → dB',同时将 d 入栈,追加到最右边,同样道理,依次分析,直到分析完毕。
3. 已知文法 G[E]。
E → E + T I T
T → T * F I F
F → (E) I i
(1)给出句型 i + i * F 的最右推导;
(2)根据语法树求句型 i + i * F 的短语、简单短语和句柄。
从下到上,从左到右去找。
4. 已知文法 G[Z]:
Z → Aala
A → Abla
(1)构造相应的状态转换图;
(2)判断该状态转换图是否是 DFA,如果是 NFA,将其转换成 DFA 并化简。
画状态转换图首先确定状态,初态 S,终态 Z 以及中间状态 A,初态双箭头,终态双圈,中间箭头连接,箭头上标小写字母。根据已知的文法可知,S 可通过 a 直接到达 Z,也可通过中间状态 A 到达 Z,根据 Z → ab^na 知,A 前后路线上的字母都是 a,中间部分循环未知个 b,也就是 A 通过 b 到达 A。
只要问到状态转换图是否是 DFA,不用多想,一定不是。解释原因就是一个状态通过一个小写字母可以到达多个不同的状态,它是不唯一的,所以应该是 NFA。
NFA 转 DFA,先画表,X 轴方向表头填入小写字母 a 和 b,Y 轴方向先依次填入 S、A、Z 三个状态,用中括号括起来,后面还会增加新的状态,我们先看这三个,表格内容填什么呢?填横坐标通过纵坐标可以到达的状态集,这样说比较抽象,比如看第一空,横坐标是 [S],纵坐标是 a,盯着上面画出来的状态转换图,[S] 可以通过 a 到达 Z 和 A,所以第一空这里我们就填 [A, Z],到达不了的就不填,同理把每一栏都填完之后,我们观察填入的内容,把除了 S、A、Z 这三种状态之外的所有新状态都照搬到下一行的开头,再进行上面的操作即可。
最后一步,画图。根据上面准备好的表格,S 通过 a 到达 AZ,AZ通过 a 到达 Z,AZ 通过 b 到达 A 等等,注意 AZ 和 Z 都是最终状态,所以要画两个圈。
5. 写出下列语句的三元式序列。
for (i = 1; i <= 100; i++)
{
x = i * (b + c);
y = 2 * (x - c);
}
三元式整体上与四元式类似,但三元式只有运算符和两个运算对象,没有临时变量,所以三元式的前面必须都标上序号。
这边补充 BR 表示无条件转的单目后缀运算符,本题中用于无条件跳回判断语句进行判断,BF 表示按条件转的双目后缀运算符,本题用于满足条件继续执行下面内容。记不住怕写错你可以这样记,英语字母表的 F 在 R 前面,所以遇到循环语句,先写 BF 后写 BR。
执行完一次循环语句,i 要加 1 并且给 i 重新赋值,序列最后不要忘记再加上一个空序列,即序列(13)。
序列(3)的操作符为有条件跳转 BF,两个操作数分别为空序列序号和上一步序列的序号。
序列(12)为无条件跳转 BR,因为不管怎么样你都要跳回去判断一下看满不满足条件,操作符为 BR,两个操作数分别为条件判断操作(2)和下划线 __。
对于赋值操作,等号右边的值作为第一操作数,等号左边的值作为第二操作数。
6. 已知文法G[S]:
S → aAbb
A → aAb I c
问:该文法产生的语言是什么?(给出通式)
找规律就好。
7. 已知语言 L(G[Z]) = {cb^nc | n >= 0},构造文法。
这个主要就是多写几次找出规律。
文法 G[Z]:
Z → Ac
A → Ab | c
8. 判断一个文法是否有二义性,是否是正则文法,并说明原因。
是否有二义性?简单来说你就看同一个句子是否能够画出两种不同的语法树,不管是怎么推倒的,也不管这两棵树是对称还是非对称,只要有一点不一样,那它就是二义性文法。说明原因的时候你需要举出两个例子并画出这两颗语法树,去证明该文法有二义性。
是否是正则文法?正则文法要求形式为 A → aB 或 A → Ba 或 A → a,其中 A、B ∈ VN,a ∈ VT。你只需要观察题目已知文法是否满足正则文法条件,不满足要指出哪条文法不满足,解释原因最好把正则文法的规定形式再复述一遍。
更多推荐
所有评论(0)