编译原理笔记(上海交大CS二专)

1 Introduction

20分出勤
10分大作业:交纸质版,报告性质的大作业
70分考试
汇编程序是翻译程序
汇编语言程序是汇编程序的源程序
编译程序将高级语言程序翻译成低级语言的程序
解释程序将源程序中的语句按动态顺序,逐句逐段翻译成可执行代码,并立即执行

1.1 编译的过程

  • 词法分析:对组成源程序的字符串进行扫描和识别,识别出一个具有独立意义的单词,将字符串变换成单词符号流
    标识符:用户自己定义的变量名之类的
  • 语法分析:在输出单词流的基础上,根据语言的语法规则分析单词流是否正确的组成各类语法单位
    语法错误:但一个语句中就能发现
  • 语义分析、中间代码生成:明确你是想要干什么,根据语义规则逐一翻译成等价的中间语言代码,通常称为语法制导翻译
    语义错误:多条语句综合来看,发现的问题,比如说有变量名c没有定义
  • 优化阶段:等价变换,使程序占用空间少,运行时间短
  • 目标代码生成阶段:
    C++是一门通用的语言: 不同的指令系统,都有这个语言的编译系统,意味着有多个不一样的编译器

编译的前端:词法分析、语法分析、语义分析中间代码生成
后端:目标代码生成

1.2 编译程序的实现

C o m p i l e r S L − > A + C o m p i l e r A S − > A = C o m p i l e r A L − > A Compiler^{L->A}_{S}+Compiler^{S->A}_{A}=Compiler^{L->A}_{A} CompilerSL>A+CompilerAS>A=CompilerAL>A
其中A表示硬件指令系统,L和S表示一种高级语言

  • 自展:若 S ⊆ L S \subseteq L SL表示S是L的扩展
  • 移植:
    C S S − > B + C A S − > A = C A S − > B C_{S}^{S->B}+C_{A}^{S->A}=C_{A}^{S->B} CSS>B+CAS>A=CAS>B
    上面这是交叉编译器
    C S S − > B + C A S − > B = C B S − > B C^{S->B}_{S}+C_{A}^{S->B}=C_{B}^{S->B} CSS>B+CAS>B=CBS>B

2 文法与语言

  • 词法:正规文法
  • 语法:上下文无关文法
  • 语义:上下文有关文法

2.1 定义

  • 字母表:符号的非空有穷集合,用 Σ \Sigma Σ表示,通常程序语言的字母表是ASCII字符集
    ASCII码一般只用前128个字符

  • 字符串:有字母表 Σ \Sigma Σ 的字符所组成的有穷序列,称为字母表上的符号串/字符串/字,用 Σ ∗ \Sigma * Σ表示所有字符串的集合

  • 空串:不包含任何字符的字符串,用 ϵ \epsilon ϵ 表示

  • 字符串的长度:字符串中字符的个数

  • 字符串的联结:x=ab, y=cd, xy=abcd

  • 前缀与后缀:若z=xy,则x是z的前缀,y是z的后缀

  • 子串:非空字符串x删去他的前缀和后缀所得的字符串是x的子串

  • 语言:给定字母表 Σ \Sigma Σ,则 Σ \Sigma Σ上任意字符串集合,称为 Σ \Sigma Σ上的一个语言,记为 L L L
    ϵ {\epsilon} ϵ是语言,但是{}不是语言

  • L ∪ M = { x ∣ x ∈ L , o r x ∈ M } L \cup M=\{ x|x \in L, or x \in M \} LM={xxL,orxM}
    Σ = { a , b } \Sigma =\{ a, b\} Σ={a,b},则 Σ 2 = { a b , b a , a a , b b } \Sigma ^2 =\{ ab, ba, aa, bb\} Σ2={ab,ba,aa,bb},显然 Σ 3 \Sigma ^3 Σ3是长度为3的字符串的集合, Σ ∗ = Σ 0 ∪ Σ 1 ∪ Σ 2 ∪ Σ 3 ∪ . . . . . \Sigma ^* =\Sigma ^0 \cup \Sigma ^1 \cup \Sigma ^2 \cup \Sigma ^3 \cup..... Σ=Σ0Σ1Σ2Σ3.....

  • 文法:文法由四部分组成:终结符号集Vt、非终结符号集Vn、文法开始符、产生式的非空有限集合
    其中终结符号集与非终结符号集之间不能有交集

  • <字母> L=a|b|c…

  • <数字> D=0|1|2…

  • <字母或数字> T->L|D

  • <字母数字串> S->T|ST(这是左递归,即产生式的左部与右部的最左面相同)

  • <标识符> 字母开始的字母数字串 I->L|LS
    是IS的一个子集,所以I才能做文法的开始符

  • 开始符:一定是非终结符号,一定不是 ϵ \epsilon ϵ

  • <产生式>左部一定是非终结符号,是终结符号集与非终结符号集的正闭包,即至少有一个非终结符号

  • 终结符号:语言不可再分的基本符号,一般用小写字母表示

  • 非终结符号:也称语法变量,一半用大写字母表示

  • 文法符号串:终结符与非终结符的任意组合,一般用希腊字母表示
    为什么C++中运算符重载不能改变符号的优先级和结合性??因为这些文法中都规定好了
    a=b=c=0是右结合的

  • 直接推出:如果 A − > δ A-> \delta A>δ ,则称 α A β \alpha A \beta αAβ 可直接推导出 α δ β \alpha \delta \beta αδβ

