编译原理 笔记

面向考试的编译复习笔记。

U4 语法分析(包含4~7讲)

  1. 自顶向下方法 只介绍了LL(1)文法,这个其实就是预测分析法。核心思想就是根据下一个输入的字符,决定采用哪个产生式进行推到。自顶向下分析过程称为推导。

第一个“L”表示从左向右扫描输入
第二个“L”表示产生左推导
“1”表示在每一步中只需要向前看一个输入符号来决定语法分析动作

  1. 自底向上分析 介绍了LR(0)、SLR(1)、LR(1)、LALR。
    拿到了识别活前缀的DFA图,构建LR分析表:
    1.1 对于待约项目和移入项目,大家的操作都是一样的。
    1.2 对于规约项目,大家具有不同的操作:
    ① LR(0)对于所有的非终结符,都采取规约的操作;
    ② SLR(1)仅对于该规约项目的左部的FOLLOW集中的非终结符采取规约操作;
    ③ LR(1)仅对于该规约项目的搜索符集中的非终结符采取规约操作。

L:从左向右扫描输入字符串
R:自底向上规约,使用的是最左规约,也就是反向的最右推导
K:向前看K个字符,K=1时省略


U5 语法制导翻译(包含8~10讲)

5-1 语法制导翻译概述

5-2 语法制导定义SDD

5-3 SDD求值顺序

  1. 依赖图

5-4 S属性定义和L属性定义

  1. S属性SDD=S属性定义=S-SDD:仅使用综合属性。适用于自底向上语法分析。
  2. L属性SDD=L属性定义=L-SDD:可以有综合属性,也可以有继承属性(但是继承属性必须是自己的、左兄弟节点的或者是父节点的)。
  3. 有上可知,L-SDD包含S-SDD。

5-5语法制导翻译方案SDT

  1. SDT可以看作是SDD的具体实现方案
  2. 将S-SDD转换为SDT:这个较为简单,因为S属性定义中,所有的属性值都是综合属性,只有在所有的子节点计算完毕之后才可以计算综合属性,所以语义动作直接放在产生式的最后即可。
  3. 将CFG转化成SDT之后,对应的分析SLR规约过程是,“状态-符号”栈扩展为“状态-符号-属性值”栈。
  4. L-SDT的话,综合属性同上,继承属性放在该非终结符即将出现的位置。这一点比较好理解,因为继承属性必须在这个非终结符出现之前计算好。

5-6在非递归的预测分析过程中进行翻译

  1. 非递归的LL分析,和L-SDT类似。

5-7在递归的预测分析过程中进行翻译

  1. 递归预测分析法就是为每个非终结符编写一个函数,当分析这个非终结符的时候调用这个函数即可。现在为了完成翻译,需要修改补充这个函数即可。继承属性作为形参,返回值作为综合属性。

5-8L属性的自底向上翻译

  1. 所有S-SDD都可以用于自底向上,因为它的属性是综合属性。但是L-SDD中包含继承属性,所以需要修改才能进行自底向上翻译。
  2. 修改:引入一个非终结符(称为标记非终结符),该标记非终结符具有唯一的空产生式,语义动作和原等价。(标记非终结符的继承属性是原语义动作右边的值,综合属性就是计算结果,同时也是原非终结符动作的继承属性)
  3. 这个修改过后,原LL文法实际上变成了LR文法,可以进行LR分析。

语法制导翻译小结:
语法制导翻译是一种技术,该技术可以在语法分析(规约、推导)的同时进行语义分析。
基本思想:

  1. 将(语言结构的)语义以属性的形式赋予(代表此结构的)文法符号。
  2. 属性的计算以语义规则的形式赋予(由文法符号组成的)产生式。
  3. 在语法分析的(规约、推导)同时,通过语义规则实现对属性的计算,以达到对语义的处理。

U6 中间代码生成(包含11~14讲)

这一章主要学习各种语句的翻译

6-1类型表达式

  1. 类型表达式就是一套古怪的抽象定义,一套表示规则

6-2声明语句的翻译

  1. 变量offset表示下一个可用的位置
  2. 声明语句的翻译,仍然是一些产生式的翻译,和上一章没啥区别,就是在推导的时候执行语义动作即可。

6-3简单赋值语句的翻译

  1. code属性包含翻译方案的三地址码序列,表达式的翻译过程中,需要多次复制子表达式的code内容,还需要生成新的结合的三地址码,较为复杂,因此产生了“增量翻译方案”。
  2. 根据例子,发现翻译过程还是比较直观的,只是去掉了原始的冗余部分。

6-4数组引用的翻译

  1. 重点是对于数组元素位置的翻译,特别是多维数组的时候。
  2. 可以发现,三地址码是规约过程中进行的语义动作生成的。

6-5控制流语句及其SDT

  1. 主要讲分支语句和循环语句,根据布尔表达式的真假结果跳转到不同的代码段。
  2. 控制流语句分析的时候需要画程序片段图,很多小方块。我想你应该记起来上课时候的内容了。

6-6布尔表达式及其SDT

6-7控制流翻译的例子

