【编译原理复习 Part_1】引论、词法分析
编译原理复习_01
第1章 引论
1~3
- 编译器和解释器的区别在于:
- 编译器 - 先生成目标代码再执行
- 解释器 - 不生成目标代码,直接执行。
Extension:
Java语言的处理结合了编译和解释,为什么这样说呢?
(a) Java源程序编译成字节码,因此Java源程序并不是真正的编译
(b) Java源程序可以通过Java虚拟机解释执行。
- 编译器分为前端和后端
中间代码生成以及之前的部分,叫做编译器的前端;
中间代码以后的部分,叫作编译器后端;
Question 1: 下面过程中,属于编译器前端的是:(A)
A. 词法分析 B. 目标代码生成 C. 机器无关代码优化器
- 词法单元分为两个部分,即属性名和值。
Question 2: 在C++代码a = a * 2中,2对应的词法单元是:(D)
A.<id,2>
B.<number,'a'>
C.<id,'a'>
D.<number,2>
4~5
-
词素是词法单元中不包含属性值的部分,即第一部分。
-
在编译原理当中,int变量占4字节,float变量占8字节(和C++不一样的哦~,似乎和Python一样)
第3章 词法分析
6 词法分析器
- 词法分析器的作用:读入字符流,组成词素,输出词法单元序列;过滤空白、换行符、制表符和注释,将词素添加到符号表当中。
Question 3: 在下列代码中,词素属于relop的是:(D)
if (a + b <= 12){
printf("a + b is not past 12");
}
A.a
B.b
C."a+b is not past 12
D.<=
7 正则表达式
- 构建正则表达式
- 并 比如a|b接收的串可以是a也可以是b.
- 连接 比如ab接收的串是前边为a,后边为b的字符串
- Kleene闭包 比如a*接收的串是含有0个或者多个a的字符串
- 正闭包 a+接收的串是含有1个或者多个a的字符串
Question 4: 构建下面描述的正则表达式:
包含5个元音的所有小写字符串,这些串中的元音按照顺序出现。
首先,元音是a, e, i, o, u,我们需要构建的正则表达式应该包含这五个元音,并且它们按照顺序出现。以下是正则表达式的构建步骤:
- 每个元音之间可以有任意数量的非元音字符。
- 所有元音必须按照顺序出现。
考虑到元音之间可以有其他小写字母字符,我们可以用[^aeiou]*来表示这些字符。最后我们组合起来的正则表达式如下:
[^aeiou]*a[^aeiou]*e[^aeiou]*i[^aeiou]*o[^aeiou]*u[^aeiou]*
这段正则表达式匹配所有包含且按顺序出现五个元音的小写字符串。
(第一次词法分析作业就这道题错了,但损失惨重,不知道是为什么..正确率高得离谱>_<)
Question 5: 根据下面的正则表达式描述对应的字符串,假设字母表为{0,1}:
((epsilon|0)1*)*
在这个正则表达式中:
epsilon表示空字符。0是字母表中的一个字符。1*表示零个或多个1。
那么我们先来解析表达式的各个部分:
(epsilon|0)表示可以匹配一个空字符或一个0。1*表示零个或多个1。- 整个部分
((epsilon|0)1*)被星号*包围,表示这部分可以重复零次或多次。
因此,这个正则表达式描述的字符串可以分解为以下几种情况:
- 空字符串,因为
epsilon可以是空字符,并且((epsilon|0)1*)可以整体出现零次。 - 只有
0,因为epsilon可以被替换为0,并且1*可以是零个1。 0后面跟着任意多个1,例如0,01,011,0111,等等。- 由多个前面描述的部分组成的字符串,例如
0,01,011,0111,00,001,0011,00111,等等。
综上所述,正则表达式 ((epsilon|0)1*)* 可以匹配以下类型的字符串:
- 空字符串。
- 由一个或多个部分
(0 followed by zero or more 1s)组成的字符串。
8 正则表达式 -> NFA
- 正则表达式转换为NFA:
- 方法:识别基本操作并一步一步将其识别出来。
Question 6:
将下面的正则表达式翻译为NFA,假设字母表为{a,b}.
a|b*
9 NFA -> DFA
- NFA转换为DFA的方法
- 方法:根据"子集构造法“来构造状态。
-
初始状态
DFA的初始状态是NFA的初始状态的ε闭包。ε闭包是一个状态集,包括初始状态和所有通过ε转换可以到达的状态。 -
处理输入字符
对于DFA的每一个状态(即NFA的状态子集),处理每个输入字符,计算从这些状态出发通过这个字符可以到达的所有状态,再计算这些状态的ε闭包。将这个新的状态子集作为DFA的一个新状态。 -
重复直到没有新的状态产生
重复步骤2,直到没有新的状态子集产生为止。每次产生的新状态子集都要作为DFA的一个状态处理。 -
识别接受状态
如果DFA的某个状态(即NFA的状态子集)包含NFA的一个或多个接受状态,那么这个DFA状态就是接受状态。
-
- 方法:根据"子集构造法“来构造状态。
10 DFA最小化
DFA最小化的方法:
(1)初始划分:按照接受状态和非接受状态划分。Π = {S - F, F}
(2)细分并迭代,直到最终划分结果不变为止(迭代前的Π和迭代后的Π相同)。
细分G,使得G中两个状态s和t在同一个小组中 iff 对符号集合中的所有符号,s和t都到达Π中的同一组;
Π_new = 将Π中的G替换为细分得到的小组。
Question 7: 假设字母表为{a,b},请完成一个构造最简DFA的过程。
描述:识别最后三个字符为a或者最后两个字符为b的字符串。
(1)将描述转换为正则表达式;
(2)将正则表达式转换为NFA;
(3)将NFA转换为DFA;
(4)将DFA转换为最简DFA。

浙公网安备 33010602011771号