数据结构-程序范围的数据结构?

我正在尝试通过程序的AST来解析一种组合语言,具体来说,我正在尝试模拟范围,因此您输入一个函数,例如,推入一个新范围,以及该函数何时完成被访问者访问时,它弹出了作用域.一个重要方面是,当我们推送新范围时,会设置一个指针currentScope,该指针指向我们当前正在查看的范围.当我们弹出范围时,此currentScope设置为“外部”:

class Scope:
    outer : Scope
    inner : Scope

这将在多个过程中发生,但是第一遍重要的是构造通用的作用域树.
我要问的问题是如何以创建树的顺序遍历该树?
例如:

{ // global scope
    { // a
        { // aa

        }
        { // ab
        }
    }
    { // b
    }
}

从理论上讲,当我再次传递完全相同的节点集时,它们将为我提供相同的作用域树,但我想保留我们收集的所有数据,并在每次传递中存储每个作用域.换句话说,当第二遍或第三遍通过AST时,当我们访问a时,currentScope = a,而当我们访问aa时,currentScope = aa.这可能吗?我真的对这个想法感到困惑,整个递归y方面真的让我很头疼,而且我似乎不知道该怎么做.

这是我尝试过的:

class Scope
    outer : Scope
    inner : Scope
    siblings : []Scope

    Scope(outer):
        this.outer = outer

push_idx = 0

push_scope()
    // set global scope
    if current is null
        global = new Scope(null)
        current = global
        return

    if current.inner is not null:
        // first pass over the AST
        if current_pass == 0:
            new_scope = new Scope(current)
            current.siblings.push(new_scope)
            current = new_scope
            return
        current = current.siblings[push_idx++]
    else:
        new_scope = new Scope(current)
        current.inner = new_scope
        current = current.inner

pop_scope()
    push_idx = 0
    current = current.outer

尽管顺序似乎不正确,但我相当确定这是错误的处理方法.

最佳答案
意大利面条堆栈通常用于跟踪编译器内部范围的数据结构,它实际上是一个链表数据结构,其中每个范围都是一个节点,该节点存储指向其父范围的指针.无论何时输入范围,都将创建一个新节点,将其指向封闭的范围,然后将该节点存储在与该范围关联的AST中.遍历AST时,您的AST遍历器将存储指向当前作用域节点的指针.输入范围时,如上所述,您将创建一个新的范围节点.离开范围时,更改指针以指向当前范围的父级.这样最终构建了一个大型的倒置树结构,其中每个合并范围都可以跟踪其合并范围链直到根范围(意大利面条堆栈).

转载注明原文:数据结构-程序范围的数据结构? - 代码日志