第6章 语法制导翻译和中间代码生成Tsu版电Word文档下载推荐.docx
- 文档编号:17305074
- 上传时间:2022-12-01
- 格式:DOCX
- 页数:16
- 大小:21.83KB
第6章 语法制导翻译和中间代码生成Tsu版电Word文档下载推荐.docx
《第6章 语法制导翻译和中间代码生成Tsu版电Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《第6章 语法制导翻译和中间代码生成Tsu版电Word文档下载推荐.docx(16页珍藏版)》请在冰豆网上搜索。
//NI表示整常数表长度
floatconst_real_table[NR];
//NR表示实常数表长度
②常数表使用
③常数表地址使用说明
6.3中间代码
6.3.1三元式
㈠格式
OPARG1ARG2
运算符
第一运算量
第二运算量
㈡优点
代码生成无需引进临时变量。
㈢缺点
调整困难。
6.3.2四元式
OPARG1ARG2RESULT
运算结果
调整方便。
在生成中间代码时引进大量临时变量。
㈣临时变量的处理
①将Ti作为标识符存入符号表
②设置临时变量表
6.4说明语句(简单变量)的翻译
㈠文法及修改
<
语句>
→integer<
标识符表>
S→aV
→real<
S→cV
→<
标识符V→V,i
→标识符V→i
为了避免使用队列,文法修改如下:
说明>
S→V
标识符V→V,i
→integer标识符V→ai
→real标识符V→ci
用这个文法来制导翻译,每当读进一个标识符,就可把它的变量名及其性质填入符号表,没有必要集中起来成批处理。
㈡语义子程序
V→ai{
fill_sym_table(wval,0,0);
//填写符号表(标识符名,简单变量,整型)
V.cat=0;
//保存语义值(简单变量)
V.type=0;
//保存语义值(整型)
}
V→ci{
fill_sym_table(wval,0,1);
//保存语义值(简单变量)
V.type=1;
//保存语义值(实型)
V→V
(1),i{
fill_sym_table(wval,V
(1).cat,V
(1).type);
//继承V
(1)的语义信息
V.cat=V
(1).cat;
V.type=V
(1).type;
S→V{;
}//空
①语义变量.cat和.type
②fill_sym_table函数
㈢手工计算
intergera,b
6.5整型算术表达式及赋值语句的翻译
㈠文法
→标识符=<
整型算术表达式>
S→i=X
+<
项>
X→X+Y
X→Y
*<
因子>
Y→Y*Z
Y→Z
→(<
)Z→(X)
→-<
Z→-Z
→标识符Z→i
→无符号整常数Z→x
S→i=X{
gen_code(=,X.addr,0,sym_entry(wval));
//产生四元式。
X→X
(1)+Y{
X.addr=get_tmpvar(0);
//申请临时变量(整型)
gen_code(+,X
(1).addr,Y.addr,X.addr);
//产生四元式
X→Y{
X.addr=Y.addr;
//传递语义值
Y→Y
(1)*Z{
Y.addr=get_tmpvar(0);
gen_code(*,Y
(1).addr,Z.addr,Y.addr);
//产生四元式
Y→Z{
Y.addr=Z.addr;
//传递语义值
Z→(X){
Z.addr=X.addr;
Z→-Z
(1){
Z.addr=get_tmpvar(0);
gen_code(-,Z
(1).addr,0,Z.addr)//产生四元式
Z→i{
Z.addr=sym_entry(wval);
//wval表示单词的值
Z→x{
Z.addr=const_int_entry(atoi(wval));
//wval表示单词的值,atoi为C语言系统函数。
①get_tmpvar函数
②sym_entry函数
③gen_code函数
④const_int_entry(wval)函数
a=-b*(c+2)
6.6混合型算术表达式及赋值语句的翻译
㈠概述
①拒绝接受混合运算,报错(如标准Fortran语言)。
②允许混合运算,在运算前将它们转换成同一类型(例Pascal语言、C语言)。
㈡引入定点、浮点和类型转换运算符
●运算符itr作用:
将整型量转换为实型量。
●运算符+r、+i、…,分别表示实数加、整数加、…。
设源程序为
inta,b;
realc,d;
c=d+a*b
符号表略,相应的四元式代码为
(*i,&
a,&
b,&
T1)
(itr,&
T1,0,&
T2)
(+r,&
d,&
T2,&
T3)
(=r,&
T3,0,&
c)
㈢文法
算术表达式>
S→i=X
X→X+Y
X→Y
)Z→(X)
→标识符Z→i
→无符号实常数Z→y
㈣语义子程序(X→X+Y)
void*t;
X→X
(1)+Y{
if(X
(1).type==Y.type)//类型相同
if(X
(1).type==0){//intopint
gen_code(+i,X
(1).addr,Y.addr,X.addr);
X.type=0;
else{//real=real
X.addr=get_tmpvar
(1);
gen_code(+r,X
(1).addr,Y.addr,X.addr);
X.type=1;
else{//类型不相同
//结果类型均为实型
t=get_tmpvar
(1);
//申请临时变量(实型),用于类型转换。
if(X
(1).type==0){//intopreal
gen_code(itr,X
(1).addr,0,t);
gen_code(+r,t,Y.addr,X.addr);
}
else{//realopint
gen_code(itr,Y.addr,0,t);
gen_code(+r,X
(1).addr,t,X.addr);
}
6.7布尔表达式的翻译
㈠布尔表达式作用
①控制语句的条件ifx+y<
10gotoL
②计算逻辑值d=x>
y
㈡程序设计语言的优先级和结合性
①标准Fortran语言(按表达式类别分级)
②Pascal语言(共分4级,同级运算优先性相同)
③C语言(共分17级,同级运算优先性相同)
㈢描述布尔表达式文法
以标准FORTRAN语言为基础,适当化简。
E→E∨E|E∧E|(E)|~E|XrX|X
X→X+X|X*X|(X)|-X|i|x
㈣布尔表达式计算方法
①根据优先性和结合性按步计算
②优化计算法
㈤布尔表达式的第一种翻译法
同算术表达式
㈥布尔表达式的第二种翻译法
①概述
②实例引入
③问题的提出
④解决办法
1)修改文法
2)引进语义变量.tc和.fc保存未填转移目标的四元式地址
3)变量和函数
●nxq指示器
●链合并函数merg(p1,p2)
●回填函数backpatch(p,t)
⑤语义子程序
E→X{
E.tc=nxq;
gen_code(jnz,X.addr,0,0);
E.fc=nxq;
gen_code(jmp,0,0,0);
Er→XrX
(1){
E.tc=nxq;
E.tc:
=nxq+1;
gen_code(jr,X.addr,X
(1).addr,0);
gen_code(jmp,0,0,0)
E→~E
(1){//真假出口链链首互换
E.tc=E
(1).fc;
E.fc=E
(1).tc;
E→(E
(1)){//传递真假出口链链首
E.tc=E
(1).tc;
E.fc=E
(1).fc;
EA→E∧{
backpatch(E.tc,nxq);
//可填真出口(下一个四元式地址)
EA.fc=E.fc;
//传递假出口链链首
E→EAE
(2){
E.tc=E
(2).tc;
//传递真出口链链首
E.fc=merge(EA.fc,E
(2).fc);
//合并假出口链
}
EO→E
(1)∨{
EO.tc=E
(1).tc;
backpatch(E
(1).fc,nxq);
//可填假出口(下一个四元式地址)
E→EOE
(2){
E.tc=merge(EO.tc,E
(2).tc);
//合并真出口链
E.fc=E
(2).fc;
//传递假出口链链首
X→i{
X.addr=sym_entry(wval);
//wval表示单词的值。
X→x{
X.addr=const_int_entry(atoi(wval));
//wval表示单词的值。
⑥手工计算
a∨b∨c
6.8标号和无条件转移语句的翻译
㈠标号和goto语句
①向后转移(程序首部方向)
②向前转移(程序尾部方向)
㈡文法及修改
<
→标识符:
S→i:
S
→goto标识符S→gi
标号用于标领一个语句,为了能及时填写标号的地址,将文法修改如下:
标号>
S→FS
→标识符:
F→i:
㈢问题的提出和解决办法
①gotoL99是一个向后转移语句
②gotoL99是一个向前转移语句
●L99第一次出现
●L99非第一次出现
㈣语义子程序(不考虑出错情况)
F→i:
{
if(sym_entry(wval)==0){//标号未进入符号表,属先定位后使用。
fill_sym_table(wval,1,1);
//将标号名填入符号表且标记已定位
(*sym_entry(wval)).addr=nxq;
//nxq为标号i标领的语句第一个四元式地址
else{//标号已进入符号表,属先使用后定位,此时应回填。
backpatch((*sym_entry(wval)).addr,nxq);
//回填
(*sym_entry(wval)).type=1;
//标号已定位
S→gi{
if(sym_entry(wval)==0){/*标号未进入符号表,属先使用后定位且是第一个向前转移语句,此时产生新链,链中仅有一个四元式。
*/
fill_sym_table(wval,1,0);
//将标号名填入符号表且标记为未定位
//下一个无条件转移四元式地址(编号)
//产生不完全四元式
else{//标号已进入符号表
if((*sym_entry(wval)).type==1)//标号已进入符号表且定位,直接产生四元式。
gen_code(jmp,0,0,(*sym_entry(wval)).addr);
else{/*标号已进入符号表,但未定位,即有以该标号为转移目标的单向链存在,将新产生的四元式插入单向链。
t=(*sym_entry(wval)).addr;
(*sym_entry(wval)).addr=nxq;
gen_code(jmp,0,0,t);
S→FS{;
}//暂时可认为是空
6.9控制语句的翻译
㈡语义变量E.fc的传递
㈢引进语义变量.chain
6.9.1if-then语句的翻译
→if<
布尔表达式>
then<
endifS→fEtS
(1)j
<
→标识符=<
S→i=X
为了能及时回填真出口,文法修改如下:
C→if<
thenC→fEt
→C<
endifS→CS
(1)j
C→fEt{
backpatch(E.tc,nxq);
//回填真出口
C.chain=E.FC;
//假出口是离开if-then语句
S→CS
(1)j{
S.chain=merge(C.chain,S
(1).chain);
//S
(1)中可能含有离开if_then的四元式
S→i=X{//赋值语句按顺序执行,它的四元式代码中不存在需回填转移目标的四元式。
S.chain=0;
gen_code(=,X.addr,0,sym_entry(wval));
ifathenb=dendif
6.9.2if-then-else语句的翻译
else<
S→fEtS
(1)eS
(2)
当扫描到then可填真出口,当扫描到else可填假出口,当S
(1)执行完毕,应离开if-then-else语句。
为了能及时回填四元式,修改如下:
→TP<
S→TPS
(2)
TP→C<
elseTP→CS
(1)e
thenC→fEt
TP→CS
(1)e{//TP可理解为then-processed
t=nxq;
//t为下一条四元式地址,即(jmp,0,0,0)的地址(编号)。
gen_code(jmp,0,0,0);
//执行完S
(1)后,离开if-then-else语句。
backpatch(C.chain,nxq);
//回填假出口,这里C.chain相当于E.FC,此时nxq=t+1。
TP.chain=merge(S
(1).chain,t);
//S
(1)中可能含有离开if_then-else的四元式
S→TPS
(2){
S.chain=merge(TP.chain,S
(2).chain);
//S
(2)中可能含有离开if_then-else的四元式
C→fEt{…}//见6.9.1
ifathenb=celseb=d
6.9.3while-do语句的翻译
→while<
do<
S→wEdS
(1)
为了便于语义分析,修改如下:
W→whileW→w
Wd→W<
doWd→WEd
→Wd<
S→WdS
(1)
W→w{
W.quad=nxq;
//记录E的第一个四元式编号
Wd→WEd{//Wd可理解为while-do
backpatch(E.TC,nxq);
Wd.chain=E.fc;
//传递假出口、即while-do的出口。
Wd.quad=W.quad;
//传递E的第一个四元式地址
S→WdS
(1){
backpatch(S
(1).chain,Wd.quad);
/*回填S
(1).chain链,因S
(1)可能是控制语句,离开S
(1)的四元式的转移目标是E的第一个四元式。
*/
gen_code(jmp,0,0,Wd.quad);
//生成转向E首址的无条件转移指令
S.chain=Wd.chain;
//传递假出口、即while-do的出口。
whileadoifbthenc=dendif
6.9.4复合语句的翻译
→begin<
语句串>
endS→{L}
;
L→L
(1);
L→S
分号意味着一个语句的结束,当扫描到分号,就可回填转移目标。
为了能及时回填chain链,文法修改如下:
→LS<
L→LSS
LS→<
LS→L;
L→S{
L.chain=S.chain;
//传递
Ls→L;
backpatch(L.chain,nxq);
//回填
L→LsS{//LS表示L-S
L.chain=S.chain//因前一语句L已回填,而当前语句S尚未回填,故需传递。
}
S→{L}{
S.chain=L.chain;
//传递
P→{L}{
//填写最后一个语句的chain链
gen_code(halt,0,0,0);
//产生停机指令
㈢例子
设源程序为
begin
ifathenb=10endif;
whilec>
ddo
begin
c=c-1;
d=d+1
end
end
根据上述语义子程序,其相应四元式序列为:
⑴(jnz,&
a,0,03)//if
⑵(jmp,0,0,04)
⑶(=,&
10,0,&
b)
⑷(j>
&
c,&
d,06)//while
⑸(jmp,0,0,011)
⑹(-,&
1,&
T1)
⑺(=,&
T1,0,&
c)
⑻(+,&
d,&
T2)
⑼(=,&
T2,0,&
d)
⑽(jmp,0,0,4)
⑾(halt,0,0,0)
6.10小结
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第6章 语法制导翻译和中间代码生成Tsu版电 语法 制导 翻译 中间 代码 生成 Tsu