Compiler construction 何时使用抽象或具体语法树?

Compiler construction 何时使用抽象或具体语法树?,compiler-construction,abstract-syntax-tree,concrete-syntax-tree,Compiler Construction,Abstract Syntax Tree,Concrete Syntax Tree,我一直在研究编译器。词法分析似乎非常直截了当:把一个“句子”分解成单词(或代词)。为了确保语法正确,需要一个解析器。解析器通常会获取标记并构建一棵树,从而生成根节点(将单词转换成句子、段落、页面等) 从这一点来看,解析器似乎可以构建AST。AST只包含执行代码所需的内容,因此括号之类的内容是不必要的,因为AST中内置了运算符优先级。AST可能是编译器所需要的全部 但是如何将代码从一种语言转换成另一种语言呢?采用一种合成语言(语法)或一种现有语法,并将其转换为另一种,其中运算符优先级规则可能不同,

我一直在研究编译器。词法分析似乎非常直截了当:把一个“句子”分解成单词(或代词)。为了确保语法正确,需要一个解析器。解析器通常会获取标记并构建一棵树,从而生成根节点(将单词转换成句子、段落、页面等)

从这一点来看,解析器似乎可以构建AST。AST只包含执行代码所需的内容,因此括号之类的内容是不必要的,因为AST中内置了运算符优先级。AST可能是编译器所需要的全部

但是如何将代码从一种语言转换成另一种语言呢?采用一种合成语言(语法)或一种现有语法,并将其转换为另一种,其中运算符优先级规则可能不同,也可能不同?操作员优先级是否也“内置”到CST

例如,让我们假设我编写了一种语言,并希望将其转换为PHP代码。大多数语言中的三元运算符具有从右到左的关联性。PHP错误地使用了从左到右的关联性()。我希望“我的语言”从右向左使用,但生成的PHP代码必须应用括号才能在PHP中获得正确的结果(使用,结果需要是“train”而不是“horse”)

那么对于语言翻译来说,CST会更好吗?运算符优先级通常内置于CST中吗?中间有什么事吗?有没有用简单的代数方程来比较这两棵树的例子?有说明三元运算符的例子吗

(转码是“编程语言翻译”的正确术语吗?谷歌搜索会显示转换媒体。)


我想弄清楚的是:什么时候使用一种语言比使用另一种语言更合适?

您只需要一个模拟源语言所有语义细节的AST。根据定义,如果它确实正确地建模了语义,并且您的语言包含了一个三元运算符,那么它也将正确地建模运算符应用的特定顺序(例如,前因模重写的结果,如括号)

所以你的问题不在AST中。它使用优先级不同的类似(三元)运算符生成另一种语言

这是代码生成中一个由来已久的问题:目标的运算符与源的运算符不太匹配,因此输出不能是一对一的。在您的例子中,您应该能够通过生成带有括号的PHP三元运算符来解决问题,以控制实现原始语义的顺序,因此这不是一个大问题

一般来说,生成实现所需结果的代码序列可能相当复杂,而且有很多方法可以做到这一点。这就是为什么编译器的书厚而不是薄。您似乎已经含蓄地决定了“获取AST、行走AST、吐代码”;这几乎是一个动态代码生成器。如果您不关心生成的代码是否特别好,并且目标语言与源语言非常接近,那么这就足够了

如果代码生成问题更复杂,通常情况下,AST用于生成计算的数据流模型,该模型由产生结果的运算符组成,并使用以前运算符的结果,以获取变量值和常量的“运算符”为基础。然后遍历数据流表示以生成代码;这样做的好处是,您可以在数据流表示中选择运算符,在目标语言中找到匹配的代码序列,生成该序列,然后考虑如何收集操作数。更好的方案将数据流子图(表示等效的复合目标语言结构)与生成的数据流图相匹配;这可以产生更好的代码。通常,可以在生成原始代码后应用特定于目标语言的优化,以生成更好的代码。在这两种情况下,您都必须担心如何管理运算符结果;它们可以直接输入下一个目标语言操作员,或者必须进入某种临时存储器(对于机器代码,这可以是另一个寄存器或内存位置)。做这一切并不容易;同样,这也是为什么编译器的书不薄的原因

这种想法的一个变体是源代码到源代码的程序转换。这将源代码中的结构“直接”映射到目标代码中的结构,尽管这通常是通过在AST上操作在幕后完成的,因为未解析的编程语言文本很难匹配。我们的系统就是这种系统的一个例子。使用这样的工具,您可以用源语言(隐式地与解析树匹配)编写模式,并用目标语言(隐式地生成目标语言AST)编写相应的模式。您可以编写复杂的源或目标构造,以提供上述数据流图匹配的大部分效果。生成后优化包括更多重写规则,这些规则将目标代码转换为目标代码

一句话:有一个AST是不够的,除非你的翻译真的很琐碎。 您可以在此阅读更多关于您需要什么的信息,请回答:

警告:以下是响亮的意见

关于“转码器”:我更喜欢术语“编译”、“翻译”或“源代码到源代码”编译器。我已经建立了将近40年的程序分析和操作工具。我从未听说过“转码器”这个词,直到我遇到了这样一个问题:一个描述IMHO的回答是一个真正糟糕的代码翻译方案,叫做NACA。从那以后,我听说这个词越来越受欢迎;我不明白为什么我们必须发明另一个术语,当我们有足够的术语时。通常这是有人发明了一个高级祭司职位的标志;“让我们发明一个闪亮的新术语,这样人们就不会真正理解我们在做什么”。我很高兴离开