语义分析定位

语义分析是编译器前端(词法/语法分析)与后端(中间代码生成/优化/目标代码生成)的桥梁。

  • 前端完成语法正确性检查 → 语义分析进行上下文相关检查 → 后端生成目标代码

语义错误类型

  • 未声明标识符
  • 重复定义
  • 数组越界
  • 类型不兼容
  • break/continue 出现在错误位置

语义分析任务

  • 作用域检查
  • 类型检查
  • 中间代码生成

语法制导翻译

每个产生式配备一个语义子程序,在语法分析的同时调用语义子程序完成翻译。

  • 语法分析驱动 → 语义子程序执行 → 中间代码生成
  • 语义信息通过属性附着在文法符号上传递

属性文法

属性文法 = 上下文无关文法 + 属性 + 语义规则

  • 每个文法符号 可以关联若干属性
  • 每个产生式 关联一组语义规则

综合属性

子结点→父结点 传递。

  • 在产生式 中, 的综合属性由子结点 的属性计算得到
  • 语法树自底向上传递信息

示例:表达式 的值向上综合

    E.val=19
   /        \
  T.val=15   +
 /     \      \
F.val=3 *      F.val=4
         \
        F.val=5

重点 综合属性自底向上传递,在自下而上分析中天然适用。

继承属性

父结点/兄弟结点→子结点 传递。

  • 在产生式 中, 的继承属性由 的属性计算得到
  • 语法树自上而下/从左到右传递信息

示例:float id1, id2 的类型传递

        D
       / \
   type   L
  float  / \
       id1  L
           / \
         id2  ε
  • = 继承自 的类型信息
  • 沿链表传递同一类型

重点 继承属性自顶向下传递,在自上而下分析中天然适用。

综合 vs 继承对比

类型传递方向适用分析方式
综合属性子→父自下而上
继承属性父/兄→子自上而下

语法制导翻译方案(SDTS)

SDTS 是属性文法的具体实现框架,定义为五元组

  • :终结符集
  • :非终结符集
  • :输出符号集(中间代码/目标代码)
  • :规则集,每条规则形如 ,其中
  • :开始符号

翻译对偶

翻译过程通过翻译对偶 的推导描述:

其中 是源文法串, 是输出串。

示例: 对应翻译规则 ,输入 的翻译对偶推导:

简单 SDTS(Simple SDTS)

非终结符在规则中的出现顺序在源文法和翻译文法中相同

S- 属性文法(S-Attributed Grammar)

仅含综合属性的属性文法,适合 LR 自下而上分析。

在规约时计算综合属性:

L- 属性文法(L-Attributed Grammar)

继承属性仅依赖于左边兄弟或父结点的属性,即每个继承属性可沿语法树从左到右传递。

对比

属性文法属性类型适用分析计算时机
S- 属性仅综合自下而上(LR)规约时
L- 属性综合 + 继承(受限)自上而下(LL)推导时

LL(1) 消除左递归后的 SDT

消除左递归后需用继承属性传递信息:

消除前:

消除后:

其中 为继承属性(传递已计算部分), 为综合属性(返回最终结果)。

带语义动作的 LL(1) 分析算法

LL(1) 分析栈中混入语义符号(用 # 标记),处理规则:

  1. 终结符:匹配输入
  2. 非终结符:查表展开,将产生式右部(含语义动作符号)逆序入栈
  3. 语义动作符号:执行对应语义子程序

LR 分析中的 SDT 实现

LR 分析在规约时执行语义动作:规约到 时,栈顶 对应的属性值已计算完毕,此时执行 的语义规则。

这种方式天然适合 S- 属性文法——综合属性在规约时自底向上计算,无需额外机制。

AST 构建

语法分析结果可组织为抽象语法树(AST),相比语法树:

  • 运算符提升为内部节点
  • 单继承产生式折叠
  • 省略括号、分隔符等语法细节
  • 便于后续语义分析和代码生成

类型检查

类型等价

  • 名字等价(Name Equivalence):两类型当且仅当名字相同才等价(如 typedef
  • 结构等价(Structural Equivalence):两类型当结构组成相同即等价

类型转换

  • 类型提升(Promotion):向超集的自动转换(如 intfloat
  • 强制转换(Coercion):隐式类型转换,编译器自动插入
  • 显式转换(Casting):程序员显式写出(如 (float) i

类型检查规则

类型检查的形式化表述:(在环境 中,表达式 的类型为

  • if 语句:条件必须为 bool,then/else 分支类型一致
  • 函数调用:实参类型与形参类型匹配,返回值类型一致
  • 赋值:左值类型与右值类型兼容