哈工大编译原理期末复习(完整版)

文章目录


本文PDF下载

本文章中有些图片可能由于图床的防盗链问题导致加载不出来。本文的PDF下载见下方地址,整理不易,麻烦点个小小的赞😘😘😘
https://download.csdn.net/download/m0_50906780/85413560

一.绪论

1.1 什么是编译

将高级语言翻译成汇编语言或机器语言的过程

image-20220501201521833

image-20220501201636845

1.2 编译系统的结构

image-20220501201931017

词法分析:

从左向右逐行扫描源程序的字符,识别出各个单词,确定单词的类型。
将识别出的单词转换成统一的机内表示——词法单元(token)形式
token:< 种别码,属性值 >

语法分析:

语法分析器(parser)从词法分析器输出的token序列中识别出各类短语,并构造语法分析树(parse tree)

image-20220502085734125

语义分析:

  • 收集标识符的属性信息
  • 语义检查

image-20220502090010585

image-20220502090032974

image-20220502090138637

中间代码生成器:

  • 三地址码:类似于汇编语言的指令序列组成,每个指令最多有三个操作数(operand)
  • 语法结构树/语法书

image-20220502090324872

三地址指令的表示:

  • 四元式 :(op, arg1, arg2, result)
  • 三元式: (op, arg1, agr2)
  • 间接三元式:

目标代码生成器:

