1.语法制导定义
语法制导定义是一个上下文无关文法和属性及规则的结合。属性和文法符号相关联,而规则和产生式相关联。如果X是一个符号而a是X的一个属性,那么我们用X.a来表示在某个标号为X的分析树结点的值。
2.继承属性和综合属性
1).综合属性:在分析树结点N上的非终结符号A的综合属性是由N上的产生式所关联的语义规则来定义的。请注意,这个产生式的头一定是A。结点N上的综合属性只能通过N的子节点或N本身的属性来定义。
2).继承属性:在分析树结点N上的非终结符号B的继承属性是由N的父节点上的产生式所关联的语义规则来定义的。请注意,这个产生式的体中必然包含符号B。结点N上的继承属性只能通过N的父节点,N本身和N的兄弟节点上的属性值来定义。
我们不允许结点N上的继承属性通过N的子节点上的属性值来定义,但是我们语序结点N上的一个综合属性通过结点N本身的继承属性来定义。终结符号可以具有综合属性,但是不能有继承属性。终结符号的属性值是由词法分析器提供的词法值,在SDD中没有计算终结符号的属性值的语义规则。
3.SDD的求值顺序
依赖图描述了某个语法分析树中的属性实例之间的信息流。从一个属性实例到另一个实例的边表示计算第二个属性实例时需要第一个属性实例的值。图中的边表示语义规则所蕴含的约束。更详细的说:
- 对于每个语法分析树的结点,比如一个标号为文法符号X的结点,和X关联的每个属性都在依赖图中有一个节点。
- 假设和产生式p关联的语义规则通过X.c的值定义了综合属性A.b的值(这个规则定义A.b时可能还用到了X.c之外的其他属性)。那么,相应的依赖图中有一条从X.c到A.b的边。更准确地讲,在每个标号为A且应用了产生式p的结点N上,创建一条从该产生式体中的符号X的实例所对应的N的子节点上的属性c到N上的属性b的边。
- 假设和产生式p关联的一个语义规则通过X.a的值定义了继承属性B.c的值。那么,在相应的依赖图中有一条从X.a到B.c的边。对于每个标号为B,对应于产生式p中的这个B的结点N,创建一条从结点M上的属性a到N上的属性c的边。这里的M对应于这个X。请注意,M可以是N的父节点或者兄弟节点。
4.S,L属性的定义
S属性:如果每一个SDD的每一个属性都是综合属性。对于S属性我们可以按照语法分析树结点的任何自底向上顺序来计算它的各个属性值。S属性的定义可以在自底向上语法分析的过程中实现,因为一个自底向上的语法分析过程对应于一次后序遍历。
L属性:这类SDD的思想是在一个产生式体所关联的各个属性之间,依赖图的边总是从左到右,而不能从右向左(因此称之为L属性的)。更准确地讲,每个属性必须要么是一个综合属性要么是一个继承属性。
note:对于只有综合属性的SDD可以按照任何自底向上的顺序计算它们的值,对于同时具有继承属性和综合属性的SDD,不能保证存在一个顺序对各个结点上的属性进行求值。
任何包含下列产生式和规则的SDD都不是L属性的:
- 产生式:
- 语义规则:
第一个规则A.s = B.b在S属性SDD或L属性SDD中都是一个合法的规则。它通过一个子结点(也就是产生实体中的一个符号)的属性定义了综合属性A.s。
第二个规则定义了一个继承属性B.i,因此整个SDD不可能是S属性的。不仅如此,虽然这个规则是合法的,这个SDD也不可能是L属性的,因为属性C.c用来定义B.i,并且C在产生式体中位于B的右边。虽然在L属性的SDD中可以使用语法分析树中的兄弟结点的属性,但这些节点必须位于被定义属性的符号的左边。
5.具有受控副作用的语义规则
在实践中,翻译过程会出现一些副作用:一个桌上的计算器可能打印出一个结果;一个代码生成器可能把一个标识符的类型加入到符号表中。对于SDD,我们在属性文法和翻译方案之间找到了一个平衡点。属性文法没有副作用,并支持任何与依赖图一致的求值顺序。翻译方案要求按从左到右的顺序求值,并允许语义动作包含任何程序片段。
我们将按照下面的方法之一来控制SDD中的副作用:
- 支持那些不会对属性求值产生约束的附带副作用。换句话说,如果按照依赖图的任何拓扑顺序进行属性求值时都可以产生“正确的”翻译结果,我们就允许副作用的存在。这里的“正确”要视具体应用而定。
- 对允许的求值顺序添加约束,使得以任何允许的顺序求值都会产生相同的翻译结果。这些约束可以被看作隐含加入到依赖图中的边。
下面我们举出一个例子:
如下图所示:
产生式 | 语义规则 |
1) | |
2) | |
3) |