《编译原理》第三章:词法分析(笔记二)

3.1 词法分析简介

  1. 编译器可以拆分成为两个“盒子”,一个前端,一个后端
    在这里插入图片描述
    前端又可以拆分成为三个盒子,分别是词法分析器语法分析器语义分析器
    在这里插入图片描述
  2. 词法分析器的任务:字符流到记号流
    (1)字符流:和被编译的语言密切相关(ASCII, Unicode, or …)。
    (2)记号流:编译器内部定义的数据结构,编码所识别出的词法单元。
    在这里插入图片描述
  3. 例子:如图所示,把输入的C语言字符流转化成为特定的记号流
    在这里插入图片描述
    记号的数据结构定义(也可以采用其他的数据结构)
    在这里插入图片描述

3.2 词法分析器的手工构造

  1. 词法分析器的实现方法
    (1)手工编码实现法 :相对复杂、且容易出错。但是是目前非常流行的实现方法,如GCC, LLVM, …
    (2)词法分析器的生成器:可快速原型、代码量较少,但较难控制细节
  2. 转移图
    最开始输入时,我们先判断输入的是>,<还是=,如果是<则继续判断下一个输入是=,>还是其他符号,根据判断返回最终结果。
    在这里插入图片描述
    C语言代码实现:rollback()表示回滚到上一个状态
    在这里插入图片描述
    扩展内容:
#include<stdio>  //头文件
fseek(FILE *stream,long offset,int fromwhere)
/*
功能:重新定位流上的文件指针。
具体:函数设置文件指针stream的位置,如果执行成功stream会指向以fromwhere为基准,
      偏移offset个字节的位置(offset可负),如果失败则不改变stram指向的位置。
返回值:成功返回0,失败返回其他值
获取文件位置:
(1)SEEK_SET:文件开头
(2)SEEK_CUR:当前位置
(3)SEEK_END:文件结尾
*/
//例子:
FILE *fp;
fp=fopen(filename,"rb+");
fseek(fp,100L,SEEK_SET);  //把fp指针移到离文件开头100字节处
fseek(fp,-1L*sizeof(S),SEEK_END);  //offset为负数
  1. 标识符的转移图
    在这里插入图片描述
  2. 关键字
    (1)从词法分析的角度看,关键字是标识符的一部分
    (2)以C语言为例:
标识符关键字
以字母或下划线开头,后跟零个或多个字母,下划线,或数字if,while,else

(3)识别方法:切分转移图关键字表算法
(4)切分转移图(以if为例子):
在这里插入图片描述
(5)关键字表算法
对给定语言中所有的关键字,构造关键字构成的哈希表H
对所有的标识符和关键字,先统一按标识符的转移图进行识别
识别完成后,进一步查表H看是否是关键字
通过合理的构造哈希表H(完美哈希),可以O(1)时间完成
在这里插入图片描述

3.3 正则表达式

  1. 手工 VS. 自动生成
    在这里插入图片描述
  2. 正则表达式
    (1)定义
    在这里插入图片描述
    (2)例子
    在这里插入图片描述在这里插入图片描述
  3. 语法糖
    在这里插入图片描述

3.4 有限状态自动机

  1. 有限状态自动机(FA)
    在这里插入图片描述
  2. 自动机例子
    (1)确定状态有限自动机DFA:对任意的字符,最多有一个状态可以转移。
    在这里插入图片描述
    (2)非确定的有限状态自动机NFA:对任意的字符,有多于一个状态可以转移。
    在这里插入图片描述

3.5 正则表达式转NFA

  1. DFA因为状态转移唯一,所以可以通过如图所示列表的方式进行实现。
    在这里插入图片描述
    NFA情况复杂,所以实现会复杂一些。需要把NFA转化成为DFA再进行词法分析
    在这里插入图片描述
  2. Thompson算法
    在这里插入图片描述
    例子:a (b | c)*
    在这里插入图片描述

3.6 NFA转DFA

  1. 算法思想消除非确定性——找出一个字符可能转移到的所有状态,将这些状态的集合做为一个状态。(读入这个字符去往的状态肯定属于该集合)
    在这里插入图片描述
  2. 例子
    在这里插入图片描述
    在这里插入图片描述
  3. 子集构造算法伪代码
    (1)NFA=(∑, S, q0, F, D),DFA=(∑, S*, q0*, F*, D*)
    在这里插入图片描述
    (2)算法不可能无限运行下去,因为该算法的时间复杂度在最坏的情况下为O(2^N),而最坏情况基本不会出现,因为并不是每个子集都出现。
  4. ε-闭包的计算的伪代码(深度优先)
    在这里插入图片描述

3.7 DFA的最小化

  1. 状态压缩合并
    在这里插入图片描述
  2. 伪代码
    (1)将状态最开始分为两类N和A,A为终止状态。
    在这里插入图片描述

3.8 DFA的代码表示

  1. DFA是一个有向图,其代码表示可为转移表,跳转表,哈希表等,选择哪一种表示方式取决于在实际现实中对时间空间的权衡。
  2. 转移表
    在这里插入图片描述
    (1)最短匹配驱动代码:如果识别的是if,则在读取字符串ifif时,读取到第一个if时直接返回。
    在这里插入图片描述

(2)最长匹配驱动代码:最后返回ifif。
在这里插入图片描述
3. 跳转表
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

焦妮敲代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值