目标代码生成以源程序的中间表示形式作为输入,并把它映射到目标语言;(中间形式 ==> 目标语言
目标代码生成的一个重要任务是为程序中使用的变量合理分配寄存器

代码优化

1.3 编译程序的生成

不用画T形图

image-20220502090823762

image-20220502091045265

1.4 为什么要学习编译原理

1.5 编译技术的应用

二、语言及其文法

2.1 基本概念

串:有穷符号(symbol) 序列

串的连接:xy

串的n次幂:将n个s连接起来

字母表:有穷符号集合

字母表的乘积:笛卡尔积

字母表的n次幂:长度为n的符号串构成的集合

字母表的正闭包:长度正数的符号串构成的集合

字母表的克林闭包:任意符号串(长度可以为零)构成的集合

2.2 文法的定义

image-20220502094115021

G = (VT , VN , P , S )

VT = { apple, boy, eat, little }

VN = { 句子, 名词短语, 动词短语, 名词, … }

P : 产生式集合

S:开始符号

2.3语言的定义

推导:用产生式的右部替换产生式的左部 (生成语言

规约:(识别语言

image-20220502095203647

image-20220502095701525

image-20220502095716445

由文法G的开始符号S推导出的所有句子构成的集合称为文法G生成的语言,记为L(G )。

2.4 文法分类

image-20220502100307236

image-20220502100417187

image-20220502100458052

image-20220502100520806

image-20220502100613375

2.5 CFG的分析树

image-20220502100839434

image-20220502101111514

二义性文法:如果一个文法可以为某个句子生成多棵分析树,则称这个文法是二义性的

image-20220502101308981

三、词法分析

3.1 单词的描述

  • 正则表达式:描述正则语言

image-20220503103542961

3.2 单词的识别

  • 有穷自动机:➢这类系统具有一系列离散的输入输出信息和有穷数目的
    内部状态(状态:概括了对过去输入信息处理的状况),系统只需要根据当前所处的状态和当前面临的输入信息就可以决定系统的后继行为。每当系统处理了当前的输入后,系统的内部状态也将发生改变

    image-20220503103817679

image-20220503103835196

image-20220503103912266

DFA(确定的有穷自动机)

输入+ 状态 ==> 一个状态

image-20220503105740582

NFA(非确定的有穷自动机)

输入 + 状态 ==> 多个状态

image-20220503110003330

image-20220503110049129

DFA和NFA可以识别相同的语言

正则文法 <=> 正则表达式 <=> FA

带有 ε-边 的NFA

image-20220503110604949

image-20220503110735981

image-20220503110745849

image-20220503110952770

image-20220503111607175

把DFA的状态改成一个NFA可以到达的状态集合就可以了

子集构造法

image-20220503111802093

image-20220503112049228

image-20220503112119713

image-20220503112147635

3.3 词法分析阶段的错误处理

➢词法错误检测

➢如果当前状态与当前输入符号在转换表对应项中的信息为空,而当前状态又不是终止状态,则调用错误处理程序

错误处理: 查找已扫描字符串中最后一个对应于某终态的字符 ➢如果找到了,将该字符与其前面的字符识别成一个单词。 然后将输入指针退回到该字符,扫描器重新回到初始状态,继续识别下一个单词,如果没找到就采用错误恢复

**错误恢复:**采用==“恐慌模式”==,从剩余的输入中不断删除字符,直到词法分析器能够在剩余输入的开头发现一个正确的字符为止

四、语法分析

语法分析的主要任务是根据给定的文法,识别输入句子的各个成分,从而构造出句子的分析树

大部分程序设计语言的语法构造可以用CFG(上下文无关文法)来描述,CFG以token作为终结符

自顶向下的分析(推导)自底向上分分析(归约)这两个方法只能给出某些文法子类,但其表达能力足以描述现代大多语言的语法构造

4.1 自顶向下的分析

可以看成是从开始的S推导出串w的过程

  • 最左推导:总是选择每个句型的最左非终结符进行替换

  • image-20220504101458275

  • image-20220504101423439

  • 最右推导:总是选择每个句型的最右非终结符进行替换

  • image-20220504101522314

    自底向上的分析中,最左归约成为规范归约,最右推导称为规范推导(自底向上,右导左归)

    自顶向下的语法分析采用最左推导的方式

    ➢总是选择每个句型的最左非终结符进行替换 ➢根据输入流中的下一个终结符,选择最左非终结符的一个候选式

    自顶向下语法分析(递归下降分析)

    image-20220504102857152

同一非终结符的多个候选式存在共同前缀,会出现回溯现象,左递归文法(A->Aa)会使递归下降分析器陷入无限循环

消除直接左递归(引入一些非终结符和空产生式),把左递归转换成右递归

image-20220504104525985

image-20220504104535863

image-20220504105936445

image-20220504111946379

image-20220504112150207

image-20220506201840791

image-20220506201847981

预测分析是递归下降分析技术的一个特例,通过在输入中向前看固定个数符号来选择正确的A-产生式,向前看K个输入符号的预测分析器——LL(k)文法类,预测分析不需要回溯,是一种确定的自顶向下分析方法

4.2 预测分析法

LL(1) 文法

从文法开始符号出发,在每一步推导过程中根据当前句型 的最左非终结符A当前输入符号a,选择正确的A-产生 式。为保证分析的确定性,选出的候选式必须是唯一的。

  • S_文法(每个产生式的右部都以终结符开始,同一非终结符的各个候选式的首终结符都不同,S文法不含ε产生式

    image-20220506202908060

  • q_文法 (每个产生式的右部或为ε ,或以终结符开始 ➢具有相同左部的产生式有不相交的可选集 。)

  • LL(1)文法:当且仅当G的任意两个具有相同左部的产生式A -> a|b 满足不存在终结符a使得a和b都能推导出以a开头的串,a和b至多有一个可推导出空。(同一非终结符的各个产生式的SELECT集互不相交

  • FOLLOW集:FOLLOW(A)(在某个句型中紧跟在A后边的终结符a的集合)

  • SELECT集:SELECT(A->b)(产生式A→β的可选集是指可以选用该产生式进行推导时对应的输入符号的集合,SELECT( A→aβ ) = { a },SELECT( A→ε )=FOLLOW( A )

  • FIRST集:FIRST(α)(➢给定一个文法符号串α, α的串首终结符集FIRST(α)被定义为可以从α推导出的所有串首终结符构成的集合。如果α => ε, 那么ε也在FIRST(α)中。如果X是一个终结符,那么FIRST(X) = {X},非终结符就递归着看,如果 X→ε∈P,那么将ε加入到FIRST( X )中)

  • 计算串X1X2 …Xn的FIRST 集合:先加入X1的FIRST集中的非空符号,如果有空,则依次加入下一个Xi的的所有非空符号,直到没有空为止

  • image-20220506205018656

  • 计算SELECT可选集:如果包含空集,select集等于first集;如果不包含,select集等于first集并上它的follow集

  • 计算非终结符的FOLLOW集: 把$放入到FOLLOW(S)中;如果有A->aBb,FIRST(b)中除ε之外的所有符号都在FOLLOW(B)中,如果存在一个产生式A→αB,或存在产生式A→αBβ且 FIRST ( β ) 包含ε,那么 FOLLOW( A )中的所有符号都在 FOLLOW( B )中

  • 下面是求各个集的例子

  • image-20220506203034938

image-20220506204151361

image-20220506204159936

只有FIRST集中会有空串!!!!

只有FIRST集中会有空串!!!!

只有FIRST集中会有空串!!!!

只有FIRST集中会有空串!!!!

image-20220508093051620

求follow集的讲解:

对于每个非终结符号,我们都可以求出其follow集:

根据(1),首先将 加 入 到 f o l l o w ( E ) 中 , 即 f o l l o w ( E ) = { 加入到follow(E)中,即follow(E)={ followEfollowE=},由⑤可知,)也应该在follow(E)中,即follow(E)={$,)};

对于E’,根据规则(3)以及产生式①,应该将follow(E)加入到follow(E‘)中,即follow(E’)={$,)};

对于T,根据规则(2)以及产生式①,应该将first(E’)加入到follow(T)中,即follow(T)={+},根据规则(3),由于first(E’)包含ε,所以应该将follow(E’)加入到follow(T)中,即follow(T)={+,$,)};

对于T’,根据规则(3)以及产生式③,应该将follow(T)加入到follow(T‘)中,即follow(T’)={+,$,)};

对于F,根据规则(2)以及产生式③,应该将first(T’)加入到follow(F)中,即follow(F)={},根据规则(3),由于first(T’)包含ε,所以应该将follow(T’)加入到follow(F)中,即follow(F)={,+,$,)};

image-20220508093330753

select集有终结符号直接加进去,有空串的情况就直接加follow集

LL(1)的分析方法

递归的预测分析法:在递归下降分析中,根据预测分析表进行产生式的选择(根据式子写对应的过程代码)

image-20220508093954750

image-20220508094005550

procedure PROGRAM(TOKEN);

​ begin

​ if TOKEN ≠ ‘xxx’ then ERROR;

​ GETNEXT(TOKEN);

​ 左部名(TOKEN);

​ end

非递归的预测分析法:维护一个栈结构来模拟最左推导过程

image-20220508095051116

image-20220508095434636

预测分析表是根据相应符号的产生式的SELECT集采取并运算构建的

如果栈顶符号和剩余输入是相同的终结符,则把它们弹栈删除

输出相应结果和把相应结果压入栈中是同时进行的(在同一行上)

image-20220508100322312

预测分析法实现步骤:

1)构造文法

2)改造文法:消除二义性、消除左递归、消除回溯

3)求每个变量的FIRST集FOLLOW集,从而求得每个候选式的SELECT集

4)检查是不是 LL(1) 文法(同一非终结符的各个产生式的SELECT集互不相交)。若是,构造预测分析表

