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)。

figure_0231_0063

图7-3 含有数组的分析树的类型

在图7-3中,圆形中间带有 []的符号表示下标运算符 IndexExpression。它是 Expression结构体中的一种共用体,数组和下标的表达式保存在下面的结构体中。

typedef struct {

Expression array; / 数组的表达式 */

Expression index; / 下标的表达式 */

} IndexExpression;