选择题
1.代码优化的主要目的是: B
①提高目标程序的运行速度
②如何减少目标程序运行所需的空间
③如何协调①和②
④使生成的目标代码尽可能简短
A ①② B ①②③ C ①②④ D①②③ ④
2.在编译程序采用的优化方法中,_____ 是在循环语句范围内进行的。 D
①合并已知常量 ②删除多余运算, ③删除归纳变量 ④强度削弱 ⑤代码外提
A. ①④ B. ①⑤ C. ①④⑤ D. ③④⑤
3.在编译过程中,引起源程序发生质的变化的阶段是(B)
A.语法分析
B.语义分析
C.词法分析
D.中间代码分析
4.有代码为 x=a+b+B; y=a+b+d;
可以采用的优化方法是:B
A.常量的合并与传播
B.公共子表达式删除
C.无用赋值的删除
D.死代码删除
判断题
1.编译过程可以一遍完成,也可以分为多遍完成 √
2.一个DFA即可认为是一个词法分析器 √
3.对于一个任意给定的正规式,一定存在一个能识别该正规集的DFAM √
4.若存在算符有限关系a>b,优先关系b<a一定也存在 ×
5.一个有限自动机中有且只有一个结束状态 ×,(最多有一个结束状态)
6.文法经过提取左因子和左递归后一定会是LL(1)文法 ×
7.所有文法规则的左部只能有非终结符号,不能有终结符号 ×
8.chomsky的形式文法分类的依据是产生式的形式 √
9.最左素短语首先一定是短语,也肯定是句柄(直接短语中的最左直接短语为该句型的句柄) ×
10.文法中的右递归不影响进行确定的自顶向下语法分析 √
11.计算机高级语言翻译成低级语言只有解释一种方式 ×
12.每个文法都能改写为LL(1)文法 ×
13.算符优先关系表不一定存在对应的优先函数 ×
- LR分析方法是自顶向下语法分析方法 ×
LL(1)文法属于自上而下的分析方法
LR文法属于自下而上的分析方法
递归下降分析是确定的自上而下的
15.如果一个文法存在某个句子对应两颗不同的语法树,则该文法是二义的 √
16.数组元素的地址计算与数组的存储方式有关 √
17.编译程序是对高级语言程序的解释执行 × (编译程序是高级语言的翻译)
18.逆波兰表示法表示表达式时无须使用括号 √
19.在编译中进行语法检查的目的是为了发现程序中所有错误 ×
20.一个句型的句柄一定是文法某产生式的右部 √
21.若一个句型中出现了某产生式的右部,则此右部一定是该句型的句柄 ×
22.在程序中标识符的出现仅为使用性的 ×
23.递归下降法允许任一非终极符是直接左递归的 ×
24.自底而上语法分析方法的主要问题是候选式的选择 ×(自顶向下的语法分析方法的关键是如何选择候选式
的问题。
25.同心集的合并有可能产生归约归约冲突 √
26.一个文法所有句子的集合构成该文法定义的语言 √
27.非终结符可以有综合属性,但不能有继承属性 ×
28.若过程p第k次被调用,则p的DISPLAY表中就有k+1个元素 ×
29.词法分析应遵循的是语义规则 ×(构词规则)
30.中间代码是依据语言的语义规则进行的 √
31.环境把名字映射到左值,而状态把左值映射到右值 √
32.含有优化功能的编译程序执行效率高 ×
(有优化功能的编译程序,其优化是指对生成的目标代码进行优化,而不是编译程序本身得到优化,它提高目标代码的效率,而不是编译程序的效率)
大题
消除左递归和提取左因子
1.消除左递归
A→Aα|β(α,β为任意符号串)
改为 A→β A ′ A^{'} A′
A ′ A^{'} A′→α A ′ A^{'} A′|ε
2.提取左因子
A→ ζ β 1 ∣ ζ β 2 ∣ . . . ∣ ζ β i ∣ β i + 1 ∣ . . . ∣ β j ζβ_{1}|ζβ_{2}|...|ζβ_{i}|β_{i+1}|...|β_{j} ζβ1∣ζβ2∣...∣ζβi∣βi+1∣...∣βj
改为A→ ζ A ′ ∣ β i + 1 ∣ β j ζA^{'}|β_{i+1}|β_{j} ζA′∣βi+1∣βj
A ′ → β 1 ∣ . . . ∣ β j A^{'}→β_{1}|...|β_{j} A′→β1∣...∣βj
LR(1)分析表步2骤:
1.文法的拓广并编号:
2.LR(1) 项目集规范族所对应的识别活前缀的 DFA*
(1)求FOLLOW集
注意:当A是最右部的时候,将#加入到follow(A)中
-
将# 放到follow(S)中,其中S是文法的开始符号。
-
如果存在一个产生式A→αBβ,那么first(β)中除ε之外的所有符号都在follow(B)中。 【 follow(B)是求跟在B后的终结符或# 组成的集合,因此对于跟在B后的β,它的first集合就是follow(B)的子集 】
-
如果存在一个产生式A→αB,或存在产生式A→αBβ且first(β)包含ε,那么follow(A)中的所有符号都在follow(B)中。 【 对于A→αBβ,且β多步推导出ε ,那么可以用αB替换A, B后面紧跟的字符就是A后面紧跟的字符】
(2)写向前搜索符
①文法开始符,FOLLOW集
②“先看前再看后”
A→α·Bβ,a
B→ ,b
求b,若β为空,b=a
若β不为空,first(β)加入逗号后面(β为非终结符)
β终结符的时候把β加到b里面
构造LR(1)项目集的闭包函数。
a)假定I是一个项目集, I 的任何项目都属于CLOSURE(I)。
b) 若有项目 [A→α·Bβ,a ]属于CLOSURE(I),B→γ是文法中的产生式,那么对于FIRST(βa)中的每个终结符b,如果[ B→·γ,b ]原来不在,则加入CLOSURE(I)中。
c) 重复b)直到CLOSURE(I)不再增大为止。
注意:b可能是从β推出的第一个终结符,若β推出ε,则b就是a
(3)开始画DFA*
注意:每一个项目集都要重新判断一下向前搜索符
3.构造LR(1)分析表
ACTION和GOTO
逆波兰和三元式
1.逆波兰
“自外向内”——拆分的顺序就是由左到右顺序进行,小括号内的最后拆(由外到内);
2.三元式
三元式的求解过程是由内到外,然后右左向右,可以发现先拆小括号里面,然后再按顺序向右求解;
把表达式及语句表示成一组三元式,每个三元式由运算符op,运算对象arg1,运算对象2arg2组成,形如(op,arg1,arg2)
举例: a:=b*c+b*d
(1) (* b,c)
(2) (* b,d)
(3) (+ (1),(2))
(4) (:= (3),a)
NFA到DFA的转化
1.求出 ε_closure(s)
ε_closure(s)表示由状态 s经由条件 ε 可以到达的所有状态的集合
2.下面的A,B,C…表示一种状态。如A表示{ 0 , 1 , 2 , 4 , 7 } ,其实就是 ε_closure(0)
ε_closure(move(A,a)) 中的 move(A,a)是什么意思呢?
它代表从状态A,经过a到达的状态。
3.画出DFA状态转换表
步骤2中有A,B,C,D四种情况,其中A是初始情况 ε_closure(0)={0,1,2,4,7}. 多说几句,在NFA图1中,是从0出发的,所以初始情况是ε_closure(0),那假设如果是从X开始,则初始情况是ε_closure(X)
4.根据DFA状态转换表画出DFA状态转换图
DFA的最小化
可区分:对于任何两个状态t和s,若从一状态出发接受输入字符串ω,而从另一状态出发不接受ω,或者从t出发和从s出发到达不同的接受状态,则称ω对状态t和s是可区分的。
不可区分:设想任何输入序列ω对s和t均是不可区分的,则说明从s出发和从t出发,分析任何输入序列ω均得到相同结果。因此,s和t可以合并成一个状态
通俗一点的来说,可区分状态可以理解为两个(或多个)状态根本不是一类,根据下一个输入的符号,不同状态得到的结果可能会出现不同。而不可区分状态就是,这两个(或多个)状态,无论下一个接收的符号是什么,得到的结果都是一样的。
FA的最小化就是找出DFA中所有的不可区分状态,把它们合并为一个状态