5)对于递归的预测分析,根据预测分析表为每一个非终结符编写一个过程;对于非递归的预测分析,实现表驱动的预测分析算法

预测分析中的错误检测

➢两种情况下可以检测到错误

​ ➢栈顶的终结符和当前输入符号不匹配

​ ➢栈顶非终结符与当前输入符号在预测分析表对应项中的信息为空

预测分析中的错误恢复

➢恐慌模式

​ ➢忽略输入中的一些符号,直到输入中出现由设计者选定的同步词法单元(synchronizing token)集合中的某个词法单元

​ ➢其效果依赖于同步集合的选取。集合的选取应该使得语法分析器 能从实际遇到的错误中快速恢复

​ ➢例如可以把FOLLOW(A)中的所有终结符放入非终结符A的同步 记号集合

➢如果终结符在栈顶而不能匹配,一个简单的办法就是弹出此终结符

image-20220508101126883

如果是空,忽略输入的a,如果是synch,弹出栈顶的非终结符A

如果栈顶的终结符和输入符号不匹配,则弹出栈顶的终结符(想想它俩如果相同的话,会同时把他们俩都删除掉)

4.3 自底向上的分析

将输入串w归约为文法开始符号S

自顶向下采用最左推导自底向上采用最左规约

​ ➢移入-归约分析(Shift-Reduce Parsing)

栈内符号串 + 剩余输入 = 规范句型

image-20220508105411646

每次规约的符号串被称为句柄

image-20220508105443685

移入规约的工作过程

➢在对输入串的一次从左到右扫描过程中,语法分析器将零个或多个输入符号移入到栈的顶端,直到它可以对栈顶的一个文法符号串β进行归约为止 ➢然后,它将β归约为某个产生式的左部 ➢语法分析器不断地重复这个循环,直到它检测到一 个语法错误,或者栈中包含了开始符号且输入缓冲区为空(当进入这样的格局时,语法分析器停止运行, 并宣称成功完成了语法分析)为止

