【编译原理复习 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。
本文作者:Yuzu_OvO(喵露露版)
本文链接:https://www.cnblogs.com/yuzusbase/p/18257908
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)