当前课程知识点:Compilers Techniques > 4 Syntax-Directed Translation > 4.3 L-Attributed Definitions > 4.3.1 L-Attributed Definitions
返回《Compilers Techniques》慕课在线视频课程列表
返回《Compilers Techniques》慕课在线视频列表
各位同学好
我们继续第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 Overview of Compilers Techniques
--Chapter 1 Overview of Compilers Techniques
--Overview of Compilers Techniques
-2.1 Lexical Tokens, Strings and Language
--2.1 Lexical Tokens, Strings and Language
--2.1 Lexical Tokens, Strings and Language
-2.2 Regular form
--2.2 Regular form
-2.3 Finite automata
--2.3 Finite automata
-2.4 DFA construction, Subset construction, Simpleset DFA
--2.4 DFA construction, Subset construction, Simpleset DFA
-2.5 Lex
--2.5 Lex
-3.1 Context-free Grammars
--3.1.1 The Role of the Parser
--3.1.2 The Formal Definition of a Context-free Grammar
-3.2 Writing a Grammar
--3.2.1 Elimination of Left Recursion
--3.2 Top-Down Parsing
-3.3 Languages and Grammars
--3.3 Language and Grammars
-3.4 Top-Down Parsing
--3.4.3 Recursive Descent Analysis
--3.4.4 Nonrecursive Descent Analysis
-3.5 Bottom-up Parsing
--Bottom-up Parsing
-3.6 LR Parsing
--3.6.6 Characteristics of LR Parsing
--3.6.7 Non Ambiguous and Not LR Context-Free Grammars
-4.1 Syntax-Directed Definitions
--4.1.2 Attribute Dependency Graphs and Ordering the Evaluation of Attributes
--Syntax-Directed Definitions
-4.2 Bottom-Up Calculation of S Attribute
--4.2.1 Bottom-Up Calculation of S-Attributed
-4.3 L-Attributed Definitions
--4.3.1 L-Attributed Definitions
--4.3.3 Design of Predictive Translator
--L-Attributed Definitions
-4.4 Bottom-Up Parsing of L-Attributed Translation
--4.4.1 Bottom-Up Parsing of L-Attributed Translation
--4.4.2 Simulate the Parsing of Inherited Properties
--Bottom-Up Parsing of L-Attributed Translation
-5.1 Overview
--Overview
-5.2 Global Stack Storage
-5.3 Calling Sequences
-5.4 Non Local Names
--5.4 Non Local Names and dynamic scope
--Non Local Name
-6.1 Overview of Intermediate Code Generation
--6.1 Overview of Intermediate Code Generation
-6.2 Declaration Statements
-7.1 Issues in the Design of Code Generator
--7.1 Issues in the Design of Code Generator
-7.2 Target Machine
--Target Machine
-7.3 Basic Blocks and Flow Graphs
--7.3 Basic Blocks and Flow Graphs
-7.4 A Simple Code Generator
-8.1 Demonstration of Compiler Framework based on Python
--8.1 Demonstration of Compiler Framework based on Python
-8.2 Basic
--8.2.4 SA
-8.3 SimpleJava