编译原理课程-备考-总结

程序设计语言编译原理(陈火旺第三版)

实验内容:https://github.com/JLChenode/PL0_compiler.git

第一章 编译器简介

在这里插入图片描述 编译器就是一个程序,它读入用某种语言编写的源程序,并翻译成一个与之等价的另一种语言编写的源程序。 编译过程的五个基本阶段
  1. 词法分析:
    输入源程序,对构成源程序的字符串进行扫描和分解,识别出一个个单词(也称单词符号,或简称符号)
    在词法分析阶段工作所依循的是语言的词法规则。描述词法规则的有效工具是正规式和有限自动机。
  2. 语法分析
    在词法分析的基础上,根据语言的语法规则,把单词符号串组成各类语法单位.,具体的说,语法分析是在单词流的基础上建立一个层次结构-----建立语法树
  3. 语义分析,中间代码生成
    语义分析利用语法分析阶段确定的层次结构来识别表达式和语句中的操作信息及类型信息,本阶段将产生源程序的一个显式中间表示
  4. 优化
    试图改进中间代码,以产生执行速度较快的机器代码
  5. 产生目标代码
    生成可重定位的机器代码或汇编代码

还可以采用“自编译方式”产生编译程序。
方法是,先对语言的核心部分构造一个小小的编译程序(可用低级语言实现),再以他为工具构造一个能够编译更多语言成分的较大编译程序。
这种通过一系列的自展途径而形成编译程序的过程叫做自编译过程。

总结:第一章重点是对编译器的结构有个整体的了解,主要是上述编译五步,及符号表管理,错误管理

第 2 章 高级语言及其语法描述

程序语言主要由语法和语义两方面定义

语言的语法是指这样一组规则

  1. 词法规则:是指单词符号的形成规则
    标识符,基本字,常数,算符,界符
    正规式和有穷自动机是描述词法结构和进行词法分析的有效工具
  2. 语法规则,语法规则规定了如何从单词符号形成更大的结构(即语法单位),换言之,语法规则是语法单位的形成规则
    下推自动机理论和上下文无关文法是我们讨论语法分析的理论基础
    语义是指这样的一组规则,使用它可以定义一个程序的意义。
    我们采用的方法为:基于属性文法的语法制导翻译方法。

语言的语法定义是非常重要的。本节将介绍语法结构的形式描述问题
文法是描述语言的语法结构的形式规则(即语法规则)。
上下文无关文法是这样一种文法,它所定义的语法范畴(或语法单位)是完全独立于这种范畴可能出现的环境的,(即处理这种语言时,不必考虑上下文,不能用来描述实际自然语言)
包括四个组成部分:

  1. 一组终结符号,
  2. 一组非终结符,
  3. 一个开始符号,
  4. 及一组产生式。P27
    产生式是定义语法范畴的
    VT终结符, VN非终结符
    若一个文法存在某个句子,它有两个不同的最左(最右)推导,则这个文法是法是二义的
    乔姆斯基:G=(VT ,VN ,S , ζ \zeta ζ) 是一个0型文法,如果它的每个产生式 α \alpha α-> β \beta β是这样的结构
    α \alpha α ∈ \in (VN ∪ \cup VT)* 且至少有一个非终结符,而 β \beta β ∈ \in (VN ∪ \cup VT)* 。
    0型文法也称短语文法。
    如果对0型文法分别施加以下的第i条限制,则我们就得到第i型文法:
    文法定义在这里插入图片描述
    1型文法也称上下文有关文法
    2型文法也称上下文无关文法,
    3型文法,正规文法。也称右线性文法。
    3型文法还有另一种形式,称左线性文法;
    3型文法等价于正规式所以也称正规文法。

第 3 章词法分析:

从左至右逐个字符地对源程序进行扫描,产生一个个单词符号,把作为字符串的源程序改造成为单词符号串的中间程序。
1.关键字(保留字或基本字):while, if
2.标识符:用来表示各种名字
3.字面常数:256,3 .14,true, ‘abc’
4. 运算符:如,+、-、*、/ 等等
5.分界符:如逗号,分号,冒号等
词法分析器输出的单词符号常常表示为二元式:
(单词种别,单词符号的属性值)

  1. 词类编码原则,1,4,5,通常一词一码,2,3,分别是一类一码
  2. 属性:1,4,5通常是空,2,3,是其符号表的入口地址

单词符号的识别

一个状态转换图可用于识别(或接受)一定的字符串。
PL0 语言

有限次使用上述三步骤而定义的表达式才是 ∑ \sum 上的正规式,仅由这些正规式表示的字集才是 ∑ \sum 上的正规集。
所有词法结构一般都可以用正规式描述。
若两个正规式所表示的正规集相同,则称这两个正规式等价。

