语义分析器的输入是AST(asbtract语法树)。我的问题是:语义分析器的输出是相同的AST装饰,还是应该是一棵新树?这棵树的名字是什么?要创建这个新树,我可以使用访问者模式吗? 在下面的示例中,在AST(inttofloat)中创建了一个新节点。所以我认为应该始终创建一个新的树。
答案 0 :(得分:2)
虽然这是一个老问题,但它是标准的计算机科学编译器构建课程材料,所以或许需要记录答案。
您的问题没有一个答案,因为没有一种方法可以实现编译器。没有完美正确的答案,这是许多学生认为应该永远存在的答案。考官经常会向学生提出这样的问题,以表明理解和理解不能通过单一答案的死记硬背来证明,这是我认为在这里寻求的。
编译器可以实现为单通道或多通道;抽象语法树可以是内存中的数据结构,也可以通过输出到文件中以更实质的方式记录,在最早的编译器中,文件通过打印到纸带或卡片上进行物理表示!如果输出在编译器阶段之间移动的数据(无论是令牌,抽象语法树,中间代码还是目标代码),那么一组卡片会保存一个抽象语法树,而一组卡片会保存另一个抽象语法树-syntax-tree是不同的树或原始树和该树的另一个版本?即便如此,从哲学角度来说,无论哪种方式都可以争辩。
在现代编译器中,数据可能(通常会)在多个并发任务之间沿着管道的阶段之间移动,形成编译器的不同组件;然后我们又在一根管子上放了一棵树,在另一根管子上放了另一棵树。
但是,如果我们在单个程序中实现编译器,在单个进程中运行,那么我们就不需要有一个树和一个树。编译器的所有部分都可以看到所有存储。语法分析完成后,内存中的树结构可由语义分析器处理。由于语法分析器将永远不再需要,并且语义分析器在处理语法树后将永远不会再次运行,因此无需再创建另一棵树。将树在内存中作为数据结构行走并在原位修改树更有效。在您的示例中,语义分析器将树 intofloat 节点插入树中,以表示代码中此时所需的类型转换。因此,在这种情况下,我们可能会说我们有一个由编译器的所有阶段操纵的树。
现在应该考虑已添加的 intofloat 节点。您可能认为它是树节点对象的新类型或属性。情况可能并非如此。它可以被视为一种运算符形式,例如已经存在的 = , + 和 * 节点。它可能已经在可用的运算符集中。所有语义分析都是明确地向树中添加一个操作符,该操作符可能首先显式包含在代码中。实际上没有创建新形式的节点,只是现有节点类型的另一个实例。它可能是你想象的方式,也可能不是。这两种版本都不是正确或错误的方式。
访问者模式的问题与编译器问题正交。访问者模式主要是面向对象的编程和语言的一个特征。您可以使用树上的访问者模式实现语义分析器,或者您不能,如上一段中所示。它可以以任何一种方式完成,而且没有一个正确的答案。讨论访问者模式在这样一个问题中的作用,可以用来证明访问者模式及其应用的理解,以及抽象语法树的目的和作用。因此,如果您正在寻找一个正确答案(是/否),它就不存在。只有辩论存在。
通过辩论和比较问题中的词语,我们可以表达理解。
如果这是考试课程分配的一部分,那就是所寻求的理解的证明,而不是一个神奇的答案。