在本章,你将会包含类型检查,完成第9张工作。如今你可以把Pascal变量申明为各种类型,你必须确保当这些变量出现在语句中的时候,它们的类型必须与它们的操作符兼容。如第1章所说的那样,语法检查是语义分析的一部分。
==>> 本章中文版源代码下载:svn co http://wci.googlecode.com/svn/branches/ch10/ 源代码使用了UTF-8编码,下载到本地请修改!
方法和目标
本章的目标是在前端集成类型检查。方法是将类型检查加到语句解析器中,以便在解析语句过程中可以用到。针对第5章开发的语法检查器搞了个新的版本,用来验证你的成果。
类型检查
让我们从intermediate.typeimpl包中的TypeChecker类开始。这个类附带的静态方法实现了类型兼容规则,可以被语句解析器用来执行语法检查。清单10-1 展示了检查具体类型的各种方法。
1: /**
2: * 检查类型是否一个整数
3: * @param type 被检查类型说明
4: * @return true/false
5: */
6: public static boolean isInteger(TypeSpec type)
7: {
8: return (type != null) && (type.baseType() == Predefined.integerType);
9: }
10:
11: /**
12: * 检查二元操作符的两个类型都是否是整数
13: * @param type1 第一个被检查的类型
14: * @param type2 第二个被检查的类型
15: * @return true/false
16: */
17: public static boolean areBothInteger(TypeSpec type1, TypeSpec type2)
18: {
19: return isInteger(type1) && isInteger(type2);
20: }
21:
22: /**
23: * 检查类型是否一个实数,即计算机里面的浮点数
24: * @param type 被检查类型
25: * @return true/false
26: */
27: public static boolean isReal(TypeSpec type)
28: {
29: return (type != null) && (type.baseType() == Predefined.realType);
30: }
31:
32: /**
33: * 检查类型是否是整数或者实数,也就是一个实数系内的数
34: * @param type 被检查类型
35: * @return true/false
36: */
37: public static boolean isIntegerOrReal(TypeSpec type)
38: {
39: return isInteger(type) || isReal(type);
40: }
41:
42: /**
43: * 检查两个类型中至少有一个是实数,这个即计算机里面的数系扩大。比如INT+DOUBLE=DOUBLE
44: * @param type1 第一个被检查类型
45: * @param type2 第二个被检查类型
46: * @return true/false
47: */
48: public static boolean isAtLeastOneReal(TypeSpec type1, TypeSpec type2)
49: {
50: return (isReal(type1) && isReal(type2)) ||
51: (isReal(type1) && isInteger(type2)) ||
52: (isInteger(type1) && isReal(type2));
53: }
54:
55: /**
56: * 检查类型是否布尔类型
57: * @param type 被检查类型
58: * @return true/false
59: */
60: public static boolean isBoolean(TypeSpec type)
61: {
62: return (type != null) && (type.baseType() == Predefined.booleanType);
63: }
64:
65: /**
66: * 检查参加布尔二元运算如&&,|| 的两个类型是否都是布尔数。
67: * @param type1 第一个被检查类型
68: * @param type2 第二个被检查类型
69: * @return true/false
70: */
71: public static boolean areBothBoolean(TypeSpec type1, TypeSpec type2)
72: {
73: return isBoolean(type1) && isBoolean(type2);
74: }
75:
76: /**
77: * 检查类型是否一个字符类型
78: * @param type 被检查类型
79: * @return true/false
80: */
81: public static boolean isChar(TypeSpec type)
82: {
83: return (type != null) && (type.baseType() == Predefined.charType);
84: }
清单10-2 展示了TypeChecker类中的两个兼容方法
1: /**
2: * 检查赋值两端的类型是否兼容,即左值是否能被右值兼容
3: * @param targetType 左值类型
4: * @param valueType 右值类型
5: * @return true可以赋值/false不能赋值
6: */
7: public static boolean areAssignmentCompatible(TypeSpec targetType,
8: TypeSpec valueType)
9: {
10: if ((targetType == null) || (valueType == null)) {
11: return false;
12: }
13:
14: targetType = targetType.baseType();
15: valueType = valueType.baseType();
16:
17: boolean compatible = false;
18:
19: // 类型一样,ok
20: if (targetType == valueType) {
21: compatible = true;
22: }
23:
24: // 左实数,右整数,ok
25: else if (isReal(targetType) && isInteger(valueType)) {
26: compatible = true;
27: }
28:
29: // 字符串对字符串,赋值没问题
30: else {
31: compatible =
32: targetType.isPascalString() && valueType.isPascalString();
33: }
34:
35: return compatible;
36: }
37: