编译原理的知识点是在https://www.jianshu.com/p/eb63d31ad638基础上进行适当的补充,以下图片的截图主要来自这里https://www.bilibili.com/video/BV12741147J3?t=832。如果整理有误,请好心人帮忙指出。
汇编指令: 用符号表示的指令被称为汇编指令
汇编语言: 汇编指令的集合称为汇编语言
转换(也被称为预处理):高级语言之间的翻译,如FORTRAN 到 ADA的转换
编译: 高级语言可以直接翻译成机器语言,也可以翻译成汇编语言,这两个翻译过程称为编译
汇编: 从汇编语言到机器语言的翻译被称为汇编
交叉汇编: 将一个汇编语言程序汇编成为可在另一机器上运行的机器指令成为交叉汇编
反汇编:把机器语言翻译成汇编语言
反编译:把汇编语言翻译成高级语言
解释器与编译器的主要区别:运行目标程序时的控制权在解释器而不在目标程序.
编译器:
解释器:
共同点:
均完成对源程序的翻译 。
差异:
编译器采用先翻译后执行,解释器采用边翻译边执行.
声明+操作=完整定义
注:符号表管理器和出错处理贯穿编译器工作的各个阶段.
https://www.cnblogs.com/anthony007/p/4241189.html
1> 词法分析:
2> 语法分析:
3> 语义分析:
4> 中间代码生成(可选):
生成一种既接近目标语言,又与具体机器无关的表示,便于代码优化与代码生成。
(到目前为止,编译器与解释器可以一致)
5> 中间代码优化(可选):
6> 目标代码生成:
7> 符号表管理:
8> 出错处理:
动态错误:源程序中的逻辑错误,发生在程序运行的时候。也称为动态语义错误
静态错误:静态错误分为语法错误和静态语义错误.
逻辑上把编译器分为分析(前端)部分和综合(后端)部分 。
每个阶段将程序完整分析一遍的工作模式称为一遍扫描。
(将源程序或源程序的某种形式的中间表示完整分析一遍,亦称作一遍扫描)
单词的分类:关键字(保留字)、标识符、字面量、特殊符号
模式(pattern):产生/识别单词的规则
记号(token):按照某个模式(或规则)识别出的元素(一组)
单词(lexeme):被识别出的元素的值(字符串本身) ,也称为词值
词法分析器的作用:
工作方式:
语言L是有限字母表∑上有限长度字符串的集合。
定义中强调两个有限,因为计算机的表示能力有限 :
正规式又称为正则表达式
令Σ是一个有限字母表,则Σ上的 正规式 及其表示的集合递归定义如下:
1> ε是正规式,它表示集合 L(ε) = {ε}
2>若a是Σ上的字符,则a是正规式,它表示集合L(a)={a}
若正规式r和s分别表示集合L®和L(s),则
括弧用来改变运算的先后次序!
可用正规式描述(其结构)的语言称为 正规语言 或 正规集 。
我的理解正规式是一个式子,它表示的是在该规则,式子下的字符组合的集合
正规式 | 正规集 |
---|---|
a | {a} |
a|b | {a,b} |
ab | {ab} |
(a|b)* | {ε,a,b,aa,ab,ba,bb,aaa,……} |
若运算的优先级和结合性做下述约定:
则正规式中不必要的括号可以被省略。
若正规式P和Q表示了同一个正规集,则称P和Q是等价的,记为P=Q
正闭包
可缺省
串
字符组
非字符组
若[r]是一个字符组形式的正规式,则[^r]是表示∑- L([r])的正规式。
NFA(NondeterministicFinite Automaton, NFA)是一个五元组(5-tuple):M =(S,∑,move,s0,F),其中
直观的表示方式
NFA(识别记号)的特点
NFA识别记号的最大特点是它的不确定性,即在当前状态下对同一字符有多于一个的下一状态转移。
具体体现:
NFA识别记号存在的问题
提示:正规式和有限自动机从两个侧面表示正规式。正规式是描述,自动机是识别。
构造词法分析器的一般方法和步骤:参考https://blog.csdn.net/qq_40427276/article/details/102771393
Thompson 算法
三种基本状态图
举个栗子:
备注:
第一个状态I需要填入初始态X,其他不用
若2为某个状态S,则在求Ia时**先加入e(空)**求能到达的状态,再加入字符a,求能到达的状态,合并即为Ia此时的状态。
eg {1,2,4,5,6,Y}: 走e(空)可到1,2,6,Y ;走a,2到4,6到6,不能到3,也不能到5,所以新状态为**{1,2,3,6,Y}**
通过状态转换矩阵画出DFA状态转换图
备注:
主要步骤:
分类: 表驱动型的词法分析器;直接编码的词法分析器
比较:
表驱动 | 直接编码 | |
---|---|---|
分析器的速度 | 慢 | 快 |
程序与模式的关系 | 无关 | 有关 |
适合的编写方法 | 工具生成 | 手工编写 |
分析器的规模 | 较大 | 较小 |
词法分析: 记号的集合,字符串由字母组成,线性结构
语法分析: 句子的集合,句子由记号组成,非线性结构(树)
语法分析的双重含义:
许多编译器,特别是由自动生成工具构造的编译器,往往其前端的中心部件就是语法分析器
源程序中可能出现的错误
语法(包括词法)错误和语义错误(静态语义错误和动态语义错误)
注:跟第一章的分类角度不同,第一章是从静态错误(语法错误,静态语义错误)和动态错误(动态语义错误)分类的,但是殊途同归。
词法错误: 指非法字符或拼写错关键字、标识符等
语法错误: 指语法结构出错,如少分号、括号不匹配、begin/end不配对等
静态语义错误: 如类型不一致、参数不匹配等
动态语义错误(逻辑错误):如死循环、变量为零时作除数等
CFG(Context Free Grammar,CFG)是一个四元组G =(N,T,P,S),其中
注: S ∈ N , N可以出现在产生式左边和右边,T绝不出现在产生式左边.
CFG(产生式)通过推导的方法产生语言,即(通俗地讲)从开始符号S开始,反复使用产生式:将产生式左部的非终结符替换为右部的文法符号序列(展开产生式,用=>表示),直到得到一个终结符序列。
(推导具有自反性和传递性)
4> 由 CFG所产生的**语言L(G)*被定义为: L(G) = { ω┃S ω and ω∈T },
5> 在推导过程中,若每次直接推导均替换句型中最左边的非终结符,则称为最左推导,由最左推导产生的句型被称为左句型。 类似的可以定义最右推导与右句型,最右推导也被称为规范推导。
举一个小栗子https://blog.csdn.net/Jane_96/article/details/80024154
文法G(E)为:
E -> T | E + T |E - T
T -> F | T * F | T / F
F -> (E) | i
给出i + i * i 的最左推导和最右推导。(注意集合的运算)
最左推导:
从文法的起始符号开始:
E -> E + T
-> T + T
-> F + T
-> i + T
-> i + T * F
-> i + F * F
-> i + i * F
-> i + i * i
最右推导:
从文法的开始符号开始:
E -> E + T
-> E + T * F
-> E + T * i
-> E + F * i
-> E + i * i
-> T + i * i
-> F + i * i
-> i + i * i
注:分析树的叶子,从左到右构成G的一个句型。若叶子仅由终结符标记,则构成一个句子。
对CFG G的句型,表达式的语法树被定义为具有下述性质的一棵树:
语法树是表示表达式结构的最好形式
语法树和分析树的区别:
二义性:若文法G对 同 一句子产生不止一棵分析树,则称G是二义的.
举个栗子:
如果一个文法中存在**某个句子(**全部由终结符组成的句型)对应两棵不同的语法树,则该文法具有二义性,如文法:
G(E):
E->i
E->E+E
E->E*E
存在句子i+i*i
,可以对应这样两棵语法树:
和
是具有二义性的。
或者在填写分析表(下面会讲到)时,某个单元有两个产生式。https://www.bilibili.com/video/BV19J411B7ha?p=85
结论:
二义性消除的方法:
① 改写二义文法为非二义文法;
② 规定二义文法中符号的优先级和结合性,使仅产生一棵分析树。
正规式(1型文法)所描述的语言结构均可以用CFG(2型文法)描述,反之不一定.
典型的这类语言结构包含:计数问题的抽象、变量的声明与引用、过程调用时形参与实参的一致性检查等。描述它们的文法被称为上下文有关文法(Context Sensitive Grammar,CSG)。这些语言结构无法用上下文无关文法CFG来描述.
若文法G=(N,T,P,S)的每个产生式α→β中,均有α∈(N∪T),且至少含有一个非终结符*,β∈(N∪T)*,则称G为0型文法.
对0型文法施加以下第i条限制,即得到i型文法。
1> G的任何产生式α→β(S→ε除外)满足|α|≤|β|;
2> G的任何产生式形如A→β,其中A∈N,β∈(N∪T)*;
3> G的任何产生式形如A→a或者A→aB(或者A→Ba),其中A和B∈N,a∈T。
文法 | 语言 | 自动机 |
---|---|---|
短语文法(0型) | 短语结构语言 | 图灵机 |
CSG(1型) | CSL | 线性界线自动机 |
CFG(2型) | CFL | 下推自动机 |
正规文法(3型) | 正规集 | 有限自动机 |
举个栗子:https://www.cnblogs.com/ITGirl00/p/3391211.html
S-> aaS|a是什么型的,为什么
S-> aSb|ab是什么型的,为什么
S-> SaS|b是什么型的,为什么
所以,取其最高的符合规则,最后的答案是其符合:上下文无关文法规则,即2型。
备注:
分为:递归下降分析法、预测分析法
基本思想:对任何一个输入序列ω,从S开始进行最左推导,直到得到一个合法的句子或发现一个非法结构。整个自上而下分析是一个试探的过程,是反复使用不同产生式谋求与输入序列匹配的过程。
提前准备——重写文法:1.消除左递归,以避免陷入死循环; 2.提取左因子,以避免回溯。
定义:若文法G中的非终结符A,对某个文法符号序列α存在推导A =+> Aα,则称G是左递归的。若G中有形如A→Aα的产生式,则称该产生式对A直接左递归。
<1> 消除文法的直接左递归,变成直接右递归
A→Aα|β 替换为 A →βA'
A'→αA'|ε
A’→ α1 A’ | α2 A’ | … | αm A’ |ε
为什么替换后的右递归和左递归是等价的?
左递归: A -> Aα -> Aαα _> … -> Aαα…α ->βαα…α
右递归: A -> βA’ -> βαA’ -> βαα…A’ -> βαα…α
所以两者是等价的,产生的语言是一样的。
举个栗子:
文法G(E):
E -> E+T|T
T -> T*F|F
F -> (E)|i
消除直接左递归后(E最终会以T开头):
E -> TE’
E‘ -> +TE’|ε
T -> FT’
*T’ -> FT’|ε
F -> (E)|i
什么是左递归?
举个栗子:
文法G(S):
S -> Qc|c
Q -> Rb|b
R -> Sa|a
虽没有直接左递归,但存在S推导到以S为开头的串,S -> Qc -> Rbc -> Sabc。并且显然,S,Q,R都是左递归的。
一个文法消除左递归的条件
消除左递归的方法:反复替换,打断循环,变成直接左递归
https://www.bilibili.com/video/BV19J411B7ha?p=67
终结首符集FIRST(α):
https://blog.csdn.net/jane_96/article/details/79888680
计算各个文法符号X的FIRST(X)时,不断应用下列规则,直到再没有新的终结符号或者ε可以被加入到任何FIRST集合中为止。
举个栗子:
文法G[E]:
1. E -> TE’
2. E’-> +TE’|ε
3. T -> FT’
4. T’-> *FT’|ε
5. F -> (E)|a
-------
FIRST(E): 由E -> TE’可得FIRST(E) = FIRST(T)
FIRST(T): 由T -> FT’可得FIRST(T) = FIRST(F)
FIRST(F): 由F -> (E)和F -> a可得FIRST(F) = { ( , a };
FIRST(T’): 由T’-> *FT’和T’-> ε 可得FIRST(T’) = { * , ε };
FIRST(E’): 由E’-> +TE’和E’-> ε可得FIRST(E’) = { + , ε };
------
FIRST(E) = { ( , a };
FIRST(T) = { ( , a };
FIRST(F) = { ( , a };
FIRST(T’) = { * , ε };
FIRST(E’) = { + , ε };
如何根据α定义的终结首符集FIRST(α)来自顶向下匹配句子。(此时还没有引入FOLLOW集)
左因子产生原因:公共前缀:A → αβ1|αβ2
方法:将 A → αβ1|αβ2|γ
替换为 A→αA’|γ A’→β1|β2
https://www.bilibili.com/video/BV19J411B7ha?p=68
https://blog.csdn.net/jane_96/article/details/79888680
计算所有非终结符号A的FOLLOW(A)集合时,不断应用下列规则,直到再没有新的终结符号可以被加入到任意FOLLOW集合中为止。
举个栗子:
https://blog.csdn.net/qq_40294512/article/details/89397905
E -> T E'
E' -> + T E' | ε
T -> F T'
T' -> * F T' | ε
F -> ( E ) | id
------
FIRST(E) = FIRST(T) = FIRST(F) = { ( , id }
FIRST(E') = FIRST(+) ∪ FIRST(ε)= { + , ε }
FIRST(T) = FIRST(F) = {( , id}
FIRST(T') = FIRST(*) ∪ FIRST(ε)= { * , ε }
FIRST(F) = {( , id}
-----
FOLLOW(E) ,根据规则1,首先把$加入进来,根据规则2,可以得出 FOLLOW(E) = { ) , $ }
FOLLOW(E’) = FOLLOW(E) = { ) , $ } 根据规则3
FOLLOW(T) = FIRST(E’) ∪ FOLLOW(E) = { + , ) , $ } 根据规则2
FOLLOW(T’) = FOLLOW(T) = { + , ) , $ } 根据规则3
FOLLOW(F) = FOLLOW(T) ∪ FIRST(T’) = { * , + , ) , $ } 根据规则2和3
FOLLOW(E) = FOLLOW(E') = { ) , $ }
FOLLOW(T) = FOLLOW(T') = { + , ) , $ }
FOLLOW(F) = { * , + , ) , $ }
备注:
对于非终结符B求FOLLOW
B都在产生式右边,主要看B是否可能在右边的最尾部,如果存在,则需要考虑产生式左边的FOLLOW,如果没有,则考虑紧跟其后的字符的FIRST即可。
原则1:若B在右边,则B依赖紧跟其后的字符C,找字符C的FIRST©,并去掉 ε ,加入FOLLOW(B)
原则2:若B在右边且为倒数第二个字符,如果倒数第一个字符可为空,则B依赖于左边非终结符A,找FOLLOW(A加入FOLLOW(B)
所有非终结符的FOLLOW集合同时初始化为空集合,并行填写FOLLOW集合
一个产生式可能会匹配多个原则。
ε永远不进FOLLOW集合
https://www.bilibili.com/video/BV1tt41177b5?p=14
构造不带回溯的LL(1)文法条件:
直接以程序代码(的方式)模拟产生式产生语言的过程:
基本思想: 每个非终结符对应一个子程序(函数),过程体中:
特点:
1> 子程序是递归的(因为文法是递归的);
2> 程序与文法相关;
3> 它对文法的限制是不能有公共左因子和左递归;
4> 它是一种非形式化的方法,只要能写出子程序,用什么样的方法和步骤均可。
https://www.bilibili.com/video/BV19J411B7ha?p=81
总控程序: 根据现行栈顶符号和当前输入符号,执行动作
分析表M[A, a]矩阵: A∈N,a∈T是终结符或“#”,是一种数据结构。
分析栈: 用来存放文法符号
备注:
分析表是矩阵M[A,a],是一种数据结构。根据FIRST集合和FOLLOW集合
☆ 无论是递归下降子程序法还是非递归的预测分析法,他们都只能处理LL(1)文法 。
自上而下:从开始符号出发,根据产生式规则推导给定的句子。用的是推导。
自下而上: 从给定的句子规约到文法的开始符号。用的是归约(规范归约—剪句柄—移进/归约分析—SLR(1)分析器).
主要有算符优先分析法 和 LR分析法
对于每个输入序列ω:从左到右扫描ω; 从ω开始,反复用产生式的左部替换产生式的右部(即当前句型中的句柄)、谋求对ω的匹配,最终得到文法的开始符号,或者发现一个错误。
基本概念:
a> 移进-规约的例子
1.已知文法:
E→E+T | T
T→T*F | F
F→(E) | i
以句柄作为可归约串,写出符号串‘i+i*i#’的"移进-归约"分析过程。
符号栈 | 输入串 | 动作 |
---|---|---|
# | i+i*i# | 移进 |
#i | +i*i# | 归约 |
#F | +i*i# | 归约 |
#T | +i*i# | 归约 |
#E | +i*i# | 移进 |
#E+ | i*i# | 移进 |
#E+i | *i# | 归约 |
#E+F | *i# | 归约 |
#E+T | *i# | 移进 |
#E+T* | i# | 移进 |
#E+T*i | # | 归约 |
#E+T*F | # | 归约 |
#E+T | # | 归约 |
#E | # | 接受 |
b>最左归约:若 α是文法G的句子且满足下述条件,则称序列αn,αn-1,…,α0是α的一个最左归约。
最左归约的逆过程是一个最右推导,分别称最右推导和最左归约为规范推导和规范归约.
c)移进-归约分析器
工作方式:格局与格局变换
分析表
驱动器(模拟算法)
SLR分析表的构造
LR(文法、语言、分析器)
改变格局的动作:
按照算符的优先关系和结合性质进行语法分析;适合分析表达式。
备注:
FIRSTVT§:P产生式右端从左往右第一个终结符
LASTVT§:P产生式右端从右往左第一个终结符
FIRSTVT集合和LASTVT集合的目的是为了求出字符之间的优先级,构造优先关系表。
先看产生式(1)右端 “+“的前面字符:LASTVT(E) > “+” ,及左边算符 >右边算符。
再看产生式(1)右端 “+“的后面字符:"+" < FIRSTVT(E) ,及左边算符 < 右边算符。
备注:
规范规约:句柄作为可规约串;寻找句柄是关键。如果句柄入栈,则需要马上规约,否则会错过规约的时机。
LR分析法中,L是从左到右扫描输入串,R是指自下而上进行规约。
如何查看LR分析表进行自下而上语法分析?
https://www.bilibili.com/video/BV12741147J3?p=107
备注:
3> 构造识别文法所有活前缀的DFA
先通过LR(0)项目构造NFA,然后通过合并相同的集合(变成族)构造DFA
备注:
NFA中双圈为规约态
对于NFA,如果当前活前缀接下来扫描的字符为非终结符A,有两种动作
对于NFA变成DFA,不用像词法分析一样用子集法,用状态矩阵来转换,直接看图构造
ACTION和GOTO表中的状态其实是识别活前缀的DFA的状态。
如果一个项目集中,移进和规约的Follow集合相交非空,则可以确定是移进还是规约。
备注:
备注:
备注:
这些算法的演进主要是解决移进规约冲突的问题,请参考该博客LL(1),LR(0),SLR(1),LALR(1),LR(1)对比与分析
采用语法制导翻译生成中间代码
(1)语法与语义的关系
语法是指语言的结构、即语言的“样子”;
语义是指附着于语言结构上的实际含意,即语言的“意义”.
一个语法上正确的句子,它所代表的意义并不一定正确.
☆ 语义分析的作用
• 检查结构正确的句子所表示的意思是否合法;
• 执行规定的语义动作,如:表达式求值、符号表的查询/填写、中间代码生成等
☆ 应用最广的语义分析方法是语法制导翻译,他的基本思想是将语言结构的语义以属性的形式赋予代表此结构的文法符号,而属性的计算以语义规则的形式赋予由文法符号组成的产生式.
(2)属性/语义规则的定义
定义4.1 对于产生式A→α,其中α是由文法符号X1X2...Xn组成的序列,它的语义规则可以表示为(4.1)所示关于属性的函数f:
b := f(c1, c2, ..., ck) (4.1)
语义规则中的属性存在下述性质与关系:
(1) 称(4.1)中属性b依赖于属性c1, c2, ..., ck。
(2) 若b是A的属性,c1, c2, ..., ck是α中文法符号的属性,或者A的其它属性,则称b是A的综合属性。
(3) 若b是α中某文法符号Xi的属性,c1, c2, ..., ck是A的属性,或者是α中其它文法符号的属性,则称b是Xi的继承属性。
(4) 若语义规则的形式如下述(4.2),则可将其想像为产生式左部文法符号A的一个虚拟属性。属性之间的依赖关系,在虚拟属性上依然存在。
f(c1, c2, ..., ck) (4.2) ■
☆ 继承属性从前辈和兄弟的属性计算得到,综合属性从子孙和自身的其他属性计算得到.
即,继承属性
“自上而下,包括兄弟”,综合属性
“自下而上,包括自身”.
(3)语义规则的两种形式
☆ 语义规则的两种形式(忽略实现细节,二者作用等价)
<1> 语法制导定义(Syntax Directed Definition)
用抽象的属性和运算表示的语义规则;(公式,做什么)
<2> 翻译方案(Translation Scheme)
用具体的属性和运算表示的语义规则。(程序段,如何做)
☆ 继承属性
是自上而下计算的,综合属性
是自下而上计算的.
(4)LR分析翻译方案的设计
☆ LR分析中的语法制导翻译实质上是对LR语法分析的扩充:
当执行归约产生式
的动作时,也执行相应产生式对应的语义动作
。由于是归约时执行语义动作,
因此限制语义动作仅能放在产生式右部的最右边
;
增加一个与分析栈
并列的语义栈
,用于存放分析栈中文法符号所对应的属性值
。
☆ 扩充后的LR分析最适合对综合属性的计算,而对于继承属性的计算还需要进行适当的处理.
☆ 中间代码应具备的特性
1)便于语法制导翻译
2)既与机器指令的结构相近,又与具体机器无关.
使用中间代码的好处:一是便于编译器程序的开发和移植,二是代码进行优化处理.
☆ 中间代码的主要形式:后缀式、树、三地址码等.最基本的中间代码形式是树;最常用的中间代码形式是三地址码,它的实现形式常采用四元式形式。
☆ 符号表是帮助声明语句实现存储空间分配的重要数据结构。
(1)后缀式
操作数在前,操作符紧随其后,无需用括号限制运算的优先级和结合性;便于求值.
(2)三地址码
① 三元式 形式: (i) (op, arg1, arg2)
三地址码:(i):= arg1 op arg2
序号的双重含义:既代表此三元式,又代表三元式存放的结果
存放方式:数组结构,三元式在数组中的位置由下标决定
弱点:给代码的优化
带来困难
② 四元式 形式: ( i ) (op,arg1,arg2,result)
所表示的计算: result:= arg1 op arg2
③ 树形表示
1> 语法树真实反映句子结构,对语法树稍加修改(加入语义信息),即可以作为中间代码的一种形式(注释语法树)
2> 树的优化表示-DAG
3> 树与其他中间代码的关系
☆ 树表示的中间代码
与后缀式
和三地址码
之间有内在联系
方法:对树进行深度优先后序遍历
,得到的线性序列就是后缀式
,或者说后缀式是树的一个线性化序列;
特点:树的每个非叶子节点和它的儿子对应
一个三元式或四元式;
方法:对树的非叶子节点进行深度优先后序遍历,即得到一个三元式或四元式序列。
(1)构成名字的字符串
**构成名字的字符串的存储方式:**直接存储—定长数据(直接将构成名字的字符串放在符号表条目中)和间接存储—变长数据(将构成名字的字符串统一存放在一个大的连续空间内,字符串与字符串之间采用特殊的分隔符隔开,符号表条目中仅存放指向该字符串首字符的指针).
(2)名字的作用域
☆ 程序语言范围的划分可以有两种划分范围的方式:并列
和嵌套
☆ **名字的作用域规则:**规定一个名字在什么样的范围内应该表示什么意义.
<1> 静态作用域规则(static-scope rule):编译时就可以确定名字的作用域,即仅从静态读程序就可确定名字的作用域
<2> 最近嵌套规则(most closely nested):名字的声明在离其最近的内层起作用
(3)线性表
符号表以**栈(线性表)**的方式组织.
线性表上的操作:查找、插入、删除、修改
查找:从表头(栈顶)开始,遇到的第一个符合条件的名字;插入:先查找,再加入在表头(栈顶);
关键字 = 名字+作用域;
(4)散列表
名字挂在两个链上(便于删除操作):
相同hash值
的元素,表头在表头数组中;同一作用域
中的元素,表头在作用域表中.☆ 操作:查找、插入、删除
(1)变量的声明
☆ 一个变量的声明应该由两部分来完成:类型的定义
和变量的声明
1> 简单数据类型
的存储空间是预先确定的,如int可以占4个字节,double可以占8个字节,char可以占1个字节等
2> 组合数据类型变量
的存储空间,需要编译器根据程序员提供的信息计算而定.
(2) 过程
1.过程(procedure):过程头(做什么) + 过程体(怎么做);
- 函数: 有返回值的过程
- 主程序: 被操作系统调用的过程/函数
2.过程的三种形式:过程定义、过程声明和过程调用。
过程定义:过程头+过程体;
过程声明:过程头;
3. 左值与右值
1> 直观上,出现在赋值号左边和右边的量分别称为左值和右值;
2> 实质上,左值必须具有存储空间,右值可以仅是一个值,而没有存储空间.
3> 形象地讲,左值是容器,右值是内容.
4. 参数传递
1> 形参与实参
- 声明时的参数称为形参(parameter或formal parameter)
- 引用时的参数称为实参(argument或actual parameter)
2> 常见的参数传递形式:(不同的语言提供不同的形式)
- 值调用(call by value)---过程内部对参数的修改,不影响作为实参的变量原来的值.
- 引用调用(call by reference)--- 过程内部对形参的修改,实质上是对实参的修改.
- 复写-恢复(copy-in/copy-out)--- ① 过程内对参数的修改不直接影响实参,避免了副作用;
② 返回时将形参内容恢复给实参,实现参数值的返回.
- 换名调用(call by name)--- 宏调换
3> 参数传递方法的本质区别: 实参是代表左值、右值、还是实参本身的正文.
5. 作用域信息的保存
☆ 能够画出嵌套过程的嵌套关系树(P191 4.33),根据语法制导翻译(P193 4.35)画出分析树,写出推导步骤,构造的符号表
P197 例4.36 主要是变量类型的转换
(1)数组元素的地址计算
(2)☆数组元素引用的语法制导翻译(考试热点之一)
布尔表达式的计算有两种方法:数值表示的直接计算
和逻辑表示的短路计算
☆ 布尔表达式短路计算的翻译:短路计算的控制流,真出口与假出口,真出口链与假出口链,拉链回填技术(P207 例4.41)(考试热点之一)
**控制语句的分类:**①无条件转移、②条件转移、③循环语句、④分支语句
多看课件PPT,多做题练手