左到右是推导,右到左是规约

  • 上下文无关文法:文法的所有产生式都是 P − > α P-> \alpha P>α,且P是非终结符, α \alpha α是文法符号串,且分法开始符至少在产生式的左部出现一次。
  • 从文法的开始符,经过至少零步推导的多步推导,得到的文法符号串,称文法符号串为句型
  • 全部都是又终结符号组成的句型是一个句子
    所以说S一个文法的句型,但不可能是句子。句子是句型的一个特例。
  • 语言:文法G所产生的句子的全体,称为文法G所产生的语言L(G)
  • 文法的等价:如果文法产生的语言相同,则成为文法是等价的。
  • 最左推导:每次推导,都是对句型的最左边的非终结符进行推导
    在这里插入图片描述
    我们将将最右推导称为规范推导
    规范规约:从左往右将第一个规约起来,所以规范规约和最右推导互为逆过程
  • 短语:就像“玩电脑”,如果 α β δ \alpha \beta \delta αβδ是一个句型,如果 S = > α A δ S=>\alpha A\delta S=>αAδ A = > β A=>\beta A=>β
  • 直接短语:只经过一步推导得到的短语
  • 句柄:一个句型的最左直接短语
  • 分析树:一棵树可以表示一个句型的推导
  • 子树:每个子树对应的符号串是这个句型的一个短语
  • 二义性:一个句子有两种不同的规范推导或两颗不同的分析树
    对于一个二义文法,如果能找到一个非二义文法,那么二义文法的二义性可以消除

3 词法分析

单词符号分为5类: 基本字、标识符、常数、运算符、界符
单词符号的编码:(单词类别,单词符号的属性值——符号表的入口地址)
输入预处理:剔除注释、多余的空白符、制表符换行符
扫描缓冲区:长度为2N,两个指针,只要单词长度小于N
状态转换图
正规集:正规表达式简称正规式,它表示的集合称为正规集,用L®表示
如果两个正规集相同,那么这两个正规式等价
Σ = a , b \Sigma={a,b} Σ=a,b,则R=a(a|b)*是正规式,正规集表示所有以a开头的字符串集。其中 ∗ * 表示闭包

用文法来识别单词,太浪费时间。用正规式进行词法分析就比较省时间。

3.1 有限自动机

  • 有限自动机FAM:一般的状态转换图,用五元组表示(有穷字母表,有限状态集,唯一的初态,终态集,单值映射)
    确定性有限自动机DFA是非确定性有限自动机NFA的特例
    如果初态是一个集合,那么一定是NFA——存在空字 ϵ \epsilon ϵ一定是NFA
  • 状态转换矩阵:表示状态转换图,m*n,m表示有限状态数量,n表示字母表数量
  • FAM识别的语言:一个字符串能够从初始状态到终止状态,称为FAM所识别。为FAM所识别的字符串集称为FAM所识别的语言,记为L(M)
  • 有限状态机的等价:如果L(M)=L(M’),称为M和M’等价
    对于任意给定的NFA,一定存在一个DFA与之等价
    **怎么找DFA??**用子集法
    在这里插入图片描述
    **终态怎么找?**原来NFA的终态去哪里了,DFA的终态就是啥
  • 状态的等价:从si出发能识别的字符,和从sj出发能识别的字符,如果二者相同,称为是等价的,否则就是可区分的
  • 简化的DFA:如果DFA没有无关状态,也没有彼此等价的两个不用状态
    **如何简化呢?**生成DFA之后,先将所有的状态分成两类终态集A和非终态集B,然后读入一个元素a,看如果A中的状态中A1读a变到A3,而A2状态读到a变到B1,那么说明A1和A3是两个不同的,应该拆开。然后不断循环,直达大家都没法拆开,还在一起的状态都是等价的。

