不被框架定义,只为内心而创|

【编译原理复习 Part_1】引论、词法分析

编译原理复习_01

第1章 引论

1~3

  1. 编译器和解释器的区别在于:
    1. 编译器 - 先生成目标代码再执行
    2. 解释器 - 不生成目标代码,直接执行。

Extension:
Java语言的处理结合了编译和解释,为什么这样说呢?
(a) Java源程序编译成字节码,因此Java源程序并不是真正的编译
(b) Java源程序可以通过Java虚拟机解释执行。

  1. 编译器分为前端和后端
    中间代码生成以及之前的部分,叫做编译器的前端;
    中间代码以后的部分,叫作编译器后端;

Question 1: 下面过程中,属于编译器前端的是:(A)
A. 词法分析 B. 目标代码生成 C. 机器无关代码优化器

  1. 词法单元分为两个部分,即属性名和值。
    Question 2: 在C++代码a = a * 2中,2对应的词法单元是:(D)
    A. <id,2>
    B. <number,'a'>
    C. <id,'a'>
    D. <number,2>

4~5

  1. 词素是词法单元中不包含属性值的部分,即第一部分。

  2. 在编译原理当中,int变量占4字节,float变量占8字节(和C++不一样的哦~,似乎和Python一样)

第3章 词法分析

6 词法分析器

  1. 词法分析器的作用:读入字符流,组成词素,输出词法单元序列;过滤空白、换行符、制表符和注释,将词素添加到符号表当中。

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 正则表达式

  1. 构建正则表达式
    1. 并 比如a|b接收的串可以是a也可以是b.
    2. 连接 比如ab接收的串是前边为a,后边为b的字符串
    3. Kleene闭包 比如a*接收的串是含有0个或者多个a的字符串
    4. 正闭包 a+接收的串是含有1个或者多个a的字符串

Question 4: 构建下面描述的正则表达式

包含5个元音的所有小写字符串,这些串中的元音按照顺序出现。

首先,元音是a, e, i, o, u,我们需要构建的正则表达式应该包含这五个元音,并且它们按照顺序出现。以下是正则表达式的构建步骤:

  1. 每个元音之间可以有任意数量的非元音字符。
  2. 所有元音必须按照顺序出现。

考虑到元音之间可以有其他小写字母字符,我们可以用[^aeiou]*来表示这些字符。最后我们组合起来的正则表达式如下:

[^aeiou]*a[^aeiou]*e[^aeiou]*i[^aeiou]*o[^aeiou]*u[^aeiou]*

这段正则表达式匹配所有包含且按顺序出现五个元音的小写字符串。
(第一次词法分析作业就这道题错了,但损失惨重,不知道是为什么..正确率高得离谱>_<)

Question 5: 根据下面的正则表达式描述对应的字符串,假设字母表为{0,1}:

((epsilon|0)1*)*

在这个正则表达式中:

  • epsilon 表示空字符。
  • 0 是字母表中的一个字符。
  • 1* 表示零个或多个 1

那么我们先来解析表达式的各个部分:

  1. (epsilon|0) 表示可以匹配一个空字符或一个 0
  2. 1* 表示零个或多个 1
  3. 整个部分 ((epsilon|0)1*) 被星号 * 包围,表示这部分可以重复零次或多次。

因此,这个正则表达式描述的字符串可以分解为以下几种情况:

  1. 空字符串,因为 epsilon 可以是空字符,并且 ((epsilon|0)1*) 可以整体出现零次。
  2. 只有 0,因为 epsilon 可以被替换为 0,并且 1* 可以是零个 1
  3. 0 后面跟着任意多个 1,例如 0, 01, 011, 0111,等等。
  4. 由多个前面描述的部分组成的字符串,例如 0, 01, 011, 0111, 00, 001, 0011, 00111,等等。

综上所述,正则表达式 ((epsilon|0)1*)* 可以匹配以下类型的字符串:

  • 空字符串。
  • 由一个或多个部分 (0 followed by zero or more 1s) 组成的字符串。

8 正则表达式 -> NFA

  1. 正则表达式转换为NFA:
    1. 方法:识别基本操作并一步一步将其识别出来。

Question 6:
将下面的正则表达式翻译为NFA,假设字母表为{a,b}.
a|b*

9 NFA -> DFA

  1. NFA转换为DFA的方法
    1. 方法:根据"子集构造法“来构造状态。
      1. 初始状态
        DFA的初始状态是NFA的初始状态的ε闭包。ε闭包是一个状态集,包括初始状态和所有通过ε转换可以到达的状态。

      2. 处理输入字符
        对于DFA的每一个状态(即NFA的状态子集),处理每个输入字符,计算从这些状态出发通过这个字符可以到达的所有状态,再计算这些状态的ε闭包。将这个新的状态子集作为DFA的一个新状态。

      3. 重复直到没有新的状态产生
        重复步骤2,直到没有新的状态子集产生为止。每次产生的新状态子集都要作为DFA的一个状态处理。

      4. 识别接受状态
        如果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 中国大陆许可协议进行许可。

posted @   Yuzu_OvO(喵露露版)  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起