移入规约分析器课采取的四种动作(移入、规约、接收、报错

image-20220510081255144

每次规约的符号串被称为句柄

存在的问题:错误的识别了句柄

image-20220510082646869

4.4 LR分析法(无二义性)

LR文法(Knuth, 1963) 是最大的、可以构造出相应 移入-归约语法分析器 的文法类

L:对输入进行从左到右的扫描

R:反向构造出一个最右推导序列

LR(k)分析:需要向前查看k个输入符号的LR分析,k = 0 和 k = 1 这两种情况具有实践意义,当省略(k)时,表示k =1

关键就是要正确地识别句柄

image-20220510083151809

image-20220510083222415

image-20220510084254282

sa:将符号a、状态n压入栈

rn:用第n个产生式进行规约

image-20220510085152226

一开始是只有 0 和 $ ,0遇到b把 4和b给压入,之后再输入进来a,4号状态遇到a使用③进行规约,规约成B,之后0号遇到B,看GOTO表会把2号状态压进来。

个人总结:看状态号和输入的符号进行相应的压栈操作,如果遇到规约操作,把右部的终结符换成非终结符,把原来状态号删掉,再去看GOTO,压入新的状态号

**LR(k)分析**:需要**向前查看k个输入符号**的LR分析,k = 0 和 k = 1 这两种情况具有实践意义,当省略(k)时,表示k =1

构造给定文法的LR分析表:

➢LR(0)分析

image-20220510093642094

* 在左边,移进项目
* 在中间,待约项目
* 在右边,规约项目
错误!!!
还要去看是终结符还是非终结符
  • ➢ 后继项目(Successive Item):同属于一个产生式的项目,但圆点的位置只相差一个符号, 则称后者是前者的后继项目, 比如 A→α· Xβ的后继项目是A→αX·β

image-20220510093803873

增广文法为了使文法开始符号仅出现在一个产生式的左边,从而使得分析器只有一个接受状态

image-20220510094137391

每个项目集闭包对应着自动机的一个状态,从初始状态到某一状态的路径对应的符号序列 代表着某一时刻分析栈中的内容

image-20220510094346529

状态图画法总结:初始状态,各个表达式在左部加上·,之后根据 · 后面的符号进行状态的前进,前进后如果 · 后面是非终结符,则要加上非终结符对应的移进项目产生式。ACTION中是终结符和$;GOTO中是非终结符

image-20220510095402539

image-20220510103353086

image-20220510103414415

image-20220510104003724

不是所有CFG都能用LR(0)方法进行分析,CFG不总是LR(0)文法,其中会产生移进/规约冲突还有规约/规约冲突

➢SLR分析

image-20220511192411199

出现了冲突

image-20220513093917693

image-20220511192452059

SLR分析会根据下一个输入符号的归属,来判断是规约还是移进

如果是目前可移进的下一个符号,就采用移进

如果是FOLLOW(B)里面的,就采用规约

image-20220512090351358

如果给定的SLR分析表不存在有冲突的动作,就称为SLR文法

➢LR(1)分析

因为SLR中存在着冲突

image-20220512090618562

SLR只是简单地考察下一个输入符号b是否属于与归纳项目A->a相关联的FOLLOW(A)

但是: b∈FOLLOW(A) <== 规约a (可推出)

b∈FOLLOW(A) !=> 规约a (不可推出)

image-20220512091104283

在不同的位置,A会要求不同的后继符号,A的后继符集合是FOLLOW(A)的子集

image-20220512091517408

LR(1)多了一个展望符,表示在当前状态下A后面必须要紧跟的终结符

[A --> αβ,a] 当β等于空的时候会用到展望符a

image-20220512092023640

image-20220512093847756

直到写到·后面是终结符为止

image-20220512114600891

image-20220512094335681

如果除展望符外,两个LR(1)项目集是相同的,则称这两个项目是同心

image-20220512104012878

如果LR(1)分析表中没有语法分析动作冲突, 那么给定的文法就称为LR(1)文法

➢LALR分析

image-20220512111158749

【同心:如果除展望符外,两个LR(1)项目集是相同的,则称这两个LR(1)项目集是同心的】

image-20220512114418923

image-20220512114759946

合并同心项集不会产生移进-归约冲突,但会产生归约-归约冲突

image-20220512111534481

合并同心项集的时候会产生归约-归约的冲突

image-20220512114925552

LALR分析法可能会作多余的规约动作,但绝不会作错误的的移进操作

LALR(1)的特点

形式上与LR(1)相同
大小上与LR(O)/SLR相当
分析能力介于SLR和LR(1)二者之间
SLR<LALR(1)<LR(1)
合并后的展望符集合仍为FOLLOW集的子集

每个二义性文法都不是LR的!!!!

每个二义性文法都不是LR的!!!!

每个二义性文法都不是LR的!!!!

但是某些类型的二义性文法在语言的描述和实现中很有用,更简短,更自然

image-20220512115406599

image-20220512115620234

遇到错误应该采用恐慌模式或者短语层次的错误恢复

image-20220513091705688

image-20220513091727911

image-20220513092002562

4.5总结:

  • SLR文法:

    image-20220513100240161

  • LR(1)文法

    image-20220513100352541

  • LALR(1)文法

    image-20220513100433096

image-20220513100526451

五、语法制导翻译

语法制导翻译使用CFG来引导对语言的翻译, 是一种面向文法的翻译技术

image-20220513105755656

语法制导翻译【语法分析、语义翻译(语义翻译、中间代码生成)】

为CFG中的文法符号设置语义属性,用来表示语法成分对应的语义信息

需要使用与文法符号所在产生式(语法规则)相关联的语义规则来计算分析树中各个结点对应的语义属性值

语义规则语法规则联系起来有两个概念:

  • 语法制导定义(SDD)
  • 语法制导翻译方案(SDT)

语法制导定义SDD

  • 文法符号 <==> 一个语义属性集合

  • 产生式 <==> 一组语义规则(用于计算各个文法符号的属性值)

    image-20220513111156232

语法制导翻译方案SDT

  • 在产生式右部嵌入了语义动作的CFG

  • image-20220513111305469

  • SDD

    ➢是关于语言翻译的高层次规格说明

    ➢隐蔽了许多具体实现细节,使用户不必显式地说明翻译发生的顺序

  • SDT

    ➢可以看作是对SDD的一种补充,是SDD的具体实施方案

    显式地指明了语义规则的计算顺序,以便说明某些实现细节

5.1 语法制导定义SDD

文法符号——语义属性集合

产生式——一组语义规则

  • 综合属性(子节点结点本身)(向下)

    • 通过子节点结点本身的属性值来定义
    • 终结符可以具有综合属性。终结符的综合属性值是由词法分析器提供的词法值,因此在SDD中没有计算终结符属性值的语义规则
  • 继承属性(父节点兄弟节点结点本身)(向上)

    • 只能通过父节点兄弟节点结点本身的属性值来定义
    • 终结符没有继承属性。终结符从词法分析器处获得的属性值被归为综合属性值

image-20220513113104123

image-20220513121723783

属性文法

一个没有副作用的SDD有时也称为属性文法

属性文法的规则仅仅通过其他属性值常量来定义一个属性值

SDD为CFG中的文法符号设置语义属性。对于给定的输入串x,应用语义规则计算分析树中各结点对应的属性值,语义规则建立了属性之间的依赖关系(依赖图),在对语法分析树节点的一个属性求值之前,必须首先求出这个属性值所依赖的所有属性值

image-20220513122459338

image-20220513122648746

image-20220513122915833

➢对于只具有综合属性的SDD ,可以按照任何自底向上的顺序计算它们的值

➢对于同时具有继承属性综合属性的SDD,不能保证存在一个顺序来对各个节点上的属性进行求值

image-20220513133906481

5.2 S-属性定义与L-属性定义

给定一个SDD,很难确定是否存在某棵语法分析树,使得SDD的属性之间存在循环依赖关系

但是存在S-SDDL-SDD,它们能够保证对每棵语法分析树都存在一个求值顺序,因为它们不允许 产生带有环的依赖图,它们还可以和自顶向下自底向上的语法分析过程一起高效地实现

S-SDD:仅仅使用综合属性的SDD,其可以按照语法分析树节点的任何自底向上顺序来计算它的各个属性值

L-SDD:在一个产生式所关联的各属性之间, 依赖图的边可以从左到右,但不能从右到左 (因此称为L属性的,L是Left的首字母)。一个SDD是L-SDD,当且仅当它的每个属性要么是一个综合属性,要么是满足如下条件的继承属性

假设存在一个产生式 A->X1X2...Xn, Xi的继承属性仅依赖于下列属性:
   * A的继承属性
   * 产生式中Xi左边的符号 X1 , X2 , … , Xi-1 的属性
   * Xi本身的属性,但Xi的全部属性不能在依赖图中形成环路

每个S-SDD都是L-SDD

image-20220513135656752

5.3 语法制导翻译方案SDT

语法制导翻译方案(SDT)是在产生式右部嵌入了程序片段(语义动作)的CFG

image-20220513135720623

SDT可以看作是SDD的具体实施方案

SDT可在语法分析过程中实现S-SDDL-SDD

  • 基本文法可以使用LR分析技术,且SDD是S属性

  • 基本文法可以使用LL分析技术,且SDD是L属性

将S-SDD转换为SDT:将每个语义动作都放在产生式的最后

image-20220513140642955

如果一个S-SDD的基本文法可以使用LR分析技术, 那么它的SDT可以在LR语法分析过程中实现,当归约发生时执行相应的语义动作

image-20220513140936965

image-20220513140911658

image-20220513141022235

image-20220513143211968

将L-SDD转换为SDT

  • 将计算某个非终结符A的继承属性的动作插入到产生式右部中紧靠在A的本次出现之前的位置上
  • 将计算一个产生式左部符号的综合属性的动作放置在这个产生式右部的最右端

image-20220513152234742

如果一个L-SDD的基本文法可以使用LL分析技术, 那么它的SDT可以在LL或LR语法分析过程中实现

​ ➢在非递归的预测分析过程中进行语义翻译

​ ➢在递归的预测分析过程中进行语义翻译

​ ➢在LR分析过程中进行语义翻译

5.4 L-属性定义的自顶向下翻译

​ ➢在非递归的预测分析过程中进行语义翻译

image-20220513152534423

image-20220513152552213

image-20220513152910494

注意向栈中加入的时候是这样子加的

T-》M{a3}N{a4}

在栈中先弹出T,再把M,Msyn,{a3},N,Nsyn,{a4}加进去,之后可以根据栈中指针及相对位置来进行相关代码的书写和计算。

如果栈顶(最左边)是非终结符,就按展开式一直展开直到匹配上终结符,都有综合属性,有继承属性的写在本身的下面。

如果栈顶是综合属性的属性值Fsyn(综合记录出栈),也是要弹出,但要看看后面是否会用到它;如果栈顶是继承属性的属性值F.inh(式子为F.inh = T.inh * F.inh),也是要弹出,会用到它的时候把它放到对应的语义动作下面

如果栈顶是动作,就执行该动作

执行代码:

image-20220513165010099

image-20220513165017625

image-20220513165027680

属性:是对应符号里面存储的属性

执行代码:如果是对应的符号则为弹出符号或展开符号时对其继承属性要执行的动作代码;如果是对应的动作则为执行动作时要执行的动作代码(弹出属性时,如果属性在后面还要使用,则把它复制到对应的动作下面)

top的变换:弹出栈(比如属性或者动作)top = top - 1;弹出栈(比如展开一个非终结符)top = top - 1 + 展开后的top增加量

➢在递归的预测分析过程中进行语义翻译

image-20220513172848892

image-20220513172956891

image-20220513173012185

5.5 L-属性定义的自底向上翻译

​ ➢在LR分析过程中进行语义翻译

(修改LL文法为基础的L-SDD,在LR分析中可以用)

给定一个以LL文法为基础的L-SDD,可以修改这个文法,并在LR语法分析过程中计算这个新文法之上的SDD

image-20220513173602058

把语义动作都换成产生空终结符的产生式,语义动作执行和原来相同的任务。这样所有语义动作就都可以移动到式子最右边,转化成类似于S-SDT的形式。

这样修改后的SDT,所有语义动作都位于产生式的末尾了

image-20220513175034515

image-20220513175044412

image-20220513175141353

六、中间代码生成

6.1 声明语句的翻译

收集标识符类型等属性信息,并为每一个名字分配一个相对地址

名字的类型相对地址保存在相应的符号表记录

image-20220514075620770

image-20220514075637698

➢指针构造符pointer

​ ➢ 若T 是类型表达式,则 pointer ( T ) 是类型表达式,它表示一个指针类型

➢笛卡尔乘积构造符

​ ➢ 若T1 和T2是类型表达式,则笛卡尔乘积T1 X T2 是类型表达式

➢函数构造符→

​ ➢ 若T1、T2、…、Tn和R是类型表达式,则T1XT2 X…XTn → R是类型表达式

➢记录构造符record

​ ➢ 若有标识符N1、N2、…、Nn与类型表达式T1 、T2、…、Tn, 则 record ( ( N1 X T1 )  ( N2 X T2 )X …X ( Nn X Tn )) 是一个类型表达式

image-20220514080233284

  • 对于声明语句,语义分析主要就是收集标识符的类型等属性信息,并为每一个名字分配一个相对地址
    • 从类型表达式可以知道该类型在运行时刻所需的存储单元数量,称为类型的宽度
    • 在编译时刻,可以使用类型的宽度,为每一个名字分配一个相对地址
  • 名字的类型相对地址信息保存在相应的符号表记录中

image-20220514082318063

这是一个L属性定义的SDT,如果L-SDD其基础文法是LL(1)文法具有相同左部的产生式的SELECT可选集是否相同),那么可以在自顶向下的过程中实现这个SDT

