云题海 - 专业文章范例文档资料分享平台

当前位置:首页 > 第八章 语法制导翻译和中间代码生成

第八章 语法制导翻译和中间代码生成

  • 62 次阅读
  • 3 次下载
  • 2025/5/8 1:11:53

第8章 语法制导翻译和中间代码生成

甚至FORTRAN中的计算GOTO和赋值GOTO也可看做是一种开关语句。

我们假定要讨论的开关语句的形式为: switch E of case V1:S1 case V2:S2 …

case Vn-1:Sn-1

default:Sn end

这里的E是一个表达式,也称为选择子。开关语句是分情形选择机制,在E被计算之后,测试它的值符合哪种case中的值,而执行和该值相关的语句,并做相应的转移。如果E的值不能与任何Vi(1≤i≤n-1)匹配,便执行\时的语句。 直观上看,case语句翻译成如下的一连串条件转移语句。 t∶=E; L1:if t≠V1 goto L2; S1;

goto next;

L2:if t≠V2 goto L3; S2

goto next;

… Ln-1:if t≠Vn-1 goto Ln; Sn-1;

goto next; Ln:Sn;

next:

8.6.3 for循环语句

除了while do语句外,很多程序设计语言具有下面形式的循环语句:

for i∶=E1 step E2 until E3 do S1

为了简单起见,假定E2总是正的。在这种假定下,上述循环句的意义等价于: i∶=E1;

goto OVER; AGAIN: i∶=i+E2; OVER: if i≤E3 then

begin S1; goto AGAIN end;

8.6.4 goto语句

多数程序语言中的转移是通过标号和goto语句实现的。带标号语句的形式是L∶S;goto语句的形式是goto L。 当L∶S;语句被处理之后,标号L是\定义了\的。即在符号表中,将登记L的项的\地址\栏中登上语句S的第一个四元式的地址。

如果goto L是一个向上转移的语句,那么,当编译程序碰到这个语句时,L必是已定义了的。通过对L查找符号表获得它的定义地址p,编译程序可立即产生出相应于这个goto L的四元式如(j,-,-,p)。

如果goto L是一个向下转移的语句,也就是说,标号L尚未定义,那么,若L是第一

第8章 语法制导翻译和中间代码生成

次出现,则把它填进符号表中并标志上\未定义\。由于L尚未定义,对goto L只能产生一个不完全的四元式(goto -),它的转移目标须待L定义时再回填进去。在这种情况下,必须把所有那些以L为转移目标的四元式的地址全都记录下来,以便一旦L定义时就可对这些四元式进行回填。我们将采用如图8.13所示的拉链办法,把所有以L为转移目标的四元式串在一起。链的首地址放在符号表中L的\地址\栏中。建链的方法是:若goto L中的标号L尚未在符号表中出现,则把L填入表中,置L的\定义否\标志为\未\,把nextstat填进L的地址栏中作为新链首,然后,产生四元式(goto 0),其中0为链尾标志。若L已在符号表中出现(但\定义否\标志为\未\),则把它的地址栏中的编号(记为q)取出,把nextstat填进该栏作新链首,然后,产生四元式(goto q)。

图 8.13 未定义标号的引用链

一旦标号L定义时,我们将根据这条链回填那些待填转移目标的四元式。一般而言,假定用下面的产生式来定义标号语句

S→label S label→i:

那么,当用label→i:进行归约时,应做如下的语义动作:

1.若i所指的标识符(假定为L)不在符号表中,则把它填入,置\类型\为\标号\,\定义否\为\已\,\地址\为nextstat。

2.若L已在符号表中但\类型\不为\标号\或\定义否\为\已\,则报告出错。

3.若L已在符号表中,则把标志\未\改为\已\,然后,把地址栏中的链首(记为q)取出,同时把nextstat填在其中,最后,执行回填。

