抽象语法树问题

时间:2009-12-26 00:31:38

标签: c compiler-construction abstract-syntax-tree

我目前正在研究C下的编译器,我在构建AST数据结构的部分丢失了,特别是对于构建ID结构的部分,它被称为“符号表条目”

我看到网上的结构如:

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),但这背后的逻辑是什么?

3 个答案:

答案 0 :(得分:8)

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

{
int x;
  {
   int x;
  }
}

但是,符号节点可能希望在列表中排列的原因还有很多其他原因。编译器需要访问所有节点的任何原因都是原因。

答案 1 :(得分:2)

你很快就会看到来自C程序员的有害习惯的残羹剩饭:假设符号将出现在某些列表中,而不是单独分配列表结构,列表指针作为符号结构的一部分包含在内。这个技巧为每个列表元素保存了一个分配,但代价是:符号可以打开的列表集是固定的,这种结构使程序员感到困惑。如果应用程序是编译器,则没有理由再次使用此技巧。更清楚的是有一个单独的列表结构定义如下:

struct ste_list {
    struct ste *symbol_table_entry;
    struct str_list *next;
};

你可以随心所欲地拥有这些,没有人更聪明。而你发现的内部指针会让人感到困惑。

你问

  

这背后的逻辑是什么?

部分答案很简单,在尊贵列表上添加符号很有用。在不了解特定编译器的情况下,我无法明确地回答这个问题。我最好的猜测是prev条目将用于实现嵌套作用域(C中的{ ... }括号),但这是基于我见过或编写过的编译器的猜测。因此,逻辑可能是当遇到右括号时,编译器可能会跟随该链接,直到它到达封闭范围中的ste。与您正在研究的编译器的作者相比,具有更多经验的人通常会将此逻辑放在“符号表抽象”中,其中包括enterscope()exitscope()等函数,以及这些操作将从各个符号表条目的内部表示中隐藏。

答案 2 :(得分:1)

我首先考虑使用反向链表来支持那些支持覆盖变量名的语言,例如:

int main (void) {
    int x = 1;
    int y = 1;
    if (x == 1) {
        int y = 2;
        printf ("y = %d\n", y);
    }
    return 0;
}

在这种情况下,您希望访问具有最里面范围的变量(最后一个定义的变量)。这可以通过向后走过列表找到(假设您正在通过前进构建列表)。

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

当然,你可以通过在当前头部之前插入而不是添加到列表的末尾(这看起来像概念正在做什么,只需使用名为{的指针来实现相同的效果。 {1}}代替prev)。