image-20220514082545161

6.2 赋值语句的翻译

6.2.1 简单赋值语句的翻译

image-20220514082818091

赋值语句的SDT的主要任务就是生成对表达式求值的三地址码

image-20220514083000930

||是连接的意思,观察到非终结符的code都是后面的code按顺序连接起来,化简,化简成了增量翻译,在增量方法中,gen不仅要构造出一个新的三地址指令,还要把它添加到至今为止已生成的指令序列之后

image-20220514083547787

image-20220514083817790

image-20220514085923352

new temp 会产生一个临时变量

6.2.2 数组引用的翻译

数组引用 ==> 三地址码

关键:数组元素的寻址

image-20220514090717732

image-20220514090810768

image-20220514090942706

image-20220514091033876

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s9yv5XkW-1652919086756)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220514091048573.png)]

image-20220514091130016

6.3 控制语句的翻译

image-20220514091506986

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dnSQ4M0h-1652919086757)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220514091645600.png)]

image-20220514091702789

newlabel():生成一个用于存放标号的新的临时变量L,返回变量地址(只是确定了S的后继指令标号的存放地址,但这个标号的具体值要等S分析完毕之后的语义动作中填入,先预定一个房间)

label(L):将下一条三地址指令的标号存放到地址L中,(完成继承属性的填写)

