📜  编译器设计 |语法定向定义

📅  最后修改于: 2021-09-28 10:11:28             🧑  作者: Mango

先决条件 – 语法分析简介,语法定向翻译
语法定向定义(SDD)是一种抽象的规范。它是上下文无关文法的泛化,其中每个文法产生式X –> a都与一组形式为 s = f(b 1 , b 2 , ……b k ) 的产生式规则相关联,其中 s 是从函数f。该属性可以是字符串、数字、类型或内存位置。语义规则是代码片段,它们通常嵌入在产生式末尾并括在花括号 ({}) 中。

例子:

E --> E1 + T  { E.val = E1.val + T.val} 

带注释的解析树——包含给定输入字符串每个节点的属性值的解析树称为带注释的或装饰的解析树。

特征 –

  • 高规格
  • 隐藏实现细节
  • 未指定明确的评估顺序

属性类型 –有两种类型的属性:

1. 综合属性——这些属性是从它们的子节点中导出它们的值的,即节点处综合属性的值是根据解析树中子节点的属性值计算出来的。

例子:

E --> E1 + T  { E.val = E1.val + T.val} 

在此,E.val 从 E 1 .val 和 T.val 派生其值

综合属性的计算 –

  • 使用适当的语义规则为给定语法中的每个产生式编写 SDD。
  • 生成带注释的解析树并以自下而上的方式计算属性值。
  • 在根节点获得的值是最终输出。

示例:考虑以下语法

S --> E
E --> E1 + T
E --> T
T --> T1 * F
T --> F
F --> digit

上述语法的 SDD 可以写成如下

让我们假设输入字符串4 * 5 + 6用于计算合成属性。输入字符串的注释解析树是

为了计算属性,我们从最左边的底部节点开始。规则 F -> digit 用于将 digit 减少到 F,并且 digit 的值是从词法分析器获得的,它成为 F 的值,即来自语义动作 F.val = digit.lexval。因此,F.val = 4 并且因为 T 是 F 的父节点,所以我们从语义动作 T.val = F.val 中得到 T.val = 4。那么,对于 T –> T 1 * F 产生式,对应的语义动作是 T.val = T 1 .val * F.val 。因此,T.val = 4 * 5 = 20

类似地,E 1 .val + T.val 的组合变为 E.val,即 E.val = E 1 .val + T.val = 26。然后,应用产生式 S –> E 来减少 E.val = 26 和与它相关的语义动作打印结果 E.val 。因此,输出将为 26。

2. 继承属性——这些属性是从它们的父节点或兄弟节点派生的值,即继承属性的值是由父节点或兄弟节点的值计算的。
例子:

A --> BCD   { C.in = A.in, C.type = B.type } 

继承属性的计算——

  • 使用语义动作构建 SDD。
  • 生成带注释的解析树并以自上而下的方式计算属性值。

示例:考虑以下语法

S --> T L
T --> int
T --> float
T --> double
L --> L1, id
L --> id

上述语法的 SDD 可以写成如下

让我们假设输入字符串int a, c用于计算继承属性。输入字符串的注释解析树是

L 节点的值是从 T.type (sibling) 中获得的,它基本上是作为 int、float 或 double 获得的词法值。然后 L 节点给出标识符 a 和 c 的类型。类型的计算以自顶向下的方式或预序遍历方式完成。使用函数Enter_type 将标识符 a 和 c 的类型插入到相应 id.entry 的符号表中。