编译原理(课件版)
重点回顾
- 词法分析
- 功能和作用
- 相关概念:字母表、串、语言、……
- 正则表达式及其描述的语言(?)
- 状态转换图
- 有穷自动机:确定性 & 不确定性
- NFA和DFA识别串的模拟
- 正则表达式 & NFA & DFA (等价性)
- DFA状态最小化(?)
- 语法分析
- 功能和作用
- 相关概念:文法(上下文无关文法)、推导、语法树、……
- 文法和语言
- 二义性文法,基于优先级消除二义性,基于语义解释消除二义性
- 左递归及消除,直接左递归,间接左递归(?)
- 自顶向下分析技术
- 递归下降分析框架,分析过程,栈的变化
- 预测分析
- first
- follow
- 预测分析表
- 预测分析流程
- LL(1)文法
- 自底向上分析技术
- 移进-归约的分析框架,分析的过程,栈的变化
- 句柄
- LR分析技术
- 相关概念:项,项集,项集闭包,项集规范族,可行前缀,有效项
- 分析基础:增广文法;语法分析表:ACTION表、GOTO表
- SLR分析表构造
- 规范LR(1)语法分析器
- LR(1)项、LR(1)项集规范族构造、LR(1)语法分析表构造
- LALR分析
- 二义性文法的分析
- 语义分析 & 中间代码生成
- 基于语法制导的翻译技术
- 语法制导定义
- 属性(综合属性、继承属性)
- 语义规则
- 属性求值,分析树注释
- 依赖图
- S属性定义
- L属性定义
- 语法制导定义
- 翻译方案
- 语法制导定义
- 中间代码的形式
- DAG图
- 抽象语法树
- 三地址代码
- 类型声明
- 类型表达式、类型等价
- 类型的声明及局部变量的存储布局
- 各种类型变量声明的存储
- 表达式的翻译
- 数组引用的翻译
- 数组元素的寻址
- 类型检查、类型转换
- 控制流语句的翻译
- 布尔表达式的翻译
- 回填:记录需要回填的位置,在获得目标位置的时候回填
- 过程的翻译
- 基于语法制导的翻译技术
- 运行时刻幻镜
- 存储组织
- 栈式存储分配
- 活动树
- 活动记录:布局
- 过程及调用
- 非局部数据的访问
- 垃圾回收
- 可达性
- 引用计数
- 跟踪回收
- 代码生成
- 目标语言及目标代码指令
- 指令寻址
- 目标代码中的地址
- 静态分配
- 栈分配:跟函数调用和返回相关的代码生成
- 为生成更好的目标代码,对中间代码进行优化
- 基本块和流图
- 基本块的优化
- 代码生成器
- 代码生成算法
- 寄存器分配
- 目标代码的优化
- 机器无关的代码优化
- 优化的机会
- 全局公共子表达式
- 复制传播
- 死代码消除
- 代码移动
- 归纳变量和强度削减
- 数据流分析
- 前向后向
- 传递方程
- 约束方程
- 交汇运算
- 边界条件
- 初始值
- 到达-定值分析
- 活跃变量分析
- 可用表达式分析
- 基于联立方程组的迭代计算
- 流图中循环识别
- 支配树,回边,对应于回边的自然循环结点的集合
- 优化的机会
第一章 引论
编译器 vs 解释器
编译器的机构:分析部分+综合部分
符号表(这究竟是个什么货?)
记录源程序中使用的变量的名字,收集各种属性(如:名字的存储分配、类型、作用域、过程名字的参数数量、参数类型等)
语法树
词法单元流(?)
语义分析
使用语法树和符号表中的信息,检查源程序是否满足语言定义的语义约束
同时收集类型信息,用于代码生成
类型检查,类型转换
步骤 vs 趟(pass)
环境与状态
- 环境:从名字到存储位置的映射
- 状态:从内存位置到它们的值的映射
第三章:词法分析
读入源程序的输入字符,把它们组成词素,生成并输出一个词法单元序列,每个词法单元对应于一个词素
词法单元 & 词素 & 模式
词法结构图(?)
字母表:一个有限的符号集合(典型的字母表包括字母、数位、标点符号)
串:字母表中符号组成的一个有穷序列
语言:给定字母表上一个任意的可数的串的集合
和串有关的术语
- 前缀 & 真前缀
- 后缀 & 真后缀
- 子串 & 真子串
- 子序列:从原串中删除0或多个符号得到的串(可不连续)
串的运算:连接,指数运算(幂运算)
语言的运算:并(属于其一)、连接(同时属于两者)、Kleene闭包(0到无穷)、正闭包(1到无穷)
每个正则表达式r可以描述一个语言L(r),也即其定义的正则集合
正则定义:对正则表达式命名(for simplicity)
正则表达式的运算
- 并
- 连接
- 闭包
- +
- *
- 字符类
状态转换图:可以把RE转换成状态转换图
- 状态:表示了在识别词素的过程中可能出现的情况(?)
- 状态看做是已处理部分的总结
- 某些状态为接受状态或最终状态,表明已经找到词素
- 加上*的接受状态表示最后读入的符号不在词素中
- 开始状态(初始状态):用start边表示
- 边:从一个状态指向另一个状态;边的标号是一个或者多个标号
- 如果当前符号为s,下一个输入符号为a,就沿着从s离开、标号为a的边到达下一个状态
forward指针 回退
有穷自动机:本质上等价于状态转换图;是识别器,对输入串回答yes or no
- 不确定的有穷自动机(NFA)
- 确定的有穷自动机(DFA)
NFA与DFA的异同
- 区别:
- NFA:一个符号标记离开同一状态的多条边
- DFA:对于每个状态和字母表中的每个字符,有且仅有一条离开该状态、以该符合为标号的边
- NFA:可以有边的标号为
- DFA:没有标记为的边
- 相同
- 都可以识别正则语言,两者存在等价性
NFA由以下几个部分组成
- 一个有穷的状态集合
- 一个输入符合集合
- 转换函数:对于每个状态和中的符号,给出相应的后继状态集合
- 一个状态被指定为开始状态/初始状态
- 的一个子集被指定为接受状态
转换表(NFA可表示为一个转换表)
- 表的各行对应于状态
- 各列对应于输入符号和
- 表中的元素表示给定状态在给定输入下的后继状态
自动机对输入字符串的接受
当且仅当对应的转换图中存在一条从开始状态到某个接受状态的路径,使得该路径中各条边上的标号组成符号串x
DFA
如果NFA没有之上的转换动作,且对于每个状态s和每个输入符号a有且仅有一条标号为a的边(只有一条标号为a的出边)
NFA转换成DFA:子集构造法
s表示NFA N中的单个状态,T表示N的一个状态集
action | description |
---|---|
-closure(s) | 能够从NFA的状态s开始,只通过转换到达的NFA状态集合 |
-clsure(T) | 能够从T中的某个NFA状态s开始,只通过转换到达的NFA状态集合,即 |
move(T,a) | 能够从T中某个状态s出发通过标号为a转换到达的NFA状态的集合 |
DFA化简:状态数最小化
原理:将一个DFA的状态集合划分成多个组,每个组中的各状态相互不可区分,然后将每个组中的状态合并为一个状态
最小化算法:划分部分+构造部分
可区分
如果分别从状态s和t出发,沿着标号为x的路径到达的两个状态只有一个是接受状态,称为x区分状态s和t。如果存在能够区分s和t的串,则s和t是可区分的
RE到NFA
输入:字母表上的一个正则表达式
输出:一个接受的NFA N
Lex的例子
delim [ \t\n]
ws {delim}+
letter [a-zA-Z]
digit [0-9]
id {letter}({letter}|{digit})*
number {digit}+(\.{digit}+)?(E[+-]?{digit}+)?
- yylval:存放指向符号表的指针
- yytext:token的lexeme
- yyleng:lexeme的长度
第四章:语法分析
语法分析器
输入:词法分析器输出的词法单元序列
输出:语法树表示
类型:通用型,自顶向下(LL grammar),自底向上(LR grammar)
上下文无关文法(CFG)
- 终结符号
- 组成串的基本符号,与“词法单元名”同义
- 非终结符号
- 语法变量,表示特定串的集合
- 给出了语言的层次结构
- 一个开始符号
- 某个特定的非终结符号,其表示的串集合是这个文法生成的语言
- 一组产生式
- 描述将终结符号和非终结符号组成串的方法
- 产生式左部(头)是一个非终结符号
- 符号为
- 一个由0或多个终结符号和非终结符号组成的产生式右部
符号表示
- 终结符号:a b + 3 id ...
- 非终结符号:A B C ... S stmt
- 文法符号:X Y ...
- 终结符号串:u v w ...
- 文法符号串: ...
- 不同可选体: ...
- 开始符号:
推导
- 产生式:又称重写规则
- 从开始符号出发,每个重写步骤把一个非终结符号替换为它的某个产生式的体
- 一般性定义:假设一个产生式,表示“通过一步推导出”
- 句型:如果从文法的开始符号S开始,,则称是G的一个句型
- 句子:不包括非终结符号的句型(?)
- 语言:句子的集合,由文法G生成的语言被称为上下文无关语言
- 文法的等价性
非终结符号的替换顺序
- 最左推导:总是选择每个句型的最左非终结符号,
- 最右推导:总是选择每个句型的最右非终结符号,
最左句型
语法分析树
推导的图形表示形式,能够反映串的语法层次结构
- 内部节点:对应于一个非终结符号
- 子节点:对应于其父节点为头的产生式体
- 叶子节点:可以是终结符号或非终结符号,从左到右排列可得一个句型,称为这棵树的结果
二义性文法
如果一个文法可以为一个句子生成多棵不同的语法分析树,则该文法为二义性文法
- 消除二义性
- 消除左递归
- 文法中一个非终结符号A使得对某个串,存在一个推导,则称这个文法是左递归的
- 提取左公因子
消除二义性
基本思想:在一个then和一个else之间出现的语句必须是“已匹配的”,不能以一个尚未分配的then结尾
解决方案:引入新的非终结符号,用来区分是否是成对的then/else
消除左递归
-
立即左递归
,
-
多步左递归
给非终结符号排序:
如果只有A_{i}\rightarrow A_{j}\alpha(i<j),则不会有左递归
如果发现A_{i}\Rightarrow A_{j}\alpha(i>j),代入A_{j}当前产生式。若替换后有A_{i}的直接左递归,再消除
提取左公因子
A\rightarrow\alpha\beta_{1}|\alpha\beta_{2}\Longrightarrow A\rightarrow\alpha A', A'\rightarrow\beta_{1}|\beta_{2}
对于每个非终结符号A,找到最长公共前缀\alpha
自顶向下分析技术
可以看作是为输入串构造语法分析树的问题
也可以看作是一个寻找输入串的最左推导的过程
递归下降
预测分析技术:确定性的、无回溯的分析技术
通过向前看固定多个符号来选择正确的产生式。通常只看一个符号
两个函数: FIRST, FOLLOW
FIRST(\alpha)
可从\alpha中推到得到的串的首符号的集合
若\alpha\rightarrow\epsilon, 则\epsilon也在FIRST(\alpha)中计算规则
- 若文法符号x是终结符号,则FIRST(x)={x}
- 若x是非终结符号,且有x\rightarrowa..., 则将a也添加到FIRST(x)中。若x\rightarrow\epsilon,则\epsilon也在FIRST(x)中
- to x\rightarrowY_{1}...Y_{n}, ...
FOLLOW(A)(?)
对于非终结符号A,其定义为可能在某些句型中紧跟在A右边的终结符号的集合
若A是某些句型的最右符号,则$\inFOLLOW(A).$是特殊的输入串“结束标记”
预测分析表(?)
恐慌模式
自底向上技术
移进-归约
句柄剪枝