image-20220514092122659

继承属性B.true和B.false放在B之前,要用newlabel函数生成两个用于存放标号的临时变量,并将函数的返回地址分别赋值给B.true和B.false

image-20220514093749199

&& || !被翻译成跳转指令运算符本身不出现在代码中,布尔表达式的值是通过代码序列中的位置来表示的

控制流翻译的例子:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FQE2Zura-1652919086759)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220514095227186.png)]

6.4 回填

➢基本思想

➢生成一个跳转指令时,暂时不指定该跳转指令的目标标号。这样的指令都被放入由跳转指令组成的列表中。同 一个列表中的所有跳转指令具有相同的目标标号。等到能够确定正确的目标标号时,才去填充这些指令的目标标号

➢makelist( i )

​ ➢创建一个只包含i的列表,i是跳转指令的标号,函数 返回指向新创建的列表的指针

➢merge( p1 , p2 )

​ ➢将 p1 和 p2 指向的列表进行合并,返回指向合并后的 列表的指针

**➢backpatch( p, i )** 

​ ➢将 i 作为目标标号插入到 p所指列表中的各指令中

image-20220514100451019

nextquad是即将生成的下一条指令的标号

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E8cKuMcm-1652919086759)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220514100922490.png)]

M就是为了记录下B2的第一条指令的标号

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lViJNlJk-1652919086760)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220514101521709.png)]

控制流语句的回填

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZR29Rg65-1652919086760)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220514103619680.png)]

➢S.nextlist:指向一个包含跳转指令的列表,这些指令最终获得的目标标号就是按照运行顺序紧跟在S代码之后的指令的标号

image-20220514104318333

根据示意图,我们要用S1的第一条指令来回填B.truelist,要用S2的第一条指令来回填B.falselist,需要记录下 S1、S2的第一条指令的标号。在S1之后要生成跳转指令,因此我们在S1之后设置一个标记非终结符n,用于生成这条跳转指令

image-20220514104827096

image-20220514104840147

image-20220514105334373

image-20220514105347479

6.5 switch语句的翻译

image-20220514110151436

image-20220514110221394

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZfxoCIIH-1652919086763)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220514110244502.png)]

6.6 过程调用语句的翻译

call + 过程的名字id + (Elist即过程的参数表达式列表)

image-20220514111749596

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cni5PzTr-1652919086764)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220514111828921.png)]

七、运行存储分配

7.1存储组织

一个目标程序(代码区+数据区

静态存储分配(编译时刻)

动态存储分配(运行时刻,式和式)

image-20220514224808193

活动记录:每运行一次所需要管理的信息的存放区域

image-20220514225003172

image-20220514225127001

7.2 静态存储分配(编译)

image-20220514225251288

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zv7hWORH-1652919086765)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220514225416328.png)]

常用的静态存储分配方法:

  • 顺序分配法

    ➢按照过程出现的先后顺序逐段分配存储空间

    ➢各过程的活动记录占用互不相交的存储空间

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-42exf8wm-1652919086765)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220514225543235.png)]

  • 层次分配法

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iUNDSZUg-1652919086766)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220514225822457.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AcK7rABE-1652919086766)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220514225934490.png)]

7.3 栈式存储分配(运行)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5NRtTCcX-1652919086766)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220514230159894.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CFIQhPfq-1652919086767)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220514230325374.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q9dsPSpB-1652919086767)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220514231333133.png)]

image-20220514230423706

image-20220514231739542

调用序列返回序列

➢ 调用序列

​ ➢实现过程调用的代码段。为一个活动记录在栈中分配空间, 并在此记录的字段中填写信息

➢ 返回序列

​ ➢恢复机器状态,使得调用过程能够在调用结束之后继续执行

➢ 一个调用代码序列中的代码通常被分割到调用过程(调用者) 和被调用过程(被调用者)中。返回序列也是如此

image-20220515080530661

image-20220515080712029

image-20220515080837979

编译时刻不能确定大小的对象——>

但如果是过程的局部对象——>运行时刻中(可以避免对它们的空间进行垃圾回收,也就减少 了相应的开销)

只有一个数据对象局部于某个过程,且当此过程结束时它 变得不可访问,才可以使用栈为这个对象分配空间

image-20220515090316119

7.4 非局部数据的访问

image-20220515090410422

  • 访问链:

image-20220515090748524

image-20220515091229972

image-20220515091444279

image-20220515091702868

  • display表

    image-20220515091900729

image-20220515091927060

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4s35JC1P-1652919086772)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220515092018480.png)]

例子

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w1R3Z2Sh-1652919086773)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220515092038688.png)]

7.5 参数传递

  • 形式参数

    在过程定义中使用的参数

  • 实际参数

    调用过程时使用的参数

  • 形参和实参相关联的几种方法

    ➢ 传值(Call- by-Value)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ECatkq8a-1652919086773)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220515092450695.png)]

    ➢ 传地址(Call- by-Reference)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oQizzHVO-1652919086773)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220515092600030.png)]

    ➢ 传值结果(Call- by-Value-Result)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Rh8fd8eQ-1652919086774)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220515092708155.png)]

    ➢ 传名(Call- by-Name)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vvXtW2A0-1652919086774)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220515092829377.png)]