翻译goto语句时,还有两点必须注意,第一:是相同名字的标号可以在不同名字作用域中定义。如: (1) begin (2) L:begin (3) goto L; (4) …… (5) L:… (6) end (7) end

第8章 语法制导翻译和中间代码生成

当在行(3)处理goto语句时,不知道L的作用域到底是哪个,(因为还没见到语句(5)),因此一定要延迟解决这个标号的使用。

另外有些转移标号是非法的,如下例: (1) for i∶=1 to 10 do (2) begin goto L; (3) for j∶=1 to 20 do (4) begin goto L; … …

(n) L: end {for j} end {for i}

处理到第(n)行后,第(4)行的goto目标得以解决。而第(2)行的goto L是非法的,但只有当循环关闭时才能确定。

还要注意的问题是转移出分程序或过程外的goto语句,编译程序需要很多额外的编码,比如要恢复和保留一些运行环境等,这在后面(第10章)介绍了运行环境时,可能会理解更深些。

第8章 语法制导翻译和中间代码生成

8.7 简单说明语句的翻译

程序设计语言中的说明语句旨在定义各种形式的有名实体,如常量、变量、数组、记录(结构)、过程、子程序等等,说明语句的种类也多,对象说明、变量说明、类型说明、过程说明等等。编译程序把说明语句中定义的名字和性质登记在符号表中,用以检查名字的引用和说明是否一致。许多说明语句的翻译并不生成相应的目标代码。过程说明和动态数组的说明有相应的代码。

简单说明句的翻译

程序设计语言中最简单的说明句的语法描述为: D→integer〈namelist〉|real〈namelist〉

〈namelise〉→〈namelist〉,id|id

即使用关键字integer和real定义一串名字的性质。对这种说明句的翻译是指在符号表中登录该名和性质。

用上述文法来制导翻译(自下而上)存在着这样一个问题,我们只能在把所有的名字都归约成namelist后才能把它们的性质登记进符号表。这意味着namelist必须用一个队列(或栈)来保存所有这些名字。但我们可以把上述的文法改写成: D→D1,id |integer id

|realid

这样,就能把所说明的性质及时地告诉每个名字id,或者说,每当读进一个标识符时,就可以把它的性质登记在符号表中,不用把它们集中起来最后再成批登记了。 现在来定义这些产生式所对应的语义动作,给非终结符D一个语义变量D.ATT,用以记录说明句所引入的名字的性质(int还是real),使用过程enter(id,A)把名字id和性质A登录在名表中。

(1) D→integerid {enter(id,int); D.ATT∶=int} (2) D→realid {enter(id,real); D.ATT∶=real} (3) D→D1,id {enter(id,D1.ATT); D.ATT∶=D.ATT}

1

  • 收藏
  • 违规举报
  • 版权认领
下载文档10.00 元 加入VIP免费下载
推荐下载
本文作者:...

共分享92篇相关文档

文档简介:

第8章 语法制导翻译和中间代码生成 甚至FORTRAN中的计算GOTO和赋值GOTO也可看做是一种开关语句。 我们假定要讨论的开关语句的形式为: switch E of case V1:S1 case V2:S2 … case Vn-1:Sn-1 default:Sn end 这里的E是一个表达式,也称为选择子。开关语句是分情形选择机制,在E被计算之后,测试它的值符合哪种case中的值,而执行和该值相关的语句,并做相应的转移。如果E的值不能与任何Vi(1≤i≤n-1)匹配,便执行\时的语句。 直观上看,case语句翻译成如下的一连串条件转移语句。 t∶=E; L1:if t≠V1 goto L2; S1; goto next;

× 游客快捷下载通道(下载后可以自由复制和排版)
单篇付费下载
限时特价:10 元/份 原价:20元
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信:fanwen365 QQ:370150219
Copyright © 云题海 All Rights Reserved. 苏ICP备16052595号-3 网站地图 客服QQ:370150219 邮箱:370150219@qq.com