将语义分析和中间代码生成统称为语义翻译,而语义翻译和语法分析统称为语法制导翻译
语法制导翻译使用CFG来引导对语言的翻译, 是一种面向文法的翻译技术。
语法制导翻译的基本思想包括1)如何表示语义信息?2)如何计算语义属性?
Q1:如何表示语义信息?
为CFG中的文法符号设置语义属性,用来表示语法成分对应的语义信息
比如说一个变量,它的属性包括变量的类型、存放位置和值等。
Q2:如何计算语义属性?
文法符号的语义属性值是用与文法符号所在产生式 (语法规则)相关联的语义规则来计算的 。
对于给定的输入串x ,构建x的语法分析树,并利用与产生式(语法规则)相关联的语义规则来计算分析树 中各结点对应的语义属性值。
将语义规则同语法规则(产生式)联系起来要 涉及两个概念:
语法制导定义( Syntax-Directed Definitions, SDD )
语法制导翻译方案( Syntax-Directed Translation Scheme , SDT )
语法制导定义(SDD)
SDD是对CFG的推广:
如果X是一个文法符号,a是X的一个属性,则用 X.a表示属性a在某个标号为X的分析树结点上的值
上述基础规则为一个定义变量的产生式,T的属性包括type,L和L1表示同一个符号,由第一个语义规则得出L的inh属性由T的type属性定义。
语法制导翻译方案(SDT)
SDT是在产生式右部嵌入了程序片段的CFG,这 些程序片段称为语义动作。按照惯例,语义动作放在花括号内。
第一句表示:当我们分析出T的时候,我们就可以利用T的type值来计算L的inh属性值。
一个语义动作在产生式中的位置决定了这个动作的执行时间
SDD与SDT
SDD
SDT
SDD可以将每个文法符号和一个语义属性集合相关联,而文法符号的属性可以分为两种:(1)综合属性(synthesized attribute) ;(2)继承属性(inherited attribute)
(1)综合属性(synthesized attribute) **
在分析树结点N上的非终结符A的综合属性只能通过N的子结点或N本身的属性值来定义
产生式 E → E1 + T
语义规则 E.val =E1.val + T.val
终结符可以具有综合属性**。终结符的综合属性值是由词法分析器提供的词法值,因此在SDD中没有计算终结符属性值的语义规则。
**(2)继承属性(inherited attribute) **
在分析树结点N上的非终结符A的继承属性只能通过 N的父结点、N的兄弟结点或N本身的属性值来定义 。
产生式 D →T L
语义规则 L.inh= T.typeL
终结符没有继承属性。终结符从词法分析器处获得的属性值被归为综合属性值。
例:带有综合属性的SDD
其中print(E.val) 为副作用,只是表示打印当前E的值,并不进行属性传递。
一个没有副作用的SDD有时也称为属性文法,属性文法的规则仅仅通过其它属性值和常量来定义一个属性值。
例:带有继承属性L.in的SDD
其中L.inh=real由兄弟节点传递过来,又传递给子节点。
SDD为CFG中的文法符号设置语义属性。对于给定的输入串x,应用语义规则计算分析树中各 结点对应的属性值。
Q:按照什么顺序计算属性值?
A:语义规则建立了属性之间的依赖关系,在对语法分析树节点的一个属性求值之前,必须首先求出这个属性值所依赖的所有属性值。
他们的依赖关系可以使用依赖图来表示,依赖图是一个描述了分析树中结点属性间依赖关系的有向图 ,分析树中每个标号为X的结点的每个属性a都对应 着依赖图中的一个结点 ,如果属性X.a的值依赖于属性Y.b的值,则依赖图 中有一条从Y.b的结点指向X.a的结点的有向边。
如上图中的依赖图,节点右边的属性为综合属性,节点左边的为继承属性。
对于只具有综合属性的SDD,可以按照任何自 底向上的顺序计算它们的值;对于同时具有继承属性和综合属性的SDD,不 能保证存在一个顺序来对各个节点上的属性进 行求值;
如:
此时产生了环就无法保证有一个顺序对属性进行推导,如果图中没有环,那么至少存在一个拓扑排序,存在拓扑序列的才可以分析。
从计算的角度看,给定一个SDD,很难确定是否存在某 棵语法分析树,使得SDD的属性之间存在循环依赖关系,幸运的是,存在一个SDD的有用子类,它们能够保证对每棵语法分析树都存在一个求值顺序,因为它们不允 产生带有环的依赖图,不仅如此,接下来介绍的两类SDD可以和自顶向下及自 底向上的语法分析过程一起高效地实现 :
S-属性
仅仅使用综合属性的SDD称为S属性的SDD,或S-属性定义、 S-SDD
如果一个SDD是S属性的,可以按照语法分析树节点的任何 自底向上顺序来计算它的各个属性值 。
L-属性
L-属性定义(也称为L属性的SDD或L-SDD)的 直观含义:在一个产生式所关联的各属性之间, 依赖图的边可以从左到右,但不能从右到左 (因此称为L属性的,L是Left的首字母)
一个SDD是L-属性定义,当且仅当它的每个属性要 么是一个综合属性,要么是满足如下条件的继承属 性:假设存在一个产生式A→X1X2…Xn,其右部符 号Xi (1≤i≤n)的继承属性仅依赖于下列属性:
每个S-属性定义都是L-属性定义
语法制导翻译方案(SDT)是在产生式右部中嵌入了 程序片段(称为语义动作)的CFG。SDT可以看作是SDD的具体实施方案,本节主要关注如何使用SDT来实现两类重要的SDD, 因为在这两种情况下,SDT可在语法分析过程中实现 :
将一个S-SDD转换为SDT的方法:将每个语义动作 都放在产生式的最后。例如:
即在规约的时候执行语义动作
如果一个S-SDD的基本文法可以使用LR分析技术, 那么它的SDT可以在LR语法分析过程中实现 。
为了在进行LR分析的同时进行语义分析,需要将语义动作中的抽象定义式改写成具体可执行的栈操作
先将top-2给A,然后将top-2,top-1,top的值相加后给到top-2,最终把top-2的设置为top的操作。
之所以第二个语义动作中使用top-2,是因为+号也算一个符号,而并不是作为一个数参与到其中,所以没有top-1。
假设输入为3*5+4,则分析过程如下:
将L-SDD转换为SDT的规则:
如果一个L-SDD的基本文法可以使用LL分析技术, 那么它的SDT可以在LL或LR语法分析过程中实现 :
为每个非终结符A构造一个函数,A的每个继承属性对应该函数的一个形参, 函数的返回值是A的综合属性值 。对出现在A产生式右部中的 每个文法符号的每个属性 都设置一个局部变量。
上图为非终结符T’的函数,T’inh为继承属性,所以作为形参,对出现在A产生式右部中的 每个文法符号的每个属性 都设置一个局部变量。
非终结符A的代码根据当前的输入决定使用哪个产 生式
如果一个文法是LL的,则可以进行转化。给定一个以LL文法为基础的L-SDD,可以 修改这个文法,并在LR语法分析过程中计 算这个新文法之上的SDD。