7.6 符号表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ndbmKsA9-1652919086774)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220515092917057.png)]

符号表上的主要操作:

➢声明语句的翻译(定义性出现)

​ ➢填、查

➢可执行语句的翻译(使用性出现)

​ ➢查

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xYyEgRbL-1652919086774)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220515093524890.png)]

image-20220515093737758

image-20220515093708363

image-20220515093824457

image-20220515095058948

image-20220515095116173

image-20220515095121825

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yvs5TGDr-1652919086778)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220515095210132.png)]

八、代码优化

8.1 流图

image-20220515100204388

image-20220515100611787

  • 第一个三地址指令
  • 转移指令的目标指令(要跳到的地方的第一个指令,不是goto语句,是要goto的地方)
  • 紧跟在转移指令之后的指令

image-20220515100754202

从第一条指令开始,先找goto要到的地方,再加上紧跟在goto后面的指令

image-20220515101830081

image-20220515102005290

image-20220515102111714

以基本块为单位,根据每个基本块的最后一条语句进行分析,可以画出流图

8.2 优化的分类

机器无关优化 ➢针对中间代码

机器相关优化 ➢针对目标代码

局部代码优化 ➢单个基本块范围内的优化

全局代码优化 ➢面向多个基本块的优化

常见的优化方法:

  • ➢删除公共子表达式

    image-20220515102553521

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cqNMuUof-1652919086783)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220515103101204.png)]

image-20220515102823416

  • ➢删除无用代码

image-20220515104626398

➢ 无用代码(死代码Dead-Code ) :其计算结果永远不会被使用的语句

image-20220515104730885

  • ➢常量合并

image-20220515104813435

  • ➢代码移动

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LErCLiyi-1652919086786)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220515105058755.png)]

image-20220515105135806

  • ➢强度削弱

image-20220515105202175

➢归纳变量

​ ➢对于一个变量x ,如果存在一个正的或负的常数c使得每次x被赋值时它的值总增加c ,那么x就称为归纳变量(Induction Variable) 归纳变量可以通过在每次循环迭代中进行一次简单的增量运算(加法或减法)来计算

image-20220515105502004

  • ➢删除归纳变量
  • image-20220515105632566

8.3 基本块的优化

➢很多重要的局部优化技术首先把一个基本块转换成为 一个无环有向图(directed acyclic graph,DAG)

image-20220515110057322

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HumxUx7M-1652919086789)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220515110213907.png)]

image-20220515110249188

image-20220515110741254

image-20220515110820630

image-20220515110941279

首先删除没有附加活跃变量的根节点:G

当一个定值变量表中存在多个定值变量时,我们只需生成一条三地址指令,并将计算结果赋给其中的一条变量,我们倾向于赋给一个活跃变量,删除:M,J,IH

再根据DAG重新编写基本块,删除掉的变量语句不用写,一直是常量的值用常量区代替,处理后的如蓝色小方块所示

8.4 数据流的分析

➢一组用来获取程序执行路径上的数据流信息的技术

➢数据流分析应用

​ ➢到达-定值分析 (Reaching-Definition Analysis)

​ ➢活跃变量分析 (Live-Variable Analysis)

​ ➢可用表达式分析 (Available-Expression Analysis)

image-20220515112250676

image-20220515112932649

到达定值分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wLNxFSjY-1652919086792)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220515113721649.png)]

看di到Bj的过程中,di中的变量是否有被重新定值,如果重新定值,则被杀死

image-20220515114113688

image-20220515114128036

image-20220515114142110

image-20220515114255678

image-20220515114535624

image-20220515114703098

image-20220515114724356

image-20220515114746961

迭代到不发生改变为止,最后可以根据各个基本块的IN值来得到各个入口块的到达定值信息,可以完成上面的√×表

ud链,引用-定值链

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f9tQkuzz-1652919086797)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220515114833270.png)]

活跃变量分析(逆向数据流问题)

➢活跃变量(会引用x在p的值)

➢对于变量x和程序点p,如果在流图中沿着从p开始的某条路径引用变量x在p点的值,则称变量x在点p是活跃(live)的,否则称变量x在点p不活跃(dead)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iGzD5Twi-1652919086797)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220515145927458.png)]

在程序中的各个基本块中都没有引用变量a的值,因此a在各个基本块的出口处都不是活跃的

i从B1出来到下一次改变的路径上在B2处被引用,所以i在b1的接口处是活跃的;i从B2出来到下一次改变的路径上在没有被引用,所以是不活跃的,同理可以分析出来B3和B4

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GtERSkIe-1652919086798)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220515151717293.png)]

image-20220515151837907

image-20220515152004778

​ 对于B2:i和j的首次出现是以引用形式出现的,所以把它们加入到useB2中去

​ 对于use(在该语句块中首次出现是以引用形式出现)

​ 对于def(在该语句块中首次出现是以定义形式初始)

image-20220515152627323

image-20220515152641326

OUT[B] = 后继所有结点的IN值的并集

IN[B] = useB 加上 (OUT[B] - def[B])

image-20220515153507952

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DfEGMZFr-1652919086801)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220515153829754.png)]

可用表达式分析

image-20220515154039693

image-20220515154149579

image-20220515154207461

image-20220515154230160

e_genB:添加表达式的右部,删除与表达式左部相关的式子

e_killB:添加表达式的左部相关的式子,删除表达式的右部

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n4XWJ7Fp-1652919086804)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220515154258497.png)]

IN[B] = 所有前驱的OUT集的交集