6-8布尔表达式的回填

  1. 回填技术将所有属性转化成综合属性,方便于LR分析

6-9控制流语句的回填

6-10switch语句的翻译

  1. 高效n回填,先把每个代码块和符号绑定起来,最后再全部回填

6-11过程调用语句的翻译

  1. 第一步将所有的参数单独计算出来,然后直接调用函数即可

U7 运行存储分配(包含15讲)

7-1运行存储分配概述

  1. 有个活动记录的重要概念,其中

控制链:指向调用者的活动记录
访问链:用来访问存放于其他活动记录中的非局部数据

7-2静态存储分配

  1. 顺序分配法:按照过程出现的先后顺序逐段分配存储空间。缺点是比较浪费空间
  2. 层次分配法:并列过程就共享分配空间

7-3栈式存储分配

  1. 引入了活动树的概念

7-4调用序列和返回序列

  1. 调用者和被调用者分工合作完成活动表的相应位置的填写

7-5非局部数据的访问

  1. 不支持过程嵌套的语言:数据只有两种,一种是局部数据(存放在栈中),一种是全局数据(存放在静态数据中)。这两种数据访问都比较方便。
  2. 支持过程嵌套的语言(一个过程中定义了另一个过程):
嵌套深度:没有被任何过程嵌套的过程,嵌套深度为1;此外的依次+1。
变量的嵌套深度和定义它的过程的嵌套深度等同。

访问链指针:使得内嵌过程可以访问外围过程的对象。内嵌过程的访问链指向外围活动的活动记录。

7-6符号表

7-7符号表的建立


U8 代码优化(包含16-19讲)

8-1流图

  1. 基本块划分算法:找到“首指令”,一个基本块包含一条首指令1到另一条首指令2(不含)。
    首指令寻找算法:1)程序开始的第一条指令;2)跳转语句的目标指令;3)紧跟跳转语句后面的一条语句(实际上这是另一个分支的开始)
  2. 流图:就是程序控制流的形象表示,其节点是基本块。基本快之间的指向连线根据语义(或者他给出的算法)计算即可。

8-4基本块的优化

  1. 基本块的优化是局部优化,首先将基本块转化成DAG图才可以优化。
  2. DAG图可以自动发现公共子表达式、删除无用代码(根节点的值是不再被引用的值,如果在该基本块外也不被引用,就可以删除该根节点 <不活跃根节点> ;以此递归)。
  3. 构造DAG图,是实现局部优化的手段。根据DAG图,我们可以进行2中描述的局部优化。该过程称为DAG基本块的重组。
  4. 数组元素比较特别,可以参考下PPT,有个“杀死”原则。

做题笔记

  1. 【直接短语 VS. 素短语】
    1.1 直接短语:只有父子两代的一个子树,它的叶子节点从左到右的排序,就是直接短语。
    1.2 素短语:包含终结符的短语,且该短语中不再含有其他素短语。(仔细思考发现不是直接短语的子集,可以超过父子两代,如果都是非终结符推导的话。)
    1.3 句柄:一个句型的分析树中最左面的直接短语
  2. LR(1)中的展望符(搜索符),就是产生式左部FOLLOW集的一个真子集,是对SLR(1)方法的精细化。计算方法是,在该产生式中,FIRST(β<自生的> α<继承的>)
  3. LR(0), SLR(1), LR(1)的分析表几乎类似,只是逐渐加强规约的条件,减少冲突。LR(0)中遇到任何符号都可以规约;SLR(1)中遇到产生式左部的FOLLOW集元素才可以规约;LR(1)中遇到FOLLOW集的子集才可以规约。
  4. 根据题目,“传名”就是传递引用(会改变变量在存储空间中的值)、“传值”就是传递数值(不改变实参值)
  1. 传值调用(call-by-value):主调过程计算实参,并把它们的值放入到形参的存储空间中。(不修改实参值)
  2. 引用调用(call-by-reference又称传地址):主调程序把实参的地址传递给相应的形参。(修改实参值)【当实参为表达式或常数时,先将表达式和常数的值计算出来后,存放到临时单元,然后将临时单元的地址传给形参单元
    (就是一种复杂的传地址方式)】
  3. 复制恢复(copy-restore又称传值结果):被调程序同时接受参数的值和地址,返回的时候按照地址,把修改后的值覆盖实参。(修改实参值)
  4. 传名调用(call-by-name):每当要对某形参进行访问时,就调用THUNK子程序,以获得相应实参地址或值。(修改实参值)
  1. 句型:终结符和非终结符的组合 句子:终结符串
  2. 活前缀就是分析栈中的内容,不包含句柄之后的任何内容(因为一旦包含,那就会被规约)。
  3. 代码优化技术汇总:
1. 删除公共子表达式
2. 复制传播(1会引入2;在复制语句f:= g之后尽可能用g代替f;为其他优化带来机会)
3. 强度减弱
4. 删除无用代码
5. 删除归纳变量(多个变量相互关联同时变化,只保留一个归纳变量)
6. 代码外提(就是CSAPP中学的循环不变式)
7. 合并常量(常量的计算)

你可能感兴趣的:(编译原理)