一、Constructing Syntax Tree
1.1. 基本节点结构
-
叶子节点:
If the node is a leaf, an additional field holds the lexical value for the leaf. A constructor function Leaf ( op, val) creates a leaf object. Alternatively, if nodes are viewed as records, then Leaf returns a pointer to a new record for a leaf.
-
包含一个额外字段,用于存储词法值(lexical value)。
-
通过构造函数
Leaf(op, val)创建叶子对象(或返回指向新记录的指针)。
-
-
内部节点:
If the node is an interior node, there are as many additional fields as the node has children in the syntax tree. A constructor function Node takes two or more arguments: Node(op, c_1, c_2, . . . , c_k) creates an object with first field op and k additional fields for the k children c_1, c_2, . . . , c_k.
-
包含与子节点数量相同的额外字段。
-
通过构造函数 Node(op, c_1, c_2, ..., c_k) 创建,其中:
-
op为操作符; -
c_₁ 到 c_k 为子节点。
-
-
1.2. 自底向上构造(S-属性定义)
-
适用于 S-属性定义(S-attributed definition) 。(属性值仅由子节点(children) 和自身属性决定。)
-
示例表达式:
a - 4 + c -
所有属性均为 综合属性(synthesized attributes),值从子节点向上传递。

(图中箭头上的p1-p5分别表示创建的5个节点;方框表示结点,叶子节点使用 Leaf(op, val) 创建,内部节点使用构造函数 Node(op, c_1, c_2, ..., c_k) 创建;虚线箭头指向结点)
1.3. 自顶向下构造(L-属性定义)
-
适用于 L-属性定义(L-attributed definition)。
-
示例表达式:
a - 4 + c -
关键属性:
-
继承属性
.inh:表示当前子树左侧已构造的部分语法树的根节点。 -
综合属性
.node:最终表示该非终结符对应子树的根节点。
-
-
在分析过程中,
.inh自上而下传递,.node自下而上传递,最终合成完整语法树。

1.4. 综合应用举例

该树的构建过程如下:

二、SDT Scheme
SDT Scheme(Syntax-Directed Translation Scheme)
2.1. SDT Scheme 的概念
- 定义 :SDT Scheme 是一种在上下文无关文法(CFG)的产生式体中嵌入程序片段(称为语义动作,semantic actions)的机制。
-
基本形式
- 语义动作嵌入 :在产生式体中用花括号
{}包裹语义动作。
- 执行时机:在解析过程中,当产生式体中某个动作左侧的所有符号(终端或非终端)都被匹配后,立即执行该动作。
- 语义动作嵌入 :在产生式体中用花括号

2.2. SDT 的两种主要实现方式
(1) 后缀 SDT 方案(Postfix SDT)
-
适用场景 :适用于 S-属性定义 和 自底向上解析(如 LR 解析)。
-
特点:所有语义动作都放置在产生式体的末尾。
-
实现:在解析栈中为综合属性设置专门字段。例如,在桌面计算器中,当归约时,动作被执行,计算结果压入栈顶。
-
示例 :解析
3+4时,栈的变化过程如下图示:

首先画出语法树,栈中的最后三步如下:

(2) 中缀 SDT 方案(Infix SDT)
-
特点:语义动作可以放置在产生式体的任意位置。
-
执行时机:动作在它左侧的所有符号被处理完后立即执行。
-
示例 :对于
B → X{a} Y,动作a在X被完全识别后执行。
(3) SDT 的通用实现方法
任何 SDT 均可按以下步骤实现:
-
忽略动作:先对输入进行语法分析,生成一棵语法树。
-
添加动作节点 :对于每个内部节点 N(对应产生式
A → a),在其子节点序列中插入代表语义动作的节点,使从左到右的子节点序列精确对应产生式体中的符号和动作。 -
前序遍历执行:对修改后的语法树进行前序遍历,每当访问到一个标记为"动作"的节点时,就执行该动作。
示例 :将
3*5+4转换为逆波兰表达式+\*354,可以通过在适当位置插入动作来实现:

2.3. L-属性定义的 SDT 方案
-
转换原则:
-
继承属性 :将计算非终结符 A 的继承属性的动作,嵌入在 A 出现之前的位置。
-
综合属性 :将计算产生式头部(head)的综合属性的动作,放在产生式体的末尾。
-
-
实现方法:与上述2.2中的通用实现方法相同,即先生成带动作的语法树,再进行前序遍历执行动作。