当然有可能初态和终态是同一个集合,那么意思就是最开始就没法分成两类,那么大家状态都是等价的
作业:3.10:a、d

3.2 一个例子

先是一个NFA
在这里插入图片描述
然后按照子集法进行“洗牌”,得到构造的表
在这里插入图片描述
根据这个表,重新命名得到DFA
在这里插入图片描述
然后再做DFA的简化,先分成终结集和非终结集,然后再分
在这里插入图片描述


大作业题目:中文文本中单词自动查错方法的探讨。
内容:

  1. 问题
  2. 主要难点
  3. 解决方法:出一个自然语言的算法,
  4. 可能需要什么工具:比如中文分词系统?比如词库?
    提交形式:纸质论文报告,16周提交。

4 语法分析

语法分析有两种方法:自上而下或自下而上,来判断一个输入串是否是一个合法的句子。
自上而下:推到,一个非终结符,可能对应好几个产生式的右部。其实就是看能否从根结点出发,向下生长出一棵语法分析树,其叶结点组成的句子恰为输入串。
自下而上:规约,从叶结点出发,向上归结出以文法开始符为根结点的语法分析树
任何一个句子都可能存在最左推导或者最右推导,但任何一个句型不一定存在。但句柄有且仅有一个
规范推导:最右推导

从文法的开始符S出发,经过0步推导或者多步推导得到的任何的符号串是句型。

4.1 试探分析法

从根节点(开始符S)开始,生长分析树来进行匹配。如果
空字既不是终结符,也不是非终结符
每一个非终结符号对应一个函数,名字就是非终结符号,函数体就是他产生式的右部
**为什么叫递归下降分析器?**因为这些函数可以递归调用自己
缺点:一但文法改了,程序也就要改

4.2 递归下降分析法

要消除左递归

4.3 非递归的预测分析法

推导的方法,利用分析表,对应LL(1)文法

4.4 算符优先分析方法

  • 算符文法:对于上下文无关文法G,如果它不含有 ϵ \epsilon ϵ产生式,并且产生式右部不含相连的非终结符
  • 算符优先文法OPG:对于一个不含 ϵ \epsilon ϵ规则的算符文法G,如果任意两个终结符号a和b,优先级更高、更低、相同三个关系只有一个关系成立,则称G是算符优先文法
  • FIRSTVT(A)={a|A->a…或A->Ba…,其中a是终结符,B是非终结符}其实是产生式右部的第一个终结符
  • LASTVT(A)={a|A->…a或A->…aB,其中a是终结符,B是非终结符}其实是产生式右部的最后一个终结符

4.5 LR分析法

  • 活前缀DFA:对于规范句型的一个前缀,如果它不含句柄以外的任何符号,则称这个前缀为活前缀
  • 规范句型:最右推导每次得到的句型
    在LR分析工作中的任一时刻,栈内的文法符号应该是某一规范句型活前缀

4.5.1 LR(0)文法

4.5.2 SLR(1)文法

如果同时存在右部相同的两个表达式: A − > α A->\alpha A>α B − > α B->\alpha B>α,如果FOLLOW(A)和FOLLOW(B)不相交
a ∈ F O L L O W ( A ) a \in FOLLOW(A) aFOLLOW(A),则用 A − > α A->\alpha A>α归约
a ∈ F O L L O W ( B ) a \in FOLLOW(B) aFOLLOW(B),则用 B − > α B->\alpha B>α归约
相当于SLR(1)消除了LR(0)一些不该出现的情况

4.5.3 LR(1)文法不考

就怕SLR(1)方法中,两个FOLLOW集合有交集,这就有“归约-归约”冲突,因为我们只是简单的求一个FOLLOW集合,并不一定是规范归约的FOLLOW集合
所以用 [ A − > α . , a ] [A->\alpha. ,a] [A>α.,a]只有当输入符号是a时才能用 A − > α A->\alpha A>α归约,而不是对FOLLOW(A)的所有符号

4.5.4 LALR(1)文法不考

