编译技术-2024fa-回忆版
编译技术 2024 秋季学期的回忆版真题,来源于计算机速通之家 | QQ 群号:468081841。
🙇♂️🙇♂️🙇♂️时间仓促,有不足之处烦请及时告知。邮箱hez2z@foxmail.com 或者在 速通之家 群里
@9¾。
DFA/NFA/文法/语法树
最简 DFA
$((\varepsilon|a)b^{\ast})^{\ast}$ DFA 化为最简
步骤 1:化简正则式
原式:
$$
R = ((\varepsilon|a)b^{\ast})^{\ast}
$$
先看里面的括号:
- $(\varepsilon|a)$ 表示可以是空串 $\varepsilon$ 或者一个字母 $a$。
- 所以 $((\varepsilon|a)b^{\ast})$ 可以展开为两种情况:
- $(\varepsilon b^{\ast}= b^{\ast})$
- $(a b^{\ast})$
因此:
$$
(\varepsilon|a)b^{\ast} = b^{\ast} \mid a b^{\ast}
$$
于是整个正则式化为:
$$
((\varepsilon|a)b^{\ast})^{\ast} = (b^{\ast} \mid a b^{\ast})^{\ast}
$$
步骤 2:进一步化简
注意:
- 内部子式可以写成并集:$(\varepsilon|a)b^{\ast}= b^{\ast} \cup a b^{\ast}$。其中 $b^{\ast}$ 匹配任意个 b(包含空串),$a b^{\ast}$ 匹配以 a 开头并跟任意个 b 的串。
- 外层的 Kleene 星对这两类块任意重复,因此能够拼出任意由 a 和 b 组成的串(包括空串)。因此可以直接断言:
$$
L® = (b^{\ast} \cup a b^{\ast})^{\ast} = {a,b}^{\ast}
$$
即原正则式能够生成所有由 a 和 b 组成的字符串。
步骤 3:构造最简 DFA
对于语言 ({a,b}^*)(所有由 a 和 b 组成的字符串),DFA 很简单:
- 只需要一个状态 ($q_0$)。
- ($q_0$) 同时是初态和终态。
- 对 a 或 b 的输入仍然回到 ($q_0$)。
形式化表示:
- 状态集:$(Q = {q_0})$
- 字母表:$(\Sigma = {a,b})$
- 初态:$q_0$
- 终态:$(F = {q_0})$
- 转移函数:
$$
\delta(q_0, a) = q_0, \quad \delta(q_0, b) = q_0
$$
步骤 4:验证
- 空串 $\varepsilon$ 可接受,状态在 $q_0$。
- 任意 b 序列,如 bbb,状态始终在 (q_0),接受。
- 任意 a 或 a 和 b 混合序列,如 “abba”,状态始终在 (q_0),接受。
- DFA 只有一个状态,无法再简化。
✅ DFA 最简。
结论:
原正则式
$$
((\varepsilon|a)b^{\ast})^{\ast}
$$
对应的最简 DFA 只有一个状态 $q_0$,初态也是终态,所有 a、b 的输入都回到 $q_0$。
判断二义性
Q: 判断文法 $S \to S*S \mid S+S \mid (S) \mid a$ 是否有二义性
判断二义性举反例就行了,即一个句子有两棵不同的语法树。答案不唯一。
A: 句子 $a + a + a$ 的两棵语法树如下:
graph TD
S1[S] --> S2[S]
S1 --> OP1[+]
S1 --> S3[S]
S2 --> A1[a]
S3 --> S4[S]
S3 --> OP2[+]
S3 --> S5[S]
S4 --> A2[a]
S5 --> A3[a]
graph TD
S1[S] --> S2[S]
S1 --> OP1[+]
S1 --> S3[S]
S2 --> S4[S]
S2 --> OP2[+]
S2 --> S5[S]
S3 --> A3[a]
S4 --> A1[a]
S5 --> A2[a]
语法分析树
画出语句的语法分析树,写出短语,直接短语,句柄
这里分析$(a + a) + a$的短语,直接短语,句柄
短语:
$$
{a, a, a, a + a, (a + a), (a + a) + a}
$$
直接短语:
$$
{a, a , a}
$$
句柄:
$$
a
$$
$LL(1)$ 伪代码
写出文法对应的递归下降分析程序伪代码
$$S \to aAS \mid (A)$$
$$A \to Ab \mid c$$
A:
判断文法是否是$LL(1)$?
左递归、左公因子
若不是,改造文法。构造相关的First集合与FOLLOW集合
构造 $LL(1)$ 分析表
利用分析表给出句子的分析过程
写出文法的递归下降分析器
首先判断该文法是否是 $LL(1)$ 文法:
-
消除左递归
$A \to Ab \mid c$ 存在左递归,改造为:
$$A \to cA’$$
$$A’ \to bA’ \mid \varepsilon$$ -
消除左公因子:文法中没有左公因子。
因此,该文法变成:
$$S \to aAS \mid (A)$$
$$A \to cA’$$
$$A’ \to bA’ \mid \varepsilon$$
接下来,构造各非终结符的 $FIRST$ 和 $FOLLOW$ 集合:
| 非终结符 | FIRST 集合 | FOLLOW 集合 |
|---|---|---|
| S | { a, ( } | { $ } |
| A | { c } | { a, (, ) } |
| A’ | { b, ε } | { a, (, ) } |
注意:在产生式 $S \to a A S$ 中,符号 $A$ 后面跟随的是非终结符 $S$,因此 $FOLLOW(A)$ 包含 $FIRST(S) \setminus {\varepsilon} = {a,(}$。另外在 $S\to(A)$ 中,右括号 $‘)’$ 也是 $FOLLOW(A)$ 的一部分。
然后,构造 $LL(1)$ 分析表(仅列出非空项):
| a | ( | c | b | ) | $ | |
|---|---|---|---|---|---|---|
| S | S → a A S | S → ( A ) | ||||
| A | A → c A’ | |||||
| A’ | A’ → ε | A’ → ε | A’ → b A’ | A’ → ε |
这个题没有给出具体输入串,所以跳过逐步分析过程。
下面是该文法的递归下降分析器伪代码:
1 | void S() { |
1 | void S() { |
伪代码的形式好像有 advance() 和 match() 两种。都是对的应该。
$LL(1)$ 分析
$$<语句> \to <类型> <变量表>;$$
$$<类型> \to int \mid float \mid char$$
$$<变量表> \to ID,<变量表> \mid ID$$
注:$ID$ 为终结符
- 改造为 $LL(1)$ 文法
- 写出各非终结符的 $FIRST$、$FOLLOW$ 集
- 画出 $LL(1)$ 分析表
- 写出语句 $char\ x, y, z;$ 分析过程
A:
设 $<语句>$ 为 $S$,$<类型>$ 为 $T$,$<变量表>$ 为 $V$
则文法为:
$S \to TV;$
$T \to int \mid float \mid char$
$V \to ID,V \mid ID$
首先判断该文法是否是 $LL(1)$ 文法:
$V \to ID,V \mid ID$ 存在左公因子,改造为:
$V \to ID V’$
$V’ \to , V \mid \varepsilon$
因此,改造后的文法为:
$S \to TV;$
$T \to int \mid float \mid char$
$V \to ID V’$
$V’ \to , V \mid \varepsilon$
接下来,构造各非终结符的 $FIRST$ 和 $FOLLOW$ 集合:
| 非终结符 | FIRST 集合 | FOLLOW 集合 |
|---|---|---|
| S | { int, float, char } | { $ } |
| T | { int, float, char } | { ID } |
| V | { ID } | { ; } |
| V’ | { ‘,’, ε } | { ; } |
然后,构造 $LL(1)$ 分析表:
| int | float | char | ID | , | ; | $ | |
|---|---|---|---|---|---|---|---|
| S | S → TV; | S → TV; | S → TV; | ||||
| T | T → int | T → float | T → char | ||||
| V | V → ID V’ | ||||||
| V’ | V’ → , V | V’ → ε |
最后分析一下语句 char x, y, z; 的分析过程:
| 步骤 | 栈 | 输入 | 动作 |
|---|---|---|---|
| 1 | # S | char ID , ID , ID ; # | S → T V ; |
| 2 | # ; V T | char ID , ID , ID ; # | T → char |
| 3 | # ; V char | char ID , ID , ID ; # | 匹配 char |
| 4 | # ; V | ID , ID , ID ; # | V → ID V’ |
| 5 | # V’ ID ; | ID , ID , ID ; # | 匹配 ID(x) |
| 6 | # V’ ; | , ID , ID ; # | V’ → , V |
| 7 | # V , ; | , ID , ID ; # | 匹配 , |
| 8 | # V ; | ID , ID ; # | V → ID V’ |
| 9 | # V’ ID ; | ID , ID ; # | 匹配 ID |
| 10 | # V’ ; | , ID ; # | V’ → , V |
| 11 | # V , ; | , ID ; # | 匹配 , |
| 12 | # V ; | ID ; # | V → ID V’ |
| 13 | # V’ ID ; | ID ; # | 匹配 ID |
| 14 | # V’ ; | ; # | V’ → ε |
| 15 | # ; | ; # | 匹配 ; |
| 16 | # | # | 接受 |
分析成功!
判断文法,构造分析表,分析输入串
已知文法为: $A \to aAd \mid a \mid b \mid \varepsilon$
- 判断该文法是否是 $LR(0)$ 文法,是否是 $SLR(1)$ 文法
- 若是 $SLR(1)$ 文法,构造相应分析表
- 对输入串 $ab$# 给出分析过程
A:
- 构造文法的 $LR(0)$ 项目集规范族
- 构造识别活前缀的DFA
- 这个文法哪类 $LR$ 文法并说明理由
太多了,压榨 AI 也没法写了,直接看视频吧。
四元式
写出程序的四元式序列
1 | while(a > 0 && b > 0) { |
详细解析
由于题目中两个赋值语句的具体内容没有给出,我们假设为典型的赋值语句:a = b + c 和 x = y * z。实际题目中可能有具体赋值语句。
四元式生成过程
-
while循环的条件处理:
a > 0 && b > 0需要分解为两个条件- 先计算
a > 0,再计算b > 0,最后做逻辑与
-
控制流标签:
L1: while循环开始标签L2: 循环体开始标签L3: if条件为真时跳转标签L4: if语句结束标签L5: while循环结束标签
四元式序列
| 序号 | 四元式 | 注释 |
|---|---|---|
| 1 | (j, , , L1) | 跳转到循环开始 |
| 2 | (>, a, 0, t1) | t1 = a > 0 |
| 3 | (jfalse, t1, , L5) | 如果 t1 为假,跳出循环 |
| 4 | (>, b, 0, t2) | t2 = b > 0 |
| 5 | (jfalse, t2, , L5) | 如果 t2 为假,跳出循环 |
| 6 | (>, x, y, t3) | t3 = x > y |
| 7 | (jfalse, t3, , L4) | 如果 t3 为假,跳转到else |
| 8 | (+, b, c, t4) | t4 = b + c (第一个赋值) |
| 9 | (=, t4, , a) | a = t4 |
| 10 | (*, y, z, t5) | t5 = y * z (第二个赋值) |
| 11 | (=, t5, , x) | x = t5 |
| 12 | (j, , , L1) | 跳转回循环开始 |
| 13 | (label, , , L4) | else分支开始标签 |
| 14 | (j, , , L1) | else为空,直接跳回循环 |
| 15 | (label, , , L5) | 循环结束标签 |
说明
-
条件短路:
&&操作符具有短路特性,如果第一个条件a > 0为假,直接跳出循环 -
逻辑与:通过两个连续的条件判断实现
&& -
控制流:使用
jfalse和j四元式实现条件跳转和无条件跳转 -
临时变量:使用
t1, t2, t3, t4, t5存储中间结果 -
标签:使用标签实现循环和分支的跳转目标
设计文法
-
${a^i b^j | i \geq 0, j \geq 0, i+j \geq 2}$
-
${(a,b)^* | a的数量比b的数量多1}$
文法一
设有文法:
$S \to AA \mid BB \mid AB$
$A \to aA \mid a \mid \varepsilon$
$B \to bB \mid b \mid \varepsilon$
文法二
$S \to EaE$
$E \to EE \mid aEb \mid bEa \mid \varepsilon$
求语法指导翻译方案和语法定义
题目有给例子 $abaabaaba$
$S \to aAbA$
$A \to aSb$
$A \to bSa$
$A \to a$
-
输出每个 $b$ 的位置 样例输出 (2 5 8)
-
输出 $a$ 的数量 样例输出 (6)
救命,这是什么