C 抽象语法树问题

C 抽象语法树问题,c,compiler-construction,abstract-syntax-tree,C,Compiler Construction,Abstract Syntax Tree,我目前正在用C语言编写一个编译器,在为AST构造数据结构的部分,我有点不知所措,特别是在为IDs构造结构的部分,它被称为“符号表条目” 我看到网络上的结构,如: struct ste { struct id *name; /* pointer into hash table for assoc. id */ struct decl *decl; /* pointer into symbol table for its decl */ struct ste *prev; /

我目前正在用C语言编写一个编译器,在为AST构造数据结构的部分,我有点不知所措,特别是在为IDs构造结构的部分,它被称为“符号表条目”

我看到网络上的结构,如:

struct ste {
  struct id   *name;  /* pointer into hash table for assoc. id */
  struct decl *decl;  /* pointer into symbol table for its decl */
  struct ste  *prev;  /* pointer to previous entry in symbol table */
}; 

它看起来像一个链表,因为它包含一个指向上一个条目(*prev)的指针,但这背后的逻辑是什么

您的具体问题的答案是:prev链接意味着,当您的代码有指向其中一个节点的指针时,它可以跟随到链中上一个链接的链接。符号表可能具有如下列表的一个原因是为了处理嵌套范围:

{
int x;
  {
   int x;
  }
}

然而,还有很多其他原因使得符号节点可能需要排列在一个列表中。编译器需要访问所有节点的任何原因都是一个原因。

我使用反向链表的第一个想法是针对那些支持重写变量名的语言,例如:

int main (void) {
    int x = 1;
    int y = 1;
    if (x == 1) {
        int y = 2;
        printf ("y = %d\n", y);
    }
    return 0;
}
在这种情况下,您希望访问具有最内部作用域(定义的最后一个)的变量。这可以通过向后浏览列表找到(当然,假设您正在向前构建列表)

然后,当范围消失时,您也可以调整“head”指针以删除最近添加的变量


当然,您可以通过在当前头之前插入而不是添加到列表末尾来实现相同的效果(从概念上看,这与正在执行的操作类似,只是使用名为
prev
的指针,而不是
next
).

您看到了很久以前C程序员的一个有害习惯的遗留问题:假设符号将出现在一些列表中,而不是单独分配列表结构,列表指针将作为符号结构的一部分包含在列表中。这个技巧为每个列表元素节省了一个分配,但代价是:符号可以位于的列表集是固定的,这种结构使程序员感到困惑。如果应用程序是编译器,则没有理由再使用此技巧。更清楚的是,有一个单独的列表结构,定义如下:

struct ste_list {
    struct ste *symbol_table_entry;
    struct str_list *next;
};
你可以随心所欲地拥有这些,没有人比你更聪明。你发现的令人困惑的内部指针消失了

你问

这背后的逻辑是什么


答案的一部分是,在可分辨列表中添加符号很有用。如果不了解更多关于特定编译器的信息,我就不能肯定地回答这个问题。我最好的猜测是
prev
条目将用于实现嵌套的作用域(C中的
{…}
括号),但这是基于我见过或使用过的编译器的猜测。因此,逻辑可能是,当遇到右大括号时,编译器可能会跟随该链接,直到到达封闭范围内的
ste
。比您正在学习的编译器的作者更有经验的人通常会将此逻辑放入“符号表抽象”中,其中包括
enterscope()
exitscope()等函数,这些操作的细节将从单个符号表条目的内部表示中隐藏。

此定义的上下文是什么?如果您想了解使用链表的原因,请阅读Knuth?编译器相关资源列表:这里的问题是您不了解符号表的用途,还是您不了解它为何以这种特殊方式构造?如果你对后者感到困惑,是因为它看起来太复杂了,还是因为它似乎不够强大?