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”类型,该域没有意义 |
这里的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(非负数) |
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 数组定义时上下界大小关系
根据文法,数组定义时的上下界均为无符号数,而不会是常量表达式的情形,所以直接比较上界是否大于下界即可。