不确定的有限自动机(简称NFA)
确定的有限自动机(简称DFA)

  • 状态集合S;
  • 输入字母表 ∑ \sum
  • 转换函数move-f : S * ∑ \sum → \rightarrow S;
  • 唯一的初态 s ∈ \in S;
  • 终态集合F ⊆ \subseteq S;

DFA可以表示为状态转换图
从状态图中看NFA 和DFA的区别:

  1. 弧上的标记可以是*中的一个字,而不一定是单个字符;
  2. NFA同一个字可能出现在同状态射出的多条弧上。而DFA则不行
    DFA是NFA的特例

NFA确定化成DFA 子集法
引进新的初态结点X和终态结点Y.

  1. 从X到S0中任意状态结点连一条 ϵ \epsilon ϵ箭弧, 从F中任意状态结点连一条 ϵ \epsilon ϵ箭弧到Y。

  2. S0是初态节点集合,F是终态节点集合
    设字母表只包含两个a和b,我们构造一张表:

  3. 首先,置第1行第1列为 ϵ \epsilon ϵ-closure({X})求出这一列的Ia,Ib;

  4. 然后,检查这两个Ia,Ib,看它们是否已在表中的第一列中出现,把未曾出现的填入后面的空行的第1列上,求出每行第2,3列上的集合…

  5. 重复上述过程,知道所有第2,3列子集全部出现在第一列为止。

在这里插入图片描述

现在把这张表看成一个状态转换矩阵,把其中的每个子集看成一个状态。
这张表唯一刻划了一个确定的有限自动机M,它的初态是 ϵ \epsilon ϵ -closure({X}) ,它的终态是含有原终态Y的子集。
不难看出,这个DFA M与M’等价。

在这里插入图片描述

这里实际上,还可以对,DFA优化,比如说,终态,3,4,5,6合并成一个状态

*** DFA 的最小化算法->下面***

正规文法和正规文法存在一个有限自动机FA与其等价
定理:
1.对每一个右线性正规文法G或左线性正规文法G,都存在一个有限自动机(FA) M,使得L(M)=L(G)。
2.对每一个FA M,都存在一个右线性正规文法GR和左线性正规文法GL,使得L(M)=L(GR)=L(GL)。

  1. 对任何FA M,都存在一个正规式r,使得L®=L(M)。
  2. 对任何正规式r,都存在一个FA M,使得L(M)=L®。

DFA的化简
把M的状态集划分为一些不相交的子集,使得任何两个不同子集的状态是可区别的,而同一子集的任何两个状态是等价的。最后,让每个子集选出一个代表,同时消去其他状态。
具体做法: 对M的状态集进行划分

  1. 首先,把S划分为终态和非终态两个子集,形成基本划分 ∏ \prod
    假定到某个时候, ∏ \prod 已含m个子集,记为 ∏ \prod ={I(1),I(2),…,I(m)},
  2. 检查 ∏ \prod 中的每个子集看是否能进一步划分:
    对某个I(i),令I(i)={s1,s2, … ,sk},若存在一个输入字符a使得Ia(i) 不会包含在现行的某个子集I(j)中,则至少应把I(i)分为两个部分
  3. 重复上述过程,直到所含子集数不再增长。
  4. 对于上述最后划分 ∏ \prod 中的每个子集,我们选取每个子集I中的一个状态代表其他状态,则可得到化简后的DFA M’。
  5. 若I含有原来的初态,则其代表为新的初态,若I含有原来的终态,则其代表为新的终态。

举例来看
在这里插入图片描述

第 4 章自上而下,语法分析   叫做推导

分析方法:递归子程序法、预测分析法,(一般都要回溯)
从文法的开始符号出发,向下推导出句子;
试图用一切可能的办法,从文法开始符号出发,
   自上而下地为输入串建立一课语法树;(寻找一个最左推导)
此分析过程本质上是一种试探过程
消除直接左递归:BNF表示法或者下面:
将 A → A α|β 替换为

  1. A→βA’ 和

  2. A’→ αA’|ε

间接左递归,把终结符代入法
防止回溯,则需要计算first集,   follow集
脑海中思考一遍,,开始符号的follow集首先给他一个‘#'
某些非LL(1)文法改写为LL(1)文法

  1. 消除左递归;
  2. 反复提取公共左因子

并非一切非LL(1)的文法都能改写成LL(1)的。

递归子程序法
预测分析程序法
 使用一张分析表和一个栈来实现LL(1)分析
