1.1涉及常量的语义分析

1.1.1 常量定义时的常数传播

常数传播指的是常量右值由别的常量标识符定义,无法直接取得其取值的情况。

1.1.1.1 常数传播的目标

在引用常量时,能够直接从符号表中查到常量的绝对值(无符号值)和其符号情况(正负)。

1.1.1.2 涉及的数据结构说明

  • 抽象语法树的_Constant节点 | 域定义 | 描述 | | —- | —- | | string type | 常量类型,包括”id”、”integer”、”real”、”char”,其中”id”表示该常量的取值由别的常量标识符提供,右值常量标识符也由下述strOfVal提供,当然在进行符号种类检查之前,并不能确定该标识符是已定义的常量标识符 | | string strOfVal | 常量取值的字符串表示 | | bool isMinusShow | 右值前是否出现负号(出现了正号和没有出现任何符号的意义是一样的,即没有出现负号) |

这里的isMinusShow的含义只能理解为,是否需要在右值的基础上取相反数,并不能代表当前常量取值的正负性

  • 符号表的常量类型

当符号表中的符号类型为常量时,涉及到以下域:

域定义 描述
type 常量类型,包括“integer”、”real”、”char”
string value 常量取值
bool isMinusShow 是否是负数,对于“char”类型,该域没有意义
  1. 这里的isMinusShow的含义也可以理解为是否需要在value的基础上取相反数,但我们规定常数传播的目标是,value中保存的一定是无符号数,所以**isMinusShow应该深入理解为当前常量是否为负数**。

1.1.1.3 常量传播方法

如果碰到当前常量的右值由别的常量标识符定义,首先应该检查右值是否未定义;如果已定义,还需检查右值是否是常量标识符;如果是常量标识符,则需从符号表中查出其无符号取值value和符号情况isMinusShow。

当前_Constant节点的isMinusShow 记为A 符号表查出的isMinusShow 记为B 当前常量存入符号表后的isMinusShow 记为C
true(取反) true(负数) false(非负数)
true(取反) false(非负数) true(负数)
false(不取反) true(负数) true(负数)
flase(不取反) false(非负数) false(非负数)

观察可得,C=A异或

1.1.2 计算整型常量表达式的值

为了便于进行后续的除0错误、数组下标越界等检查,我们支持整型常量表达式的自动计算。

1.1.2.1 涉及的数据结构说明

常量表达式并不会保存到符号表中,所以要想保存常量表达式的值,只能保存在抽象语法树的_Expression节点中,涉及到以下域:

域定义 描述
int totalIntValue 如果该表达式的类型为整型常量,则该域表示其整型取值
bool totalIntValueValid 表示该表达式的类型是否为整型常量
string expressionType 该表达式的类型,取值为”integer”、”real”、”char”、”boolean”,也可能是“error”,表示类型检查发现错误

1.1.2.2 标记整型常量表达式和计算取值的方法

_Expression种类 标记和计算方法
_Expression的种类为”var”,且其附属_VariantReference经过检查,种类为”constant”,且其类型为“integer” 从符号表查出常量取值和符号情况,组合成一个有符号整型数
totalIntValueValid=true;
totalIntValue=有符号整型数;
_Expression的种类为”integer” totalIntValueValid=true;
totalIntValue=当前表达式节点保存的整型数
_Expression的种类为”compound”,且运算符种类为”minus”;且操作数表达式的类型为”integer”且其totalIntValueValid取值为true totalIntValueValid=true;
totalIntValue=操作数表达式的常量取值的相反数
_Expression的种类为”compound”,且运算符种类为”bracket”;且操作数表达式的类型为”integer”且其totalIntValueValid取值为true totalIntValueValid=true;
totalIntValue=操作数表达式的常量取值
_Expression的种类为“compound”,且运算符为+、-、*、/、div、mod;且两个操作数的表达式的类型均为”integer”,totalIntValueValid取值均为true totalIntValueValid=true;
totalIntValue=左操作数表达式的取值 操作符 右操作数表达式的取值
   未出现的_Expression类型,则不涉及整型常量表达式的计算。

1.1.3 除0错误的静态检查

涉及/、div、mod三种运算符,如果右操作数表达式是常量整型表达式,就可以判断其取值是否为0,如果为0,就可以静态检测出除0错误。

1.1.4 数组下标越界的静态检查

如果数组下标表达式是常量整型表达式,就可以通过查符号表中的数组定义的当前维上下界,检查该维下标是否越界。

1.1.5 数组定义时上下界大小关系

根据文法,数组定义时的上下界均为无符号数,而不会是常量表达式的情形,所以直接比较上界是否大于下界即可。