7.2 修改编译器
7.2.1 数组的语法规则
这次增加的语法规则如下所示。
1. 扩展类型标识符(type_specifier)以声明数组类型的变量
2. 使用 new创建数组的语法(array_creation)
3. 数组常量(array_literal)
4. 使用下标运算符(如 a[10])引用数组元素的语法
第1点,原来的类型标识符是下面这样的。
type_specifier
: BOOLEAN_T
| INT_T
| DOUBLE_T
| STRING_T
;
现在,像 boolean 或者 int 这样的基本类型都将被作为 basic_type_specifier,如下所示。
type_specifier
: basic_type_specifier
| type_specifier LB RB
;
LB和 RB是Left Bracket和Right Bracket的简称,代表 [和 ]。
type_specifier可以包含 []本身。这样一来不论加几个 []都可以(例如 int[][][])。
第2点,使用 new创建数组的语法看上去好像挺麻烦的。
比如在Java中代码 new int[10]会得到 int数组(10个元素)。
在此基础上如果加上下标 [5],就变成了 new int[10][5]。这行代码会取得 new int[10]的第5个元素 [1]是不可能的,这当然是创建二维数组的意思。
总之,下标运算符 [] 除了必须要适用于普通的表达式之外,还要适用基于 new的数组创建(array_creation)语法。
在Diksam book_ver.0.1中组成表达式的最小元素是 primary_expression(运算符优先顺序最高的块),因此“基于new创建数组”被当作“例外情况”来处理。
primary_expression
: primary_no_new_array / 基于new创建数组之外的表达式 /
| array_creation / 使用new创建数组的表达式 /
;
引用数组元素的语法规则如下所示。下标运算符 []不被局限于使用 new来创建数组。
primary_no_new_array
/ 可以使用[]的只有primary_no_new_array /
: primary_no_new_array LB expression RB
(之后省略)
……这是一段多么了不起的代码啊。可这不是我写的,我只不过是照搬了Java的语法规则而已 [7]。
7.2.2 TypeSpecifier结构体
在Diksam的编译器中,使用 TypeSpecifier结构体保存数据类型。
关于 TypeSpecifier结构体请参考6.3.4节。
要点在于,要使用保存基础类型(DVM_BasicType)的 TypeSpecifier结构体和链表连接起来的派生类型(TypeDerive)来表示所有数据类型。
这部分的代码如代码清单7-1所示。
代码清单7-1 TypeSpecifier(Diksam book_ver.0.2版)
typedef enum {
FUNCTION_DERIVE,
ARRAY_DERIVE
} DeriveTag;
typedef struct {
ParameterList *parameter_list;
} FunctionDerive;
typedef struct {
int dummy; / make compiler happy /
} ArrayDerive;
typedef struct TypeDerive_tag {
DeriveTag tag;
union {
FunctionDerive function_d;
ArrayDerivearray_d;
} u;
struct TypeDerive_tag *next;
} TypeDerive;
struct TypeSpecifier_tag {
DVM_BasicType basic_type;
TypeDerive *derive;
};
之前的派生类型只有“函数类型”,这次增加了数组的派生(在 TypeDerive的 tag中加入了 ARRAY_DERIVE)。
在fix_tree.c 中,表达式的各个节点中也要附加对应地 TypeSpecifier 结构体。比如,使用 int[][] a;声明变量 a,在附加 TypeSpecifier的时候,首先给 basic_type 赋值为 DVM_INT_TYPE,在此基础上给进行了数组派生的 TypeDerive累加上两个链表。
于是,使用下标运算符进行引用(如 a[10])的时候,移除 TypeDerive链表的第一个元素后剩下的就是表达式的类型了。同理,如果是 a[10][3]的话,把两个都移除后,表达式的类型就是 int了(如图7-3)。
图7-3 含有数组的分析树的类型
在图7-3中,圆形中间带有 []的符号表示下标运算符 IndexExpression。它是 Expression结构体中的一种共用体,数组和下标的表达式保存在下面的结构体中。
typedef struct {
Expression array; / 数组的表达式 */
Expression index; / 下标的表达式 */
} IndexExpression;