编译原理教程课后习题答案--第八章
第八章 符号表与错误处理
8.1 完成下列选择题:
(1) 编译程序使用区别标识符的作用域。
a. 说明标识符的过程或函数名
b. 说明标识符的过程或函数的静态层次
c. 说明标识符的过程或函数的动态层次
d. 标识符的行号
(2) 在目标代码生成阶段,符号表用于。
a. 目标代码生成 b. 语义检查
c. 语法检查 d. 地址分配
(3) 错误的局部化是指
a. 把错误理解成局部的错误
b. 对错误在局部范围内进行纠正
c. 当发现错误时,跳过错误所在的语法单位继续分析下去
d. 当发现错误时立即停止编译,待用户改正错误后再继续编译
【解答】 (1) b (2) d (3) c
8.2 在编译过程中为什么要建立符号表?
【解答】 在编译过程中始终要涉及到对一些语法符号的处理,这就需要用到语法符号的相关属性。为了在需要时能找到这些语法成分及其相关属性,就必须使用一些表格来保存这些语法成分及其属性,这些表格就是符号表。
8.3 对出现在各个分程序中的标识符,扫描时是如何处理的?
【解答】 对扫描到各分程序中的标识符的处理方法如下:
(1) 当在一个分程序首部某说明中扫描到一个标识符时,就以此标识符查找相应于本层分程序的符号表。如果符号表中已有此名字的登记项,则表明此标识符已被重复说明(定义),应按语法错误进行处理;否则,在符号表中新登记一项并将此标识符及有关信息(种属、类型、所分配的内存单元地址等)填入。
(2) 当在一分程序的语句中扫描到一个标识符时,首先在该层分程序的符号表中查找此标识符;若查不到,则继续在其外层分程序的符号表中查找。如此下去,一旦在某一外层分程序的符号表中找到标识符,则从表中取出有关的信息并作相应的处理;如果查遍所有外层分程序的符号表都无法找到此标识符,则表明程序中使用了一个未经说明(定义)的标识符,此时可按语法错误予以处理。
8.4 对下列程序,当编译程序编译到箭头所指位置时,画出其层次表(分程序索引表)和符号表:
program stack(output);
var m, n:integer;
r:real;
procedure setup(ns:integer, check:real);
var k, l:integer;
function total(var at:integer, nt:integer):integer;
var i, sum:integer;
begin
for i:=1 to nt do sum:=sum+at[i];
total:=sum;
end;
begin
l:=27+total(a,ns);
end;
begin
n:=4;
setup(n,5.75)
end.
【解答】 编译程序编译到箭头所指位置时,其层次表(分程序索引表)和符号表如图8-1所示。 11 10
9
8 7
6
5 4
3
2 1
符号表
图8-1 分程序索引表和符号表示意图
8.5 已知文法G[S]: S→while (e) S
S→{L}
S→a /*a代表赋值句*/
L→S;L
L→S
构造该文法的LR型的错误校正分析程序。
【解答】 首先将文法G[S]拓广为G[S′]:(0) S′→S
(1) S→while e do S
(2) S→begin L end
(3) S→a
(4) L→S
(5) L→S;L
则文法G[S′]的LR(0)项目集示范族为
I0:S′→·S I4:S→a· I10:L→S;·L
S→·while e do S I5:S→while e· do s L→·S
S→·begin L end I6:S→begin L·end L→·S;L
S→·a I7:L→S· S→·while e do S I1:S′→S· L→S· ;L S→·begin L end
I2:S→while·e do s I8:S→while e do·S S→·a
I3:S→begin·L end S→· while e do s I11:S→while e do S·
L→·S S→·begin L end I12:L→S;L·
L→·S;L S→·a
S→·while e do s I9:S→begin L end·
S→·begin L end
S→·a
将这些项目集的转换函数GO表示为如图8-2所示的DFA。
a
图8-2 习题8.5中文法G[S′]的DFA
在LR(0)项目集规范族中,只有I7含有“移进”/“归约”冲突,且该冲突可用SLR(1)方法解决。为此计算文法G[S′]中每个非终结符的FOLLOW集如下:
FOLLOW(S′)={#}
FOLLOW(S)={end,;,#}
FOLLOW(L)={end}
由此构造出包括错误校正处理子程序的SLR(1)分析表如表8-1所示。
表8-1 习题8.5的SLR(1)分析表
由表中可以看出,在状态7面对输入符号为“;”时移进,而面对输入符号为“end”时为归约。表中ei(i=1~7)代表不同的错误处理子程序,其含义和功能分别如下:
(1) 输出符号错处理程序e0:删除当前输入符号,显示出错信息“输入符号错”。
(2) 输入不匹配错误处理程序e1:去除栈顶状态和栈顶符号,显示出错信息“输入不匹配”。
(3) 缺语句错误处理程序e2:将假想符号a与状态4压栈,显示出错信息“缺少语句”。
(4) while语句缺少布尔量处理程序e3:将假想符号e与状态5压栈,显示出错信息“缺布尔量”。
(5) 缺少分号错误处理程序e4:将分号“;”插入未扫描的输入串首,显示出错信息“缺少分号”。
(6) while语句缺少do处理程序e5:将符号“do”与状态8压栈,显示出错信息“缺少do”。
(7) begin与end不配对,缺少end处理程序e6:将符号“end”与状态9压栈,显示出错信息“缺少end”。
(8) 缺少语句错误处理e7:将假想符号a插入未扫描的输入串首,显示出错信息“缺少语句”。