LALR(1)分析表是LR(1)分析表的简化
同心的LR(1)项目集: 两个LR(1)项目集中,除了搜索符不同之外,核心部分都相同
LALR(1)分析法:将LR(1)项目集规范族中所有同心的项目集合并为一个,以减少项目集个数,所以说合并之后只可能有“归约-归约”冲突,新产生“移进-归约”冲突
那么多的分析表,有什么共同点?? 所有分析表关于移进的部分都一样,不同的是关于归约的部分

5 语义分析

5.1 赋值语句

要考虑简单变量、数组、a=a*(b+c)这些情况
对于102010的三维数组d1=10,d2=20,d3=10,A[y,z,k],low1=low2=low3=1,一个元素所占空间W=4,则x=A[y,z,k]的三地址语句序列为

  1. t1=y*20
  2. t1=t1+z
  3. t2=t1*10
  4. t2=t2+k
  5. t3=A-211
  6. t4=t2*4
  7. t5=t3[t4]
  8. x=t5
    如果是A[y,z,k]=x则7、8变成
    t3[t4]=x

5.2 布尔表达式

5.2.1 数值表示法

对布尔表达式 af 生成三地址代码,其中 a < b a<b a<b c = d c=d c=d e > f e>f e>f分别是一个布尔量,对每个布尔量都有四条三地址代码
在这里插入图片描述

5.2.2 解释法(短路法)

每个布尔量有两个goto表达式,在语义分析的时候通过三地址代码的顺序来表示优先级
可是不知道跳转的位置怎么办? 先空着,最后按照优先级一点一点合并,比如说true的两部分连成一条线,false的两部分连成一条线
对于a<b or c<d and not e<f
在这里插入图片描述
如果这个布尔表达式是用于if条件语句:
S->if(E) L=L+1; else L=L-1
那么后面增加:
106 t1=L+1
107 L=t1
108 goto 0
109 t2=L-1
110 L=t2
nextlist=108//这句话表示,108语句跳转的目标地址应该是nextlist,即下一个语句

6 优化

在这里插入图片描述

6.1 程序流图

到了中间结点一级,程序的数据流不好判断,需要构造程序流图。程序流图的每一个节点是 顺序执行 程序段,即基本块
不执行的语句在这一部分就被删掉了

6.2 无环有向图DAG

描述基本块内部,可以合并已知量(能常数就常数),删除多余代码(如果没有被引用)
在这里插入图片描述

6.3 循环优化

  • 循环的定义:是程序流图中有唯一入口节点的强连通子图
  • 必经结点集:首结点和他本身是每个结点的必经结点
    怎么求必经结点集? 设D表示必经结点集,如果节点2的前驱节点是1和9,那么
    D ( 2 ) = { 2 } ∪ D ( 1 ) ∩ D ( 9 ) D(2)= \{2\}\cup D(1) \cap D(9) D(2)={2}D(1)D(9)
    变化一次就要再循环,直到大家都不变
    回边是什么? 如4是5的必经节点集中的点,则5->4是回边

步骤总结一下

  1. 找基本块
  2. 找边,形成程序流图
  3. 局部优化:基本块划分的时候就能优化,删除掉不可能执行到的代码
  4. 循环优化:循环优化之前先要判断出是否是循环,循环优化的细节不要求

7 代码生成

代码生成的输入有两部分:一个是前端生成的中间代码,及三地址代码,一个是符号表

  • 活跃信息:出了基本块之后变量是否被引用
  • 待用信息:在基本块内某一变量下一个引用点
    [例8.1]四行代码
    t=a-b
    u=a+c
    v=a-t
    w=v+u
    在这里插入图片描述
    转换出二地址代码
    mov a, R0
    sub R0, b
    mov a, R1
    add R1,c
    mov R1, u
    mov a, R1
    sub R1,R0
    add R1,u
    mov R1,w

8 复习课

  1. 自展和移植
  • 给定文法,描述这个文法对应的语言
  • 给定语言,描述这个语言对应的文法
  • 给定文法和句型,确定该句型的短语、直接短语、句柄和短素语
  1. 正规式->最简DFA
  • 正规式->NFA
  • NFA->DFA
  • 化简
  1. 预测分析表、算符优先分析表、LR(0)、SLR(0)
  2. 综合语句的三地址代码翻译
  • 赋值语句
  • 数组元素
  • 条件语句
  • 循环语句
  • 程序流图的描述(基本块的划分、有向边)
  • 局部优化DAG方法
  • 循环体查找(必经结点集、回边)
  1. 待用信息的确定和目标代码的生成
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值