简介
该套习题的参考用书为陈意云、张昱的《编译原理》第三版。习题来源于老师的课堂测试的爬取,总结了前七章经典、易错的知识点,对照课本每一章节的知识点进行复习回顾效果更佳。
适合刷题前对总的知识点进行一遍梳理。
第一章 引论
1.编译器的工作可以分成若干个阶段,请按顺序排列编译器工作的7个阶段。
A. 词法分析器 B. 语法分析器 C. 语义分析器 D. 中间代码生成器 E. 独立于机器的代码优化器 F. 代码生成器 G. 依赖于机器的代码优化器
2.编译器会检查每个算符的运算对象,看他们的类型是否适当,这叫做类型检查。类型检查一般在编译器阶段划分中的哪个阶段进行?
语义分析器
3.编译器阶段划分的哪个阶段会将记号流构造成抽象语法树?
语法分析器
4.编译器阶段划分的哪个阶段会去掉源程序中的注释?
词法分析器
5.编译器的前端主要包括了编译器阶段划分的哪几个阶段?
语义分析器 词法分析器 语法分析器 中间代码生成器
6.C语言和汇编语言相比较而言谁是低级语言? 为什么?
汇编语言,因为汇编语言更贴近机器语言。
7.X86机器上原有一个C编译器(C→X86),如果想得到一个MIPS机器上的C编译器(C→MIPS),则需要进行如下工作: (1)先写一个(C→MIPS)的C源程序(源程序A) (2)在X86机器上用(C→X86)编译器编译源程序A得到X86机器上的(C→MIPS)编译器。 (3)在X86机器上用刚生成的(C→MIPS)编译器再编译源程序A一次,即得到MIPS机器上的(C→MIPS)编译器。 请问这个过程中有没有交叉编译?如果有,交叉编译发生在哪一步?
有,发生在(3)中
第二章 词法分析
在编译器中,词法分析和语法分析之间的典型关系是什么?
语法分析为主导,词法分析器作为语法分析器的子程序,被语法分析器调用。
如果对下列源程序进行词法分析,请问词法分析器应该返回多少个记号? printf( “Total=%d\n”, score); 7个
如下程序,在词法分析阶段,是否会对return报错?下面哪项说法正确?
if (sum > 0) return sum; 词法分析阶段不会报错,return会被识别为标识符返回。
下列哪个正规式表示Σ= {a, b}上a和b构成的所有串?
(a|b)*
二进制偶数用正规式表示为:
(0|1)*0
=========================================================
Lex根据Lex源程序生成的词法分析器源程序中,必须包含的两部分内容是什么?
根据Lex源程序中正规式构造的DFA状态转换表。 词法分析器驱动程序yylex()。
Lex生成的词法分析器使用什么原则匹配被选中的词法单元?
最长匹配原则 如果词法单元可与若干正规式匹配,则优先选择排在前面的正规式
Lex源程序中有两条正规式:A可以匹配所有标识符(以字母开头的字母数字组合),B可以匹配While关键字。如果想让输入文件中的While被识别为While关键字,则在Lex源程序中:
要把B放在A前面
Lex源程序的正规式中 . 表示什么?
字符 .
语法分析器在使用Lex生成的词法分析器时,每次调用yylex()获取一个词法记号,如果词法分析器的输入文件并未扫描到结尾,则关于这个过程正确的说法是:
每次调用yylex()后,输入缓冲区不会被重置。 每次调用yylex()后,词法分析器当前所属状态不变。
第三章 语法分析
正规式可以用于描述括号配对。
错
如果两个文法产生同样的语言,则称这两个文法等价。
对
如果一个文法G是二义的,则它所表示的语言L(G)也是二义的。
错
正规式能描述的所有结构都可以用上下文无关文法来描述。
对
组成上下文无关文法的四元组不包括
接受符号
=========================================================
按照惯常定义的“与”“或”“非”的优先级和结合性改写下列文法, S → S and S | S or S | not S | p | q | (S) 得到的等价的非二义文法是:
E → E or T | T T → T and F | F F → not F | ( E) | p | q
对于左递归文法:A→A a|b ,消除左递归后得到的文法是:
A→b A′ A′→ a A′ | ε
上下文无关文法在Chomsky分类中属于( )型文法?
2
Chomsky文法分类中3型文法又称为:
正规文法
假设有如下完整的if语句: if (a>0) then if (a>1) then b=1; else b=0; 按照正常语义, else应该和语句中从左数第几个then 配对?
第二个then
=========================================================
下列文法是LL(1)文法。 S → A B A → a b | ε B → a c
错
若有文法: S → A B A → a b | ε B → c 则First(S)= ?
{a, c}
若有文法: S → A B A → a b | ε B → c 则Follow(A) = ?
{c}
给文法: S → (L) | a L → S L′ L′→ , S L′ | ε 设计递归下降的预测分析器时,为L ′写的函数如下:
void Lprime (){
if(lookahead==‘,’){
match(‘,’);
S();
Lprime();
} else {
_________________
} else
error();
}
请问空白处应填写下列哪条语句?
if (lookahead==‘)’) return;
=========================================================
非递归预测分析算法中,栈中存放的是:
文法符号串
非递归预测分析算法中,如果栈顶是一个非终结符,则分析器的动作为:
根据当前输入a和栈顶非终结符X访问分析表M(X,a)
在非递归预测分析的分析表中,空白表项表示
出错
在非递归预测分析时,假设采用紧急方式的错误恢复,且同步集合选用Follow(A)中的元素。那么当出错时,若栈顶是A,输入经抛弃若干符号后,指向同步记号c(c∈Follow(A)),此时错误恢复动作应为
弹出栈顶A,恢复分析栈中A下面的那个符号。
在非递归预测分析时,如果采用紧急方式的错误恢复,当栈顶元素是终结符并且和当前输入符号不匹配时,一般怎样进行错误恢复?
弹出栈顶的终结符,给出“插入了该终结符”的错误恢复信息,并恢复分析
=========================================================
最左推导的逆过程是( ),( )也称规范归约。
最右归约,最左归约
自下而上分析又称为( )
移进归约分析
用栈实现移进-归约分析时,分析器在做“归约”这个动作时是把栈顶的( )归约为非终结符。
句柄
LR分析算法中,栈中存放的是:
状态
移进-归约分析中的冲突有:
移进-归约冲突 归约-归约冲突
=========================================================
所有能够用LL分析法(预测分析法)分析的文法,都能够用LR分析法分析
对
SLR分析的分析能力高于规范LR分析。
错
LR(0)项目中点的含义是表示分析过程中的状态,点后面的部分表示分析中在该状态下已经看见的部分,点前面的部分表示该状态下希望看见的部分。
错
构造SLR分析表的时候,非核心项目指的是所有点在左端的项目
错
构造SLR分析表时,在根据LR(0)项目集规范族中的项目填写“动作-转移表”时,项目[A→α ⋅Bβ]属于:(注:其中A,B是非终结符, α,β 是文法符号串)
待归约项目
=========================================================
构造规范的LR分析表时,在根据项目集族和识别活前缀的DFA填充动作-转移表的时候,如果碰到归约项目,应该填写action(i, a)为按相应产生式进行归约。请问怎样选择对哪些a填写归约呢?
a是搜索符
在构造规范的LR分析表时,应该构造( )集合作为识别活前缀的DFA的状态。
LR(1)项目
为如下文法构造规范的LR分析表,在构造第一个项目集时,正确的I0是:
E ′ → E E → E + T | T T →T ∗ F | F F →( E ) | id
E′→ ·E, $ E → ·E + T , $/+ E → ·T , $/+ T → ·T ∗ F , $/+/ T → ·F , $/+/ F → ·(E) , $/+/* F → ·id , $/+/***
所有能用规范LR分析进行分析的文法也都能用SLR分析进行分析。
错
无论是规范的LR分析还是SLR分析,分析算法都是一样的,分析表的形式也一样,不同点在于LR分析表的构造方法不同。
对
=========================================================
同心的LR(1)项目集就是指只有搜索符不同,其他部分都相同的LR(1)项目集。
对
在LALR分析时,合并同心项目集可能会导致移进-归约冲突。
错
当输入串有错误时,LALR分析可能会比规范的LR分析移进更多的输入符号。
错
有些文法能进行LALR分析,但是不能进行规范LR分析。
错
所有非LR的上下文无关文法都是二义的。
错
对于二义文法E → E + E | E ∗ E | (E) | id 进行SLR分析时,某LR(0)项目集如下: E → E + E· E → E·+ E E → E·∗ E 已知Follow(E)={+,*, ) , $} 请问该项目集中是否存在冲突?如果存在冲突,是在什么情况下存在冲突?按照正常语义,应该怎样处理?下面说法正确的是:
遇到+时,存在移进归约冲突,应该优先于归约。
=========================================================
进行LR分析时,一旦访问到转移表的空白项,则表示分析出错。
错
进行LR分析时,如果在试图将某输入子串归约为A的过程中出错,那么采用紧急方式的错误恢复,实际上相当于假设被退栈的部分和被抛弃的输入已经成功分析出了A,从而可以继续后面的分析。
对
Yacc解决分析动作冲突的一般原则是:
除另有说明外,( ) 对于移进-归约冲突,优先于移进,对于归约-归约冲突,优先于先出现的产生式。
在实现LR分析的短语级错误恢复时,实际上是为动作表中每个出错条目编写一个错误恢复子程序,分析一旦进入该出错条目,就调用该错误恢复子程序。
对
Yacc解决分析动作冲突时,如果定义了终结符的优先级和结合性,则如果产生移进归约冲突,下面说法正确的是:
如果归约的产生式的优先级和移进的终结符的优先级相同,且产生式左结合,则进行归约。
Yacc中产生式的优先级与产生式中处在最右端的终结符的优先级相同。
如果归约的产生式的优先级高于移进的终结符的优先级,则进行归约。
第四章 语法制导的翻译
一个语法制导定义不包含下列哪项:
属性依赖图(包括:基础文法(上下文无关文法)、产生式对应的语义规则、文法符号的属性)
语法制导定义中的一组语义规则如下:A→XYZ A.a=X.a+Y.a; Z.a = A.a下列说法正确的是:
A.a是A的综合属性
分析树中每个结点的所有属性(包括虚拟属性)都应该在属性依赖图中有一个结点,如果属性a依赖于属性b,则依赖图中应该有一条从结点a指向结点b的有向边。
错(依赖图中应该有一条从结点b指向结点a的有向边)
S属性定义中的综合属性可以由自下而上的分析器在分析输入的同时完成计算。
对
S属性定义中的继承属性不可以自下而上计算。
错(S属性定义中没有继承属性)
=========================================================
S属性定义也是一种L属性定义
对
L属性定义就是只含有继承属性的语法制导定义
错(L属性定义中可以包含综合属性,也可以包含继承属性,但是属性信息必须从左向右流动。)
翻译方案和语法制导定义的区别就是:语法制导定义中的语义规则在翻译方案中叫做语义动作,它被放在大括号里,可以插在产生式右部的任何地方,以此表示动作执行的时机。
对
L属性定义的翻译方案有可能在进行预测分析的同时进行属性的计算。
对
能不能给一个S属性定义写一个翻译方案?如果能,怎样写?下面说法正确的是:
能。只需要把S属性定义中的语义规则用大括号括起,然后放在产生式右部的末尾。
关于L属性定义的自下而上计算,下面说错误的是:
如果继承属性是综合属性的函数,则没有办法用自下而上的方式进行计算了。
(如果继承属性是综合属性的函数,则可以通过添加标记非终结符的方式使对继承属性的计算变为对标记非终结符综合属性的计算,从而转变成继承属性由简单复写规则产生的情况。)
第五章 类型检查
变量的类型的本质是变量在程序执行期间的取值范围。
对
由下面这条定型规则(该规则出自课本简单类型检查器规范)可以看出:如果想要得出id的类型是T的定型结论,必须要求定型环境中包含id,且id的类型为T。
对
下列关于类型可靠的说法不正确的是:
C语言是类型可靠的语言。
类型系统是一种逻辑系统,它通常应该包含三类要素,这三类要素不包括
类型检查器(推理(定型)规则、类型表达式、断言)
类型系统中的推理规则有三种形式,下面这条规则属于哪种形式的推理规则?
定型规则
=========================================================
类型声明如下所示,下列说法不正确的是:
type link = ↑cell; np = ↑cell; nqr = ↑cell; var next : link; last : link; p : np; q : nqr; r : nqr; 采用结构等价的观点看,q和r类型相同,p、q类型不同。
C语言在进行类型检查时对所有类型都采用了结构等价的观点。
错(C语言唯独对记录类型采用了名字等价的观点以避免类型表达式中出现环。)
如果类型转换由编译器自动完成,则称为显式类型转换。
错
类型检查器通常根据类型系统的定义进行编写,类型系统中的定型环境Γ在类型检查器中通常用符号表来表示。
对
类型检查器通常根据类型系统的定义进行编写,类型检查器中采用的所有类型在类型系统中都要有对应的类型表达式。
错(type_error在类型系统中没有对应的类型表达式)
第六章 运行时存储空间的组织和管理
关于下面的程序,错误的说法是:
void quickSort(int m, int n) { int i; if (n > m) { i = partition(m, n); quickSort(m, i-1); quickSort(i+1,n); } } i = partition(m, n);中m,n是形式参数。
过程的活动记录中包含过程的代码。
错
编译器为记录类型分配存储空间时,只要记录中域的数量、名称,及相应的类型不变,则无论记录域定义的顺序如何,为该记录分配的存储空间的大小不会变。
错 (由于有对齐的存在,分配的空间会变。)
调用序列全部处于调用过程中,返回序列全部处于被调用过程中。
错 (调用序列和返回序列分别有部分处于调用过程和被调用过程中。)
控制栈中当前存在的过程活动都是处在生存期内的活动。
对
=========================================================
悬空引用是指引用某个被释放的存储单元。
对
在无过程嵌套的静态作用域规则下,过程的活动要访问非局部变量需要用到访问链。
错 (在有过程嵌套的静态作用域规则下,过程的活动要访问非局部变量要用到访问链。)
在无过程嵌套的静态作用域规则下,过程可以作为参数来传递,也可以作为结果返回。
对
使用值调用传递参数时,对形参的任何赋值会影响调用者的实参。
错
C语言过程的活动记录中通常应该包含存放如下这些部分的区域:参数、返回地址、控制链、访问链、局部变量等。
错 (C语言属于无过程嵌套的语言,不需要访问链。)
第七章 中间代码生成
三地址码是语法树或DAG的一种线性表示,其中为语法树写出的三地址码通常比为DAG写出的三地址码更简洁(假设语法树和DAG都是为同样源程序写出的中间表示)。
错
后缀表示通常用于处理表达式,其最大优点是便于用计算机处理表达式。
对
赋值语句翻译成三地址码时,三地址码中的名字(变量名)实际上应该是该名字在符号表中的位置指针。
对
声明语句翻译成三地址码时,主要是为声明的名字在符号表中建立相应条目并填写类型信息和相对地址信息等。
对
对于允许过程嵌套的语言来说,所有声明的变量可以放在一个符号表中,用统一偏移计算相对地址。 错 (通常每个过程有自己的符号表和偏移。)