[语义分析]语法树节点波澜再起[编译时类型确定]

    上一次修改AbstractValueNode 时添加了一个typeOf 成员函数,这个函数用来在编译时确定AbstractValueNode 的类型。相对于确定编译时值,确定类型要简单一些。

    对于IntegerNodeRealNode ,它们的成员函数实现依然是很简单的

AcceptType typeOfInt(void* node)
{
    return INTEGER;
}

AcceptType typeOfReal(void* node)
{
    return REAL;
}

而确定变量的类型,well,我们在符号表管理器中已经实现过这么一个函数

AcceptType typeOf(struct VariableNode* var);

现在摆在我们面前有两条路选,一是修改这个函数的参数类型,并在函数体内去转换这个参数类型,另一条路就是再加套一个这样的函数

AcceptType typeOfVar(void* node)
{
   return typeOf((struct VariableNode*)node);
}

哪一种就随意了。

    接下来又是运算节点的类型确定了。对于UnaryOperationNode ,仅需要

AcceptType typeOfUnaryOp(void* node)
{
    struct UnaryOperationNode* self = (struct UnaryOperationNode*)node;
    if (NOT == self->op && REAL ==
                                         self->operand->typeOf(self->operand)) {
            // 报错:实型数不可以作为条件
    }
    return self->operand->typeOf(self->operand);
}

 注意报错以后仍然若无其事地返回,这样也是提升容错性的一种方法。在BinaryOperationNode 的对应函数中也用到这个方法

AcceptType typeOfBinaryOp(void* node)
{
    struct BinaryOperationNode* self = (struct BinaryOperationNode*)node;
    AcceptType leftType = self->leftOperand->typeOf(self->leftOperand),
              rightType = self->rightOperand->typeOf(self->rightOperand);
    if (ASSIGN == self->op) {
        return leftType;
    }
    if (isLogicOperator(self->op) &&
                         (REAL == leftType || REAL == rightType)) {
            // 报错:实型数不可以作为条件
    }
    return leftType > rightType ? leftType : rightType;
}

首先,如果这是一个赋值,那么赋值以后的类型由被赋值的变量决定,即取决于左值。最后一个?: 表达式看起来很奇怪,为什么要取两者中较大的一个呢?其实这是一个偷懒的做法,因为在定义时REALINTEGER 大,所以这样做以后,如果两者中一个是INTEGER 一个是REAL ,那么会返回REAL 。不过这样做也有别的意思,比如要添加一个LONG 类型(比INTEGER范围更大的整型 ),那么将它插入到枚举的中INTEGERREAL 之间即可──这个取较大语句会解决这些事情。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值