OUT[B] = genB 加上 (IN[B] - killB)

image-20220515154304929

8.5 流图中的循环

image-20220515160146336

image-20220515160244673

主要算IN[B],OUT[B]就是IN[B]再并上自己本身,IN[B]是其所有前驱结点OUT的交,因为是每条路径,所以要取

image-20220515162115895

回边:有一条被支配结点到支配结点的边(被支配 ==> 支配)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZAA7k8Dl-1652919086806)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220515162149880.png)]

自然循环:先把回边的那两个结点加入,再去找可以到被支配结点的结点,从被支配结点的其余前驱按照结点的前驱一个个递归去找即可

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SA9Q8EoK-1652919086806)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220515162739823.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SekiPPxy-1652919086807)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220515162748154.png)]

8.6 全局优化

➢删除全局公共子表达式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DHRcFnB5-1652919086807)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220515163312475.png)]

➢删除复制语句

image-20220515163658233

➢代码移动 (循环不变的检测 + 代码外提)

image-20220515164102549

image-20220515164401228

image-20220515164601232

即想要外提的话:所在块要支配所有出口节点;对X的赋值和引用必须为一对一的关系

➢作用于归纳变量的强度削弱

image-20220515165742036

image-20220515165846914

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v8mUMfMu-1652919086810)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220515170353565.png)]

➢删除归纳变量

image-20220515170944707

image-20220515171139279

九、代码生成

9.1 代码生成器的主要任务

image-20220515231753052

image-20220515231825034

image-20220515231910170

9.2 一个简单的目标机模型

image-20220515232016473

image-20220515232043034

寻址模式

  • image-20220515232155446

  • image-20220515232205338

  • image-20220515232221257

  • image-20220515232247071

  • image-20220515232329908

  • image-20220515232409550

9.3 指令选择

image-20220515234008765

image-20220515234258232

image-20220515234351484

image-20220515234406358

image-20220515234544759

image-20220515234632644

image-20220515235245256

image-20220516073801012

9.4 寄存器的选择

image-20220516073857434

image-20220516074020731

image-20220516074052354

image-20220516074309528

image-20220516074459592

image-20220516074537953

image-20220516074616968

image-20220516075448884

① 先根据指令,先更新寄存器的内容,再更新标识符的内容

② 再根据寄存器的变化删除右部存储在该寄存器的内容(该寄存器有了新的占领者,之前的都不是了)

③ 注意如果是复制语句(x = y)要把两个变量都更新下

④ 结束时,a,d都没有存在对应的地址符下面,说明它们是活跃变量,要加上收尾工作exit,把它们放到对应的地址符下面(ST a,R2)(ST d,R1)

9.5 寄存器选择函数getReg的设计

image-20220516081315783

image-20220516081328794

image-20220516081943299

例子:

➢冗余指令删除

image-20220516082310492

➢控制流优化

➢代数优化

image-20220516082338875

➢机器特有指令的使用

image-20220516082347235

MOOC错题

编译原理之LL(1) 、LR(0)、SLR、LR(1)、LALR文法的对比

(1条消息) 编译原理之LL(1) 、LR(0)、SLR、LR(1)、LALR文法的对比_棉花糖灬的博客-CSDN博客_lr(0)

第一讲、绪论

image-20220505232009386

image-20220505232022551

第二讲、程序设计语言及其文法

image-20220516102320247

三型文法是正则文法

image-20220505232948373

第三讲、词法分析

image-20220519075306288

image-20220519075131997

image-20220505234353846

image-20220505234406392

第四章:语法分析

image-20220519074445072

image-20220519073547864

image-20220519073339741

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CqviwpQP-1652919086832)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220519072700423.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JoEHqExK-1652919086832)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220519072618579.png)]

image-20220510112839275

image-20220510112913844

image-20220510113003924

含有公共左因子的文法肯定不是LL1文法,但不含公共左因子的也不一定就是LL1文法。LL1文法可以推出不含公共左因子,但是不含公共左因子推不出LL1文法

image-20220510113058375

image-20220510111916795

image-20220510112113042

​ 把空串加进去还要接着往后看

image-20220510105233671

image-20220510105417802

image-20220510110855476

image-20220510113850526

image-20220513094048673

image-20220513094203520

第五讲:语法制导翻译

image-20220519072257698

image-20220519071658021

image-20220519071507093

image-20220513192748741

image-20220513193332503

image-20220513194026863

返回的永远都是综合属性,继承属性都是作为函数的参数传入进去的。

第六讲:中间代码生成

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3MLaPeRm-1652919086841)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220518234042172.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D2Rolhmt-1652919086841)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/8452/image-20220514112330154.png)]

既不是仅为定义性,也不是仅为使用性

image-20220514113256785

image-20220514113325237

image-20220514113433425

image-20220518233059235

第七章:运行存储分配

image-20220515095440355

局部变量地址在被调用者的数据区

image-20220515095555655

两个临时变量的作用域不相交,分配在统一单元中

第八章:代码优化

image-20220515171507030

image-20220515171654467

image-20220516082603502

image-20220516083204913

image-20220516084317544

image-20220516085602252

没有办法引用B1中的i,因为i在B2中已经被改变了

下面的例子中,没有被改变,相当于u2 u3是隐含存在的没改变的值,没有写到代码中,但是之后被引用了

image-20220516092534615

image-20220518231444002

第九章:代码生成

image-20220516091613735

image-20220516091629315

image-20220516091645303

image-20220518230918662

窥孔优化不是在中间代码层次进行的优化工作!!!

窥孔优化不是在中间代码层次进行的优化工作!!!

窥孔优化不是在中间代码层次进行的优化工作!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值