最后还剩下一个, 声明语句的翻译. 因为符号表API已经很完善了, 所以声明语句的翻译不会太困难. 将一些小地方处理好了就行. 难对付的部分是设定初始值, 需要考虑到类型转换. OK, 代码说明一切.
struct List* insDeclarationNode(void* node)
{
struct DeclarationNode* self = (struct DeclarationNode*)node;
// 节点指令
struct List* insList = (struct List*)newArrayList();
AcceptType type = self->dectype;
int i;
// 如果有初值, 这些变量会派上用场
struct IntParamInstruction* loadAddr;
struct AbstractValueNode* initialVal;
// 如果初值需要转型, 就用这个
InstructionCode castCode = (INTEGER == type) ? REAL_2_INT : INT_2_REAL;
InstructionCode assignCode = (INTEGER == type) ? INT_ASSIGN : REAL_ASSIGN;
struct NoParamInstruction* initAssign;
// 赋值结束需要弹出初始值, 这两个留作备用.
int popSize = (INTEGER == type) ? INT_SIZE : REAL_SIZE;
struct IntParamInstruction* popInitVal;
for (i = 0; i < self->vars->length(self->vars); ++i) { // 一次可能声明多个变量
// 调用符号表
int addr = declare((struct VariableNode*)
(self->vars->peekAt(self->vars, i)), type);
if (NULL != (initialVal = (struct AbstractValueNode*) // 如果有初始化
(self->initVals->peekAt(self->initVals, i)))) {
struct List* insInitVal = initialVal->createInstruction(initialVal);
// load 刚刚声明的变量
loadAddr = (struct IntParamInstruction*)
allocate(sizeof(struct IntParamInstruction));
loadAddr->code = CONST_INT;
loadAddr->param = addr;
appendInsList(appendIns(insList, loadAddr), insInitVal);
// 类型不匹配
if (initialVal->typeOf(initialVal) != type) {
struct NoParamInstruction* cast = (struct NoParamInstruction*)
allocate(sizeof(struct NoParamInstruction));
cast->code = castCode;
appendIns(insList, cast);
}
initAssign = (struct NoParamInstruction*)
allocate(sizeof(struct NoParamInstruction));
initAssign->code = assignCode;
popInitVal = (struct IntParamInstruction*)
allocate(sizeof(struct IntParamInstruction));
popInitVal->code = POP;
popInitVal->param = popSize;
appendIns(appendIns(insList, initAssign), popInitVal);
}
}
return insList;
}
接下来, 就要进入... 测试环节了. 这么多指令生成代码, 不测试, 能放心吗?
本文介绍了一个编译器中声明语句的翻译实现方法,重点讨论了如何处理变量声明及其初始值设定过程中的类型转换问题,并提供了详细的代码示例。
888

被折叠的 条评论
为什么被折叠?



