正在加载图片...
314 翁译原理及实践 China-pub.Com 下载 factor-一id中记号的串值记作factor.name。与P.代码不同,在叶产生式的节点上没有生成三地 址码(用"表示空串) 再次,我们让读者按表8-2所给出的等式写出表达式(x=x+3)+4的每一步的tacode,这个 表达式的tacode属性如下: t1=x+3 x=1 t2=t1+4 (这里假设mew1em以)用后序调用并且产生从t1开始的临时名)。注意x=x+3是怎样用临时名产 生两个三地址指令的。这是属性值总是为每一个子表达式产生一个临时名的结果,它包括了赋 值号的右边部分。 将代码生成看成一个合成字符串属性计算,对于清楚地显示语法树各部分代码系列的关系 以及比较不同的代码生成方法是很有用的,但它作为真实的代码生成技术是不实际的,这有 几个原因:首先,串连接的使用造成了过度的串拷贝因而浪费了内存(除非连接符做得非常复 杂),其次,通常希望产生几片代码作为代码产生的收益并且将这几片代码写入一个文件或将 它们插入一个数据结构(如四元式数组),这就需要语义动作,而语义动作又不与属性的标准后 序合成有牵连。最后,即使将代码看作是纯合成是有用的,但通常的代码生成很大程度上依 赖于继承属性,这将使得属性文法大大复杂化。由于这个原因,我们就不必麻烦再去写出实 现前面例子中的属性文法的代码了(即使是伪码)。相反地,在下一节中,我们将转向更直接的 代码生成技术。 8.2.2实际的代码生成 标准的代码生成或者涉及语法树后序遍历的修改,这棵语法树是由前面例子的属性文法所 包含的,或者如没有显式生成的语法树,则在分析中涉及了相等效的动作。基本算法由下面的 递归过程描述(用于二叉树,但容易将其推广到节点子树多于2的情况): procedure genCode (T:treenode ) begin if T is not nil then generate code to prepare for code of left child of T, genCode (left child ofT). generate code to prepare for code of right child of T. genCode (right child ofT). generate code to implement the action ofT. end 注意,这个递归遍历过程不仅有一个后序部分(产生实现T动作的代码),而且还有一个前序和 一个中序部分(为T的左右子树产生准备代码)。通常,T表示的每一个动作需要前序和中序准 备代码的稍微不同的一个版本。 为了详细地看清在一个特殊的例子中怎样构造产生代码的过程,考虑我们在这一节已用过 的简单算术表达式的语法,这个语法的抽象语法树的C语言定义如下所示: Kind】NodeKind f a c t o r→i d 中记号的串值记作f a c t o r. n a m e。与P -代码不同,在叶产生式的节点上没有生成三地 址码(用" "表示空串)。 再次,我们让读者按表8 - 2所给出的等式写出表达式 ( x = x + 3 ) + 4的每一步的t a c o d e,这个 表达式的t a c o d e属性如下: t1 = x+3 x = t1 t2 = t1+4 (这里假设n e w t e m p( )用后序调用并且产生从t 1开始的临时名)。注意x = x + 3是怎样用临时名产 生两个三地址指令的。这是属性值总是为每一个子表达式产生一个临时名的结果,它包括了赋 值号的右边部分。 将代码生成看成一个合成字符串属性计算,对于清楚地显示语法树各部分代码系列的关系 以及比较不同的代码生成方法是很有用的,但它作为真实的代码生成技术是不实际的,这有 几个原因:首先,串连接的使用造成了过度的串拷贝因而浪费了内存 (除非连接符做得非常复 杂),其次,通常希望产生几片代码作为代码产生的收益并且将这几片代码写入一个文件或将 它们插入一个数据结构(如四元式数组),这就需要语义动作,而语义动作又不与属性的标准后 序合成有牵连。最后,即使将代码看作是纯合成是有用的,但通常的代码生成很大程度上依 赖于继承属性,这将使得属性文法大大复杂化。由于这个原因,我们就不必麻烦再去写出实 现前面例子中的属性文法的代码了 (即使是伪码)。相反地,在下一节中,我们将转向更直接的 代码生成技术。 8.2.2 实际的代码生成 标准的代码生成或者涉及语法树后序遍历的修改,这棵语法树是由前面例子的属性文法所 包含的,或者如没有显式生成的语法树,则在分析中涉及了相等效的动作。基本算法由下面的 递归过程描述(用于二叉树,但容易将其推广到节点子树多于 2的情况): p ro c e d u re genCode ( T: t reenode ) ; b e g i n if T is not nil t h e n generate code to pre p a re for code of left child of T; genCode (left child of T ) ; generate code to pre p a re for code of right child of T; genCode (right child of T ) ; generate code to implement the action of T; e n d; 注意,这个递归遍历过程不仅有一个后序部分 (产生实现T 动作的代码),而且还有一个前序和 一个中序部分(为T 的左右子树产生准备代码 )。通常,T 表示的每一个动作需要前序和中序准 备代码的稍微不同的一个版本。 为了详细地看清在一个特殊的例子中怎样构造产生代码的过程,考虑我们在这一节已用过 的简单算术表达式的语法,这个语法的抽象语法树的 C语言定义如下所示: typedef enum { Plus, Assign } Optype; typedef enum { OpKind, ConstKind, IdKind } NodeKind; 3 1 4 编译原理及实践 下载
<<向上翻页向下翻页>>
©2008-现在 cucdc.com 高等教育资讯网 版权所有