编译原理完整学习笔记(三):词法分析
前言
如果你对这篇文章可感兴趣,可以点击「【访客必读 - 指引页】一文囊括主页内所有高质量博客」,查看完整博客分类与对应链接。
文章目录
- 前言
- 词法分析
- 一、状态转换图
- 1.1 词法分析器概述
- 1.1.1 功能
- 1.1.2 输出
- 1.1.3 词法分析器结构
- 1.1.4 编译器中地位
- 1.2 状态转换图
- 1.2.1 基础定义
- 1.2.2 设计示例
- 1.2.3 状态图一般化代码
- 二、词法规则的形式化
- 2.1 正规式与正规集
- 2.1.1 定义
- 2.1.2 正规式的等价性
- 2.1.3 正规式的性质
- 2.2 DFA
- 2.2.1 定义
- 2.2.2 举例
- 2.2.3 DFA 程序实现
- 2.3 NFA
- 2.3.1 定义
- 2.3.2 DFA 与 NFA
- 三、有限自动机的等价性
- 3.1 NFA 改造
- 3.2 NFA 转换
- 3.2.1 $\varepsilon $-闭包
- 3.2.2 IaI_aIa
- 3.2.3 子集构造
- 3.3 DFA 化简
- 3.3.1 状态等价性
- 3.3.2 化简算法
- 3.3.3 示例
- 四、正规式与有限自动机的等价性
- 4.1 NFA 构造正规式
- 4.2 为正规式构造NFA
- 4.2.1 归纳法证明
- 4.2.2 示例
- 五、词法分析完整流程
词法分析
一、状态转换图
1.1 词法分析器概述
1.1.1 功能
- 功能
- 输入源程序、输出单词符号
- 单词符号种类
- 基本字:如begin、repeat、for、…
- 标识符:用来表示各种名字,如变量名、数组名和过程名
- 常数:各种类型的常数
- 运算符:+、-、*、/、…
- 界符:逗号、分号、括号和空白
1.1.2 输出
- 输出的单词符号的表示形式
- (单词种类编号,单词自身值)
- 单词种别通常用整数编码表示
- 基本字、运算符和界符都是一符一种
- 如果一个种别有多个单词符号,则对于每个单词符号,给出种别编码和自身的值
「举例 - if (5 = m) goto 100
」
if (34, -)
( (2, -)
整常数 (20, '5' 的二进制)
= (6, -)
标识符 (26, 'm')
) (16, -)
goto (30, -)
标号 (19, '100' 的二进制)
1.1.3 词法分析器结构
词法分析器的处理流程
扫描缓冲区结构
- 两个半区互补使用,且单词最大长度不能超过半区长度
- 两个半区互补使用,且单词最大长度不能超过半区长度
超前搜索:识别单词符号
需要的情况
不需要的情况
1.1.4 编译器中地位
- 词法分析器在编译器中地位
1.2 状态转换图
1.2.1 基础定义
结点、箭弧、状态
如果终结状态上有*,则表示识别之后需要退还一个识别的字符
α\alphaα 被识别
1.2.2 设计示例
「示例」
「转换图 => 代码」
「代码实现」
int code, value;
strToken := ""; /* 置 strToken 为空串*/
GetChar(); GetBC();
if (IsLetter())
beginwhile (IsLetter() or IsDigit())beginConcat(); /* 把ch中的字符连接到 strToken */GetChar();endRetract(); /* 子程序,把搜索指针回调一个字符位置 */code := Reserve();if (code = 0)beginvalue := InsertId(strToken);return ($ID, value);endelsereturn (code, -);
end
else if (IsDigit())
beginwhile(IsDigit())beginConcat(); GetChar();endRetract();value := InsertConst(strToken);return ($INT, value);
end
else if (ch = '=') return ($ASSIGN, -);
else if (ch = '+') return ($PLUS, -);
else if (ch = '*)
beginGetChar();if (ch = '*') return ($POWER, -);Retract(); return ($STAR, -);
end
else if (ch = ',') return ($COMMA, -);
else if (ch = '(') return ($LPAR, -);
else if (ch = ')') return ($RPAR, -);
else ProcError(); /* 错误处理 */
1.2.3 状态图一般化代码
- 变量 curState 保存现有的状态
- 用二维数组表示状态图,stateTrans[state][ch]
curState = 初态
GetChar();
while(stateTrans[curState][ch] 有定义) {// 存在后继状态,读入、拼接Concat();// 转换入下一状态,读入下一字符curState = stateTrans[curState][ch];if curState 是终态 then 返回 strToken 中的单词GetChar();
}
二、词法规则的形式化
2.1 正规式与正规集
2.1.1 定义
- 二者关系
- 正规集可以用正规式表示
- 正规式是表示正规集的一种方法
- 一个字集合是正规集当且仅当它能用正规式表示
- 递归定义
- ε\varepsilonε 和 ∅\emptyset∅ 都是 ∑\sum∑ 上的正规式,它们所表示的正规集为{$\varepsilon $} 和 ∅\emptyset∅
- 其中{$\varepsilon $}表示集合里有一个元素,即空字。长度为0,不包含任何字符。
- $\varepsilon $ 是字、正规式
- $\emptyset $ 是集合、正规式
- 任何 $a\in \sum ,a是,a是,a是\sum $上的正规式,它所表示的正规集为{a}
- a 是字符、字、正规式
- ε\varepsilonε 和 ∅\emptyset∅ 都是 ∑\sum∑ 上的正规式,它们所表示的正规集为{$\varepsilon $} 和 ∅\emptyset∅
2.1.2 正规式的等价性
2.1.3 正规式的性质
2.2 DFA
2.2.1 定义
确定有限自动机 M(DFA - Deterministic Finite Automata)
- M 是一个五元式,M = (S, $\sum $, f, S0S_0S0, F)
2.2.2 举例
DFA 构建
字被 M 所识别,即存在一条从初态到终态的道路
- DFA M 所识别的字的全体记为 L(M)
- DFA M 所识别的字的全体记为 L(M)
2.2.3 DFA 程序实现
DFA 可以使用状态转换图的一般代码来进行程序实现。
curState = 初态
GetChar();
while(stateTrans[curState][ch] 有定义) {// 存在后继状态,读入、拼接Concat();// 转换入下一状态,读入下一字符curState = stateTrans[curState][ch];if curState 是终态 then 返回 strToken 中的单词GetChar();
}
2.3 NFA
2.3.1 定义
非确定有限自动机 M(NFA - Nondeterministic Finite Automata)
- M 是一个五元式,M = (S, ∑\sum∑, f, S0S_0S0, F)
- 与 DFA 的最大区别在于三点
- 初态可以有多个
- 转移边上可以是正规式,而 DFA 上是字符
- 对于一个节点来说,一个正规式可以映射多个节点
- 与 DFA 的最大区别在于三点
DFA 与 NFA 举例
a 被 NFA M 所识别
2.3.2 DFA 与 NFA
DFA、NFA 等价理论
- DFA 与 NFA 识别能力相同
- DFA 与 NFA 识别能力相同
DFA 与 NFA 优点
- DFA:易于程序实现
- NFA:设计更容易,易于人工设计
三、有限自动机的等价性
证明 DFA 与 NFA 等价,其证明过程其实就是算法构造过程。通过构造将 NFA 转化为 DFA,并且其能识别的字的全体 L(M) 一致,因此二者等价。
3.1 NFA 改造
初始 NFA
引入初态结点 X 和终态结点 Y
- 解决初始状态唯一性
- 解决初始状态唯一性
简化弧上的标记
3.2 NFA 转换
3.2.1 $\varepsilon $-闭包
- 对于 I 来说,其 ε\varepsilonε 闭包就是往 I 中加入经过任意条 ε\varepsilonε 弧可以到达的状态
3.2.2 IaI_aIa
- Ia=ε−closure(J)I_a=\varepsilon-closure(J)Ia=ε−closure(J)
- J 为 I 中节点出发经过一条 a 弧而到达的状态集合
3.2.3 子集构造
初始状态为初始节点X的ε\varepsilonε闭包
生成新的 DFA
- 包含初态的状态集合为 DFA 初态
- 包含终态的状态集合为 DFA 终态
3.3 DFA 化简
3.3.1 状态等价性
状态等价性
化简思想
3.3.2 化简算法
首先,将 S 划分为终态与非终态两个子集
- 原因是终态可以识别空字,而非终态不可以
其次,对于每个子集检查能不能进一步划分
重复第二步,直至子集数不再增长
最后,若 I 含有原来的初态,则为新的初态;若含有原来的终态,则为新的终态。
3.3.3 示例
化简算法
生成化简后的 DFA
四、正规式与有限自动机的等价性
一个正规式与一个有限自动机 M 等价,即 L® = L(M)。
4.1 NFA 构造正规式
证明:对∑\sum∑上任一个NFA M,都存在一个 $\sum $ 上的正规式 r,使得 L(r)=L(M)L(r)=L(M)L(r)=L(M)。
添加初态与终态
反复应用下述三条规则,消去结点
举例
4.2 为正规式构造NFA
- 定理
- 对于任何正规式 r,都存在一个 FA M,使得 L(M) = L®。
- 对于任何正规式 r,都存在一个 FA M,使得 L(M) = L®。
4.2.1 归纳法证明
归纳法证明
归纳法第一步
归纳法第二步
4.2.2 示例
五、词法分析完整流程
- 根据单词符号确定正规集
- 根据正规集确定正规式
- 根据正规式确定 NFA
- 将 NFA 转换为 DFA
- 化简 DFA
- 基于 DFA 进行程序实现
编译原理完整学习笔记(三):词法分析相关推荐
- 【编译原理】学习笔记1 词法分析
进行词法分析,打印分析结果. 编译器是一个程序:输入字符串,输出目标代码. 词法分析: 读入源码字节,将其组成有意义的TOKEN流. 语法分析: 根据TOKEN流构建树形的中间表示. 语义分析: 检查 ...
- HTML4基本编译原理,Stanford公开课《编译原理》学习笔记(1~4课)
课程里涉及到的内容讲的还是很清楚的,但个别地方有点脱节,任何看不懂卡住的地方,请自行查阅经典著作<Compilers--priciples, Techniques and Tools>(也 ...
- 【编译原理】学习笔记以及课程设计
编译原理 教材用的是<编译原理>(第三版)陈火旺著,电子版戳这里密码:x4ut 课后习题答案戳这里密码:nkv9 教学PPT戳这里密码:0tfz PPT习题答案戳这里密码:v9ct (侵删 ...
- Stanford公开课《编译原理》学习笔记(1~4课)
[摘要] 编译原理基础 示例代码托管在:http://www.github.com/dashnowords/blogs B站地址:[编译原理] Stanford公开课:[Stanford大学公开课官网 ...
- Stanford公开课《编译原理》学习笔记(2)递归下降法
[摘要] javascript实现递归下降语法解析 示例代码托管在:http://www.github.com/dashnowords/blogs B站地址:[编译原理] Stanford公开课:[S ...
- 《编译原理》学习笔记 ·002【第二章:文法和语言(形式语言理论)-1】
注:前言.目录见 https://blog.csdn.net/qq_44220418/article/details/108428971 文章目录 零.引言 一.符号串与符号串集合 1.字母表 2.符 ...
- 《编译原理》学习笔记 ·003【第二章:文法和语言(形式语言理论)-2】
注:前言.目录见 https://blog.csdn.net/qq_44220418/article/details/108428971 文章目录 三.文法和语言的分类 1.Chomsky语言分类法 ...
- 《编译原理》学习笔记 ·001【第一章:总论】
注:前言.目录见 https://blog.csdn.net/qq_44220418/article/details/108428971 文章目录 一.编译程序 1.编译程序 2.编译基础设施 3.编 ...
- 【编译原理】编译原理系统学习与实践系列文章汇总目录(持续更新中)
本文属于「编译原理」系列文章的汇总目录,这一系列正式开始于2021/10/22,着重于「编译原理的学习与实践」.众所周知,编译原理难学难精,因此本系列将至少持续到作者本人「精通编译原理」为止(笑).由 ...
- 【一文弄懂】张正友标定法-完整学习笔记-从原理到实战
张正友标定法-完整学习笔记-从原理到实战 文章目录 张正友标定法-完整学习笔记-从原理到实战 (零)前言: 1 为什么需要标定? 2 相机标定的已知条件和待求解是什么? 标定前的已知条件: 待求信息: ...
最新文章
- 模块修改-column_left.php
- Kali Linux GRUB修复
- 牛客 - 合约数(树上启发式合并)
- 每日一算法 ---- 打印九九乘法表
- About “PostMessage” SendMessage
- c语言编译生成cpp,C语言的编译过程
- Mysql数据库的几大优势
- javascript中内置对象简介、Array
- Linux远程拷贝scp命令
- 计算机电路板工作原理,PCB电路板测试仪的组成及测试原理.
- 更换用户目录后conda环境配置
- javaSE(java基础库)私人学习笔记
- 图解项目管理详细流程全景图
- Win7 环境下 IE8 升级到 IE11 后 F12 工具无法使用
- Qt5-将手机上B站下载的视频提取到到电脑上并批量移动到指定文件夹和重命名
- 标量、矩阵对向量求导
- 《黑白团团队》第九次团队作业:Beta冲刺第三天
- 地图坐标系统(各种坐标系详解)
- 【Java】多人协同在线编辑Excel源代码及部署包
- 阿里云 apt软件云。ubuntu16 17适用
热门文章
- 运营商管道的精细化运营之路
- GCC编译器使用简介
- 使用 Design Pattern Toolkit 进行模型驱动的开发入门
- linux tab 缩进,codemirror TAB 缩进问题记录
- ThinkPHP实现文章上一篇和下一篇
- web server linux,GitHub - markparticle/WebServer: C++ Linux WebServer服务器
- python批量录入学生信息_基于Python的学生信息管理系统
- syslog日志转换器_图解将windows日志转成syslog格式并发送
- 闹钟流程_国际航班流程全攻略(中转+不同航空公司+中转换机场+航班变动)
- java流作为参数,java-8 – 将Java 8流映射函数作为参数传递