阅读更多
1 类型表达式
- 基本类型是类型表达式
- $integer$
- $real$
- $char$
- $boolean$
- $type\_error$(出错类型)
- $void$(无类型)
- 可以为类型表达式命名,类型名也是类型表达式
- 将类型构造符(type constructor)作用于类型表达式可以构成新的类型表达式
- 数组构造符$array$:若$T$是类型表达式,则$array(I, T)$是类型表达式($I$是一个整数)
- 指针构造符$pointer$:若$T$是类型表达式,则$pointer(T)$是类型表达式,它表示一个指针类型
- 笛卡尔乘积构造符:若$T_1$和$T_2$是类型表达式,则笛卡尔乘积$T_1 \times T_2$是类型表达式
- 函数构造符$\to$:若$T_1、T_2、...、T_n$和$R$是类型表达式,则$T_1 \times T_2 \times ... \times T_n \to R$是类型表达式
- 记录构造符$record$:若有标识符$N_1、N_2、...、N_n$与类型表达式$T_1、T_2、...、T_n$,则$record((N_1 \times T_1) \times (N_2 \times T_2) \times ... \times (N_n \times T_n))$是一个类型表达式
例如,有C程序片段
1 | struct stype |
- 和$stype$绑定的类型表达式:$record((name \times array(8, char)) \times (score \times integer))$
- 和$table$绑定的类型表达式:$array(50, stype)$
- 和$p$绑定的类型表达式:$pointer (stype)$
2 声明语句的翻译
对于声明语句,语义分析的主要任务就是收集标识符的类型等属性信息,并为每一个名字分配一个相对地址
- 从类型表达式可以知道该类型在运行时刻所需的存储单元数量称为类型的宽度(width)
- 在编译时刻,可以使用类型的宽度为每一个名字分配一个相对地址
名字的类型和相对地址信息保存在相应的符号表记录中
该文法是一个$LL(1)$文法(对于每个输入符号,$SELECT集唯一$),因此可以用自顶向下分析法,下面是两个例子
采用最左推导完全展开后,请以树的后续遍历为顺序阅读各节点的属性计算
3 参考
- 《MOOC-编译原理-陈鄞》