正在加载图片...
312 翁译原理及实践 China-pub.co 下载 型结果。stp指令对应于前面三地址码的halt指令。 )P代码和三地址码的比较P代码在许多方面比三地址码更接近于实际的机器码。P代 码指令也需要较少地址:我们已见过的都是一地址或零地址指令,另一方面,P代码在指令数 量方面不如三地址码紧凑,P.代码不是自包含的,指令操作隐含地依赖于栈(隐含的栈定位实 际上就是“缺省的”地址),栈的好处是在代码的每一处都包含了所需的所有临时值,编译器 不用如三地址码中那样为它们再分配名字。 2)P代码的实现历史上,P代码已经大量地作为文本文件生成,但前面的三元地址码的 内部数据结构描述(三元式和四元式)也能作用于P代码的修改版。 8.2基本的代码生成技术 本节讨论代码生成的基本方法,在下一节,我们将针对单个的语言结构进行代码生成。 8.2.1作为合成属性的中间代码或目标代码 中间代码生成(或没有中间代码的直接目标代码生成)能被看作是一个属性计算,这类似于 第6章中研究的许多属性问题,实际上假如生成代码被看作一个字符串属性(每条指令用换行符 分隔),这个代码就成了一个合成属性并能用属性文法定义,并且能在分析期间直接生成或者 通过语法树的后序遍历生成。 为了看清楚三地址码或P代码怎样被作为合成属性定义,考虑下边的文法,它代表了C表 达式的一个子集。 exp→id=exp|aep aexp-aexp +factor factor factor-(exp)numl id 这个文法仅包含了两个操作,赋值(=)和加法(+)°。记号i代表简单标识符,记号nm代表了 表示整数的简单数字序列。这两个记号被假设成有一个预先计算过的s1al属性,它可以是字 符串或词(例如“42”是nm, “xtemp”是id), )P代码我们首先考虑P代码的情况,由于不需要产生临时变量名,属性文法会简单些, 然而,嵌套赋值的存在是一个复杂因素。在这种情况下,我们希望保留被存的值作为赋值表达 式的结果值,然而标准的P代码指令st。是有害的,因为所赋的值会丢掉(P代码在这里显示出 了它pascal源,在pascali源代码中不存在嵌套的赋值语句)。我们通过引入一个无害的存储 (nondestructive store)指令stn来解决这个问题,stn和sto一样,都假设栈顶有一个值且下面 有一地址。st将值存入那个地址,但在丢弃那个地址时栈顶上仍保留了那个值。表8-l是使 用这个新的指令后P代码属性的属性文法。在那幅图中,已经用属性名pcod表示P-代码串, 并已把两个不同的符号用于串的连接:+表示所连的串之间不能在同一行,川表示连接一个串 用空格相隔。 我们将跟踪某个例子的pcode属性计算留给读者并写出来,例如:表达式(x=x+3)+4有如 下的pcode属性: 。这个例子中的赋值有如下的语义:x=心将e的值存入x,该赋值的结果值是。: 型结果。s t p指令对应于前面三地址码的h a l t指令。 1) P -代码和三地址码的比较 P -代码在许多方面比三地址码更接近于实际的机器码。 P -代 码指令也需要较少地址;我们已见过的都是一地址或零地址指令,另一方面, P -代码在指令数 量方面不如三地址码紧凑, P -代码不是自包含的,指令操作隐含地依赖于栈 (隐含的栈定位实 际上就是“缺省的”地址 ),栈的好处是在代码的每一处都包含了所需的所有临时值,编译器 不用如三地址码中那样为它们再分配名字。 2) P -代码的实现 历史上,P -代码已经大量地作为文本文件生成,但前面的三元地址码的 内部数据结构描述(三元式和四元式)也能作用于P -代码的修改版。 8.2 基本的代码生成技术 本节讨论代码生成的基本方法,在下一节,我们将针对单个的语言结构进行代码生成。 8.2.1 作为合成属性的中间代码或目标代码 中间代码生成(或没有中间代码的直接目标代码生成 )能被看作是一个属性计算,这类似于 第6章中研究的许多属性问题,实际上假如生成代码被看作一个字符串属性 (每条指令用换行符 分隔),这个代码就成了一个合成属性并能用属性文法定义,并且能在分析期间直接生成或者 通过语法树的后序遍历生成。 为了看清楚三地址码或 P -代码怎样被作为合成属性定义,考虑下边的文法,它代表了 C表 达式的一个子集。 e x p→i d = e x p | a e x p a e x p→a e x p + factor | f a c t o r f a c t o r→( exp ) | n u m | i d 这个文法仅包含了两个操作,赋值 (=)和加法(+) 。记号i d代表简单标识符,记号n u m代表了 表示整数的简单数字序列。这两个记号被假设成有一个预先计算过的 s t rv a l属性,它可以是字 符串或词(例如“4 2”是n u m,“x t e m p”是i d)。 1) P -代码 我们首先考虑P -代码的情况,由于不需要产生临时变量名,属性文法会简单些, 然而,嵌套赋值的存在是一个复杂因素。在这种情况下,我们希望保留被存的值作为赋值表达 式的结果值,然而标准的P -代码指令s t o是有害的,因为所赋的值会丢掉( P -代码在这里显示出 了它p a s c a l源,在 p a s c a l源代码中不存在嵌套的赋值语句 )。我们通过引入一个无害的存储 (nondestructive store)指令s t n来解决这个问题,s t n和s t o一样,都假设栈顶有一个值且下面 有一地址。s t n将值存入那个地址,但在丢弃那个地址时栈顶上仍保留了那个值。表 8 - 1是使 用这个新的指令后 P -代码属性的属性文法。在那幅图中,已经用属性名 p c o d e表示P -代码串, 并已把两个不同的符号用于串的连接: + +表示所连的串之间不能在同一行, | |表示连接一个串 用空格相隔。 我们将跟踪某个例子的p c o d e属性计算留给读者并写出来,例如:表达式 ( x = x + 3 ) + 4有如 下的p c o d e属性: lda x lod x 3 1 2 编译原理及实践 下载 这个例子中的赋值有如下的语义:x = e将e的值存入x,该赋值的结果值是e
<<向上翻页向下翻页>>
©2008-现在 cucdc.com 高等教育资讯网 版权所有