内容目录
编译原理lab7
1. 对如下PL/0源程序,编译器分析到f:=(a+b)/3时候,符号表中的信息是怎样的?请以表格形式列出,并附上调试执行到该点时候的监视窗口截图。
const a=27,b=80;
var x,y,z;
procedure p;
var f;
begin
f:=(a+b)/3;
end;
begin
x:=3; call p;
end.
当编译器分析到f:=(a+b)/3时,
符号表中信息如下:
| name | kind | val/level | addr | size |
|---|---|---|---|---|
| a | constant | 27 | ||
| b | constant | 80 | ||
| x | variable | 0 | 3 | |
| y | variable | 0 | 4 | |
| z | variable | 0 | 5 | |
| p | procedure | 0 | 2 | 4 |
| f | variable | 1 | 3 |
监视窗口截图如下:

2. 对如下PL/0源程序,编译器分析到x:=0;时候,符号表中的信息是怎样的?请以表格形式列出,并附上调试执行到该点时候的监视窗口截图。对procedure类型的标识符,其在符号表中的adr字段的含义是什么?这个adr值何时生成和更新?(指出相应代码片段并简要说明)
const a=25;
var x,y;
procedure p;
var z;
begin
y:=0;
z:=y;
end;
procedure r;
var x, s;
procedure t;
var v;
begin
v:=1
end;
begin
x:=0;
end;
begin
x:=1;
end.
当编译器分析到x:=0时,
符号表中信息如下:
| name | kind | val/level | addr | size |
|---|---|---|---|---|
| a | constant | 25 | ||
| x | variable | 0 | 3 | |
| y | variable | 0 | 4 | |
| p | procedure | 0 | 2 | 4 |
| r | procedure | 0 | 14 | 5 |
| x | variable | 1 | 3 | |
| s | variable | 1 | 4 | |
| t | procedure | 1 | 10 | 4 |
监视窗口截图如下:

对于procedure类型的标识符,其在符号表中的adr字段的含义是:该过程在代码中的入口地址
adr值在block函数中生成和更新,
adr值生成在以下代码段由table[tx].adr = cx;语句完成,先为adr赋当前层代码开始位置作为初值
...
dx = 3; /* 三个空间用于存放静态链SL、动态链DL和返回地址RA */
tx0 = tx; /* 记录本层标识符的初始位置 */
table[tx].adr = cx; /* 记录当前层代码的开始位置 */
gen(jmp, 0, 0); /* 产生跳转指令,跳转位置未知暂时填0 */
...

而adr值更新在以下代码段由table[tx0].adr = cx;语句完成,由gen函数生成虚拟代码并持续更新cx后,在声明结束以后便可以知道过程的入口地址,于是将cx赋给adr更新其值即是该过程对应虚拟代码中入口地址
...
code[table[tx0].adr].a = cx; /* 把前面生成的跳转语句的跳转位置改成当前位置 */
table[tx0].adr = cx; /* 记录当前过程代码地址 */
table[tx0].size = dx; /* 声明部分中每增加一条声明都会给dx增加1,声明部分已经结束,dx就是当前过程数据的size */
cx0 = cx;
gen(ini, 0, dx); /* 生成指令,此指令执行时在数据栈中为被调用的过程开辟dx个单元的数据区 */
...

代码链接
https://gitee.com/WilliamSamShen/complier-concepts/tree/master/Lab/lab7