当前课程知识点:编译技术 > 第四章 语法指导的翻译 > 4.3 L属性定义 > 4.3.1 L属性定义
各位同学好
我们继续第4章的学习
在上一讲中
我们学习了S属性的计算方法
由于S属性它表示比较简洁
因此我们可以在分析的同时
完成属性计算
然而S属性
并不能表达所有的语义结构
因为它只包含综合属性
那么一个非常直观的问题
如果我们的文法中有继承属性
是否可以进行边分析边计算
这个问题我们就要考虑
我们的计算顺序
以及属性计算
和分析方法之间的关系
我们说属性计算
它是依赖于我们的分析方法的
并且和我们的分析树
建立的顺序有关系
在我们的编译器中
从词法分析开始
到语法分析、语义分析
我们的分析都是从左向右完成的
因为我们读入程序
本身就是自左向右的
所以只有当我们在属性分析的时候
也是从左向右
才能够完成边分析边计算
在本章的后续内容中
我们将重点介绍L属性文法
包括L属性定义、
翻译方案、
翻译器的设计
以及使用综合属性替代继承属性
首先我们给出L属性定义
我们说一个属性
如果产生式A→X1 X2 ... Xn
它的每条语义规则的属性
都是A的综合属性
或者是 Xj 的继承属性
其中 j 从1~n
但是它有个前提
它只能依赖该产生式
Xj 左部的 也就是X1、X2、一直到X n-1 的属性
或者它可以依赖A的继承属性
当满足这样的条件的时候
我们就称这个属性是一个L属性
在这个定义中
一个非常值得注意的一点就是
S属性定义是属于L属性定义的
因为在L属性定义中
有一项
我们的属性可以是A的综合属性
而S属性的定义中
是只包含综合属性的这样一个文法定义
所以所有的S属型定义
都属于L属性定义
这一点是非常值得注意的
接下来我们看一个例子
我们来看这个例子
这就是一个典型的
不适合 边分析边计算的文法
在这个方法中
有两个产生式
A→LM和A→QR
在第2个产生式中
有一个语义规则
Q.a等于R.s的一个函数q
而在这个产生式中
我们可以看到
Q是出现在R左侧的
前面我们提到
我们的分析是自左向右的
因此在分析Q的时候
R还没有完成分析
所以我们就无法得到R的属性s
进而无法把它传递给Q来进行分析
因此这个属性
就无法完成边分析边计算
这也是为什么
我们在L属性定义中
非常强调每一个属性只能依赖于
它在产生式左侧的属性
或者它的父节点的属性
我们以之前介绍过的变量声明的例子来看
如何进行L属性的计算
在这个例子中
我们可以看到
我们既有继承属性
也有综合属性
例如像in属性
就是一个典型的继承属性
如果一个继承属性
它只依赖于产生式左部
或者父结点的属性的话
它就是一个L属性
例如像L1的in属性
它就是由它的父节点L传入的
因此它是一个L属性
可以完成边分析并计算
这时候我们就非常强调
我们在分析计算的时候
非常强调
语义规则的执行时刻
在表中
我们不但给出了产生式
也给出了对应的语义规则
而计算属性的时候
我们非常强调
语义规则它的执行顺序
因此在后续的计算中
我们需要把语义规则的每一条动作
插入到它对应的执行的位置
在介绍完L属性定义之后
我们来把它和我们之前介绍过的S属性
做一个对比
我们说在S属性定义中
它的一个非常鲜明的特点
就是可以将产生式
作为一个整体来看待
我们的属性
可以在分析完
当前的产生式之后来进行
而L属性定义则不同
它跟属性所属的符号
在产生式中的位置有关系
我们只有在产生式中
正确的位置执行语义规则
才能够保证我们的计算是正确的
对于L属性的定义
它和S属性最显著的区别在于
它们需要使用不同的翻译方案
在后续的课程中
我们将分别针对两种属性来介绍
如何实现它们的翻译方案
这就是本讲的主要内容
谢谢大家
-1.1 编译技术绪论
--编译原理介绍--作业
-2.1 词法记号 串和语言
--2.1 词法记号 串和语言--作业
-2.2 正规式 状态转换图
--2.2 正规式 状态转换图--作业
-2.3 有限自动机
--2.3 有限自动机--作业
-2.4 DFA构建 子集构造法 DAF化简
-2.5 Lex
-3.1 上下文无关文法
--3.1.3 推导
-3.2 自上而分析中的文法
--3.2 上下文无关文法--作业
--3.2.3 语言和文法--作业
-3.3 自上而下分析
-3.4 自下而上分析
--3.4 自下而上分析--作业
-3.5 LR分析器
-4.1 语法制导的定义
--4.1 语法制导的定义--作业
-4.2 S属性的自下而上计算
-4.3 L属性定义
--4.3 L属性定义--作业
-4.4 L属性的自下而上计算
--4.4 L属性的自下而上计算--作业
-5.1 概述
--5.1 概述
--概述-作业
-5.2 全局栈式存储分配
-5.3 调用序列
--5.3 调用序列
-5.4 非局部名字的访问
--5.4 非局部名字的访问--作业
-6.1 中间代码生成
-6.2 作用域信息的保存
-7.1 代码生成器设计中的问题
-7.2 目标机器
--7.2 目标机器
--7.2 目标机器--作业
-7.3 基本块和流图
-7.4 一个简单的代码生成器
-8.1 基于Python的编译器框架演示视频和代码
-8.2 代码介绍
--8.2.4 SA
-8.3 SimpleJava