预测分析表M[A,a]是一个矩阵,行代表非终结符,列代表终结符或‘#’;矩阵元素代表对应的产生式或出错标志栈STACK中存放文法符号,栈底先放一个结束符‘​#’

预测分析表构造算法:
1、计算文法的每个非终结符的FIRST集和 FOLLOW集
2、1) 对于每一产生式 A→ α \alpha α ,执行 2)
2) 对于FIRST (α)中的每一终结符a(或$),
将 A→ α 填入 M[A,a] 
3) 若ε ∈ FIRST (α),则对b ∈ FOLLOW(A)将 A→ α 填入 M[A,b]
4)将所有无定义的 M[A,b] 标上出错标识。

例子,作业4 第6页 第四章这种题出的概率很大

第 5 章自下而上,语法分析   叫做规约

所谓自下而上分析法就是从输入串开始,逐步进行“归约”,直至归约到文法的开始符号;或者说从语法树的末端开始,步步向上“归约”,直到根结。
“移进-归约”思想

  1. 简单优先分析法:按一定原则求出文法中所有符号(终结符和非终结符)的优先关系,按这种关系求出句柄。(规范归约——从左向右的规约);
  2. 算符优先分析法:只考虑算符(终结符)之间的优先关系,不考虑非终结符之间的优先关系。按这种关系求出最左素短语。(不规范归约)

规范归约是关于是一个最右推导的逆过程
最左归约 规范推导

算符优先分析
归约即计算表达式的值。归约顺序不同,则计算的顺序也不同,结果也不一样。
如果规定算符的优先次序,并按这种规定进行归约,则归约过程是唯一的。
起决定作用的是相邻的两个算符之间的优先关系。

所谓算符优先分析法就是定义算符之间的某种优先关系,借助于这种关系寻找“可归约串”和进行归约。

定义:
算符文法: 它的任一产生式的右部都不含两个相继(并列)的非终结符
算符文法,终结符对的优先关系计算

简单来说, 就是在一个句子的语法树中, 如果两个终结符在语法树的同一层,
则先找到的终结符优先级等于后找到的终结符的优先级
如果两个终结符在语法树的不同层, 层次高的终结符的优先级高于层次低的终结符的优先级

算符优先文法: 如果一个算符文法G中的任何终结符对(a,b)
至多只满足下述三关系之一:a=·b,a<·b, a·>b
从算符优先文法G构造优先关系表的算法。
通过检查G的每个产生式的每个候选式,可找出所有满足a=·b的终结符对。

  1. a=·b 当且仅当文法G中含有形如P→…ab…或P→…aQb…的产生式;
    确定满足关系<·和·>的所有终结符对:
    首先需要对G的每个非终结符P构造两个集合FIRSTVT§和LASTVT§:

可用下面两条规则来构造集合FIRSTVT§:

  1. 若有产生式P→a…或P→Qa…,则a ∈ \in FIRSTVT§;
  2. 若aFIRSTVT(Q),且有产生式P→Q…,则a ∈ \in FIRSTVT§。
    可用下面两条规则来构造集合LASTVT§:
  3. 若有产生式P→… a或P→ … aQ,则a ∈ \in LASTVT§;
  4. 若a LASTVT(Q),且有产生式P→… Q ,则a ∈ \in LASTVT§。
    然后,确定优先关系
     假定有个产生式的一个候选形为…aP… 那么,对任何b ∈ \in FIRSTVT§,有 a<·b。
     假定有个产生式的一个候选形为…Pb… 那么,对任何a ∈ \in LASTVT§,有 a·>b。

有了优先表,就开始,算符优先分析算法
主要是找最左素短语

实际例子,课件51页,见计算题总结文档,第3题
5.3 LR分析器
规范归约的关键问题是寻找句柄.
LR分析方法:把"历史"及"展望"综合抽象成状态;由栈顶的状态和现行的输入符号唯一确定每一步工作
• LR分析器的核心是一张分析表:
ACTION[s,a]:当状态s面临输入符号a时,应采取什么动作.
GOTO[s,X]:状态s面对文法符号X时,下一状态是什么
• 每一项ACTION[s,a]所规定的四种动作:

  1. 移进 把(s,a)的下一状态s’和输入符号a推进栈,下一输入符号变成现行输入符号.
  2. 归约 指用某产生式A进行归约. 假若的长度为r, 归约动作是, 去除栈顶r个项,使状态sm-r变成栈顶状态,然后把(sm-r, A)的下一状态s’=GOTO[sm-r, A]和文法符号A推进栈.
  3. 接受 宣布分析成功,停止分析器工作.
  4. 报错

