在计算机科学中,抽象语法树(AST),或者简称语法树,是用编程语言编写的源代码的抽象语法结构的树表示。树的每个节点表示源代码中出现的一个构造。语法是“抽象的”,因为它不代表真实语法中出现的每一个细节,而只是结构性的、与内容相关的细节。例如,分组括号隐含在树结构中,像if-condition-then表达式这样的语法结构可以通过具有三个分支的单个节点来表示。
这将抽象语法树与具体语法树区分开来,具体语法树通常被指定为解析树,解析树通常由解析器在源代码翻译和编译过程中构建。一旦建立,通过后续处理,例如上下文分析,将附加信息添加到AST中。
抽象语法树也用于程序分析和程序转换系统。
抽象语法树是编译器中广泛用于表示程序代码结构的数据结构。AST通常是编译器语法分析阶段的结果。它通常在编译器要求的几个阶段中充当程序的中间表示,并对编译器的最终输出有很大影响。
AST有几个特性有助于编译过程的进一步步骤:
由于编程语言及其文档的固有性质,需要ASTs。语言本质上常常是模糊的。为了避免这种歧义,编程语言通常被指定为上下文无关文法(CFG)。然而,编程语言的某些方面经常是CFG无法表达的,但却是语言的一部分,并记录在它的规范中。这些细节需要上下文来确定它们的有效性和行为。例如,如果一种语言允许声明新的类型,CFG不能预测这些类型的名称,也不能预测它们的使用方式。即使一种语言有一组预定义的类型,强制正确使用通常也需要一些上下文。另一个例子是鸭子类型(duck typing),其中元素的类型可以根据上下文而改变。运算符重载是另一种根据上下文确定正确用法和最终函数的情况。Java提供了一个很好的例子,其中“+”运算符是字符串的数字加法和串联。
虽然编译器的内部工作还涉及其他数据结构,但AST执行一个独特的功能。在第一阶段,语法分析阶段,编译器生成一个解析树。这个解析树可以通过语法导向翻译来执行编译器的几乎所有功能。尽管这种方法可以提高编译器的效率,但它违背了编写和维护程序的软件工程原则。AST相对于解析树的另一个优势是大小,尤其是AST的高度更小,元素数量更少。
AST的设计通常与编译器的设计及其预期特性密切相关。
核心要求包括以下内容:
这些要求可用于设计AST的数据结构。
有些操作总是需要两个元素,例如两个加法项。然而,一些语言构造需要任意数量的参数,例如从命令shell传递给程序的参数列表。因此,用于表示用这种语言编写的代码的AST也必须足够灵活,以允许快速添加未知数量的参数。
AST的另一个主要设计要求是,应该可以将AST反折为源代码形式。重新编译后,生成的源代码在外观上应与原始代码足够相似,在执行上也应完全相同。
由于AST需求的复杂性和编译器的整体复杂性,应用合理的软件开发原则是有益的。其中之一是使用经验证的设计模式来增强模块化和开发的容易性。
不同的操作不一定有不同的类型,所以有一个合理的节点类层次结构是很重要的。随着编译器的发展,这对于AST的创建和修改至关重要。
因为编译器遍历树几次以确定语法正确性,所以使遍历树成为一个简单的操作是很重要的。编译器根据每个节点的类型,在到达它时执行一组特定的操作,所以使用访问者模式通常是有意义的。
AST在语义分析中被大量使用,编译器在语义分析中检查程序元素和语言的正确使用。编译器还在语义分析期间基于AST生成符号表。树的完整遍历允许验证程序的正确性。
验证正确性后,AST作为代码生成的基础。AST通常用于生成代码生成的中间表示(IR),有时称为中间语言。
暂无