发送标记的联合

时间:2017-04-27 20:27:01

标签: c struct switch-statement unions

我使用C tagged-union样式结构来表示AST节点。它们看起来像这样:

struct A_var_ {
  enum {
    A_simpleVar,
    A_fieldVar,
    A_subscriptVar
  } kind;

  A_pos pos;

  union {
    S_symbol simple;

    struct {
      A_var var;
      S_symbol sym;
    } field;

    struct {
      A_var var;
      A_exp exp;
    } subscript;
  } u;
};

现在,我正在尝试调度节点的类型,如下所示:

switch(node->kind) {
  case A_simpleVar:
    ...
}

但是,我收到Can't resolve variable A_simpleVar之类的错误。我怎样才能做到这一点?我在Windows上使用Cmake,编译器是gcc。

我得到的具体错误,代码如下:

struct expty transExp(S_table venv, S_table tenv, A_exp a)
{
  switch (a->kind) {
    case A_letExp:
      struct expty exp;
      A_decList d;
      S_beginScope(venv);
      S_beginScope(tenv);
      for (d = a->u.let.decs; d; d=d->tail) {
        transDec(venv, tenv, d->head);
      }
      exp = transExp(venv, tenv, a->u.let.body);
      S_endScope(tenv);
      S_endScope(venv);
      return exp;

    case A_opExp:
      A_oper oper = a->u.op.oper;
      struct expty left = transExp(venv, tenv, a->u.op.left);
      struct expty right = transExp(venv, tenv, a->u.op.right);
      if (oper == A_plusOp) {
        if (left.ty->kind != Ty_int)
          EM_error(a->u.op.left->pos, "integer required");
        if (right.ty->kind != Ty_int)
          EM_error(a->u.op.right->pos, "integer required");
        return expTy(NULL, Ty_Int());
      } // I need to cover other operators as well, but not for prototype
  }
}

是:

C:\Users\Fotis\Documents\Devel\grimoire\Books\ModernCompilerC\semant.c: In function 'transExp': C:\Users\Fotis\Documents\Devel\grimoire\Books\ModernCompilerC\semant.c:28:7: error: a label can only be part of a statement and a declaration is not a statement struct expty exp; ^ C:\Users\Fotis\Documents\Devel\grimoire\Books\ModernCompilerC\semant.c:29:7: error: expected expression before 'A_decList' A_decList d; ^ C:\Users\Fotis\Documents\Devel\grimoire\Books\ModernCompilerC\semant.c:32:12: error: 'd' undeclared (first use in this function) for (d = a->u.let.decs; d; d=d->tail) {

值得注意的是,函数的参数是指向typedef ed的结构的指针。即A_expA_exp_ *

2 个答案:

答案 0 :(得分:3)

您正在使用C ++编译器进行编译,而不是使用C编译器进行编译。两个处理枚举的方式不同。

在C中,所有枚举在全局范围内都可见。在C ++中,它们由包含类型限定,如果有的话。因此,您需要在枚举值前加上结构名称:

switch(node->kind) {
  case A_var_::A_simpleVar:
    ...
}

答案 1 :(得分:0)

我已经发现了一段时间以前出现的问题,但只是找到时间指出它,以便其他人可以得到帮助,以防他们遇到同样的错误。

这里需要注意的是编译器错误:

C:\Users\Fotis\Documents\Devel\grimoire\Books\ModernCompilerC\semant.c: In function 'transExp': C:\Users\Fotis\Documents\Devel\grimoire\Books\ModernCompilerC\semant.c:28:7: error: a label can only be part of a statement and a declaration is not a statement struct expty exp;

由于某种原因,在C语法中,声明被认为是expression,并且C语法的语法需要声明作为case的主体。将一系列表达式/语句组成一个语句的最简单方法是将它们全部括在括号中。在这种特殊情况下,要走的路是将问题中的错误代码翻译成:

(...snip...)

switch (a->kind) {
    case A_letExp: {
      struct expty exp;
      A_decList d;
      S_beginScope(venv);
      S_beginScope(tenv);
      for (d = a->u.let.decs; d; d=d->tail) {
        transDec(venv, tenv, d->head);
      }
      exp = transExp(venv, tenv, a->u.let.body);
      S_endScope(tenv);
      S_endScope(venv);
      return exp;
    }

请注意{之后和}之后的符号case A_letExp:return exp;