定义:对于一个文法,如果能够构造一张分析表,使得它的每个入口均是唯一确定的,则这个文法就称为LR文法。 如果能用一个每步顶多向前检查k个输入符号的LR分析器进行分析,则这个文法就称为LR(k)文法.
以下每种方法都要先构造DFA,用来识别活前缀,再画表
 A . 称为"归约项目"
 归约项目 S’ . 称为"接受项目"
 A .a (aVT) 称为"移进项目"
 A .B (BVN) 称为"待约项目".

LR0 文法G的每个产生式的右部添加一个圆点称为G的LR(0)项目
1 构建拓广文法,并编号 (2,3,4)可以合起来写
2 写出文法的所有LR0项目,3 写出文法的LR0项目集规范族
4 写出识别活前缀的DFA(使用项目集规范族)
5,构造分析表 P109
区别其他:在归约时,即对于A->α. 属于状态Ik,(产生式是文法的第j个产生式)
把规约表中,ACTION[k, a]全部置为 “ rj”
如果分析表中,不存在冲突,表示文法是一个LR0文法
或者直接判断项目集中,存在一个项目集中同时含义移进项目和归约项目,也得出冲突
6,根据分析表对句子进行分析

SLR(1)
步骤,1,2,3,4与LR0完全一致
5 在构造分析表时
区别:若项目A→·属于Ik,假定A为文法G的第j个产生式;
那么,对任何终结符a,aFOLLOW(A),置ACTION[k,a]为 “rj”;
如果分析表中,不存在冲突,表示文法是一个SLR(1)文法
6,根据分析表对句子进行分析

LR1 这里重新定义项目
每个项目的一般形式是[A→·, a1a2…ak] ,
这样的一个项目称为一个LR(k)项目。项目中的 a1a2…ak 称为它的向前搜索符串(或展望串)
步骤:

  1. 构建拓广文法,并编号
  2. 构建LR(1)的项目集和识别活前缀的DFA ,
    举例一个状态是这样,从S->.BB,# 推出 B->.aB,a/b,
    是因为S->.BB,# 绿色B的first集是a,b
  3. 构造LR(1)分析表
    区别:若项目[A→α·,a]属于Ik,则置ACTION[k, a]为 “rj”;其中假定A→α为文法G的第j个产生式。

按上述算法构造的分析表,若不存在多重定义的入口(即,动作冲突)的情形,则称它是文法G的一张规范的LR(1)分析表

LALR
如果两个LR(1)项目的状态集,除了搜索符号之外,是相同的,则把这两个项目集合并
同心集的合并不会产生新的“移进-规约”冲突,但有可能产生新的“规约-规约”冲突

P117

第 6 章,第 8 章,第 9 章:不考

第 7 章 语义分析和中间代码产生

翻译模式看书,

  1. 赋值语句
  2. 布尔表达式
  3. 控制语句

第10章 优化

10.1,10.2
优化原则:3条
基本优化技术:删除公共子表达式、复习传播、删除无用代码,
(设计循环的优化)代码外提,强度削弱,删除归纳变量
基本块:
划分基本块,构造程序流图
基本块的DAG构造
利用DAG进行基本块内优化

10.4 数据流分析
活跃变量:

一个变量在基本块入口处是活跃的,则一定有:或者它在基本块的LiveUSe集合中,或者它在基本块的出口处是活跃的且在基本块中没有重新定值

有LiveIn(B) = LiveUse(B) ∪ ( LiveOut(B) – Def(B) )
所以在计算每个基本块的活跃变量时,要倒着计算,因为最后一个基本快 的LiveOut为空

第11章 目标代码生成:

11.3.1计算待用信息:
算法:还是看例子学习更好P314

  1. 开始时,把基本块中各变量的符号表登记项中的待用信息栏填为“非待用”,并根据该变量在基本块出口之后是不是活跃的,把其中的活跃信息栏填为“活跃”或“非活跃”;
  2. 从基本块出口到基本块入口由后向前依次处理各个四元式。对每一个四元式i: A:=B op C,依次执行下面的步骤:
    1. 把符号表中变量A的待用信息和活跃信息附加到四元式i上;
    2. 把符号表中A的待用信息和活跃信息分别置为“非待用”和“非活跃”;
    3. 把符号表中变量B和C的待用信息和活跃信息附加到四元式i上;
    4. 把符号表中B和C的待用信息均置为i,活跃信息均置为“活跃”。
      顺序不能颠倒
      11.3.3,代码生成算法,
      两个数组,RVALUE AVALUE分别存储,寄存器、变量现行值

P316

10.5DAG图 结点重排算法 P323
使表达式的右部,从右往左计算,

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值