它们是由编译过程的不同阶段产生的吗? 或者它们只是同一事物的不同名称?
据我所知,AST 更侧重于源代码组件之间的抽象关系,而解析树侧重于语言所使用的语法的实际实现,包括吹毛求疵的细节。它们肯定不一样,因为“解析树”的另一个术语是“具体语法树”。
Martin Fowler 的 DSL book很好地解释了这一点。AST 只包含将用于进一步处理的所有“有用”元素,而解析树包含所解析的原始文档中的所有构件(空格、括号、 ...)
AST 从概念上描述源代码,它不需要包含解析某些源代码所需的所有语法元素(大括号、关键字、括号等)。
Parse 树更接近地表示源代码。
在 AST 中,IF 语句的节点只能包含三个子节点:
对于类 C 语言,Parse Tree 还需要包含“ if”关键字、括号和花括号的节点。
This is based on the 表达式计算器 grammar by Terrence Parr.
The grammar for this example:
grammar Expr002; options { output=AST; ASTLabelType=CommonTree; // type of $stat.tree ref etc... } prog : ( stat )+ ; stat : expr NEWLINE -> expr | ID '=' expr NEWLINE -> ^('=' ID expr) | NEWLINE -> ; expr : multExpr (( '+'^ | '-'^ ) multExpr)* ; multExpr : atom ('*'^ atom)* ; atom : INT | ID | '('! expr ')'! ; ID : ('a'..'z' | 'A'..'Z' )+ ; INT : '0'..'9'+ ; NEWLINE : '\r'? '\n' ; WS : ( ' ' | '\t' )+ { skip(); } ;
输入
x=1 y=2 3*(x+y)
解析树
解析树是输入的具体表示形式。解析树保留输入的所有信息。空格表示空格,即行尾。
AST
AST 是输入的抽象表示。注意,AST 中没有括号,因为关联可以从树结构派生。
更详细的解释见 编译器和编译器生成器第23页 or 抽象语法树 on pg. 21 in 程序设计语言的语法和语义
下面是在编译器构造上下文中对 解析树木(具体语法树,CST)和 抽象语法树(AST)的解释。它们是相似的数据结构,但它们的构造不同,用于不同的任务。
解析树通常是在词法分析之后的下一步生成的(它将源代码转换为一系列标记,这些标记可以被视为有意义的单位,而不仅仅是一系列字符)。
它们是树状的数据结构,显示了如何通过有关语言的语法生成一个输入终端字符串(源代码标记)。解析树的根是语法的最一般符号-开始符号(例如,声明) ,内部节点表示开始符号扩展到的非终端符号(可以包括开始符号本身) ,例如 表情、 声明、 任期、 function call。叶子是语法的终端,实际的符号在语言/输入字符串中作为标识符、关键字和常量出现,例如 为了、 9、 如果等。
在解析编译器时,还要执行各种检查以确保语法的正确性,并且语法错误报告可以嵌入到解析器代码中。
它们可以通过语法定向的定义或翻译方案用于语法定向的翻译,也可以用于简单的任务,例如将中缀表达式转换为后缀表达式。
下面是表达式 9 - 5 + 2的解析树的图形表示(请注意树中终端的位置和表达式字符串中的实际符号) :
9 - 5 + 2
AST 表示语法 某些代码的结构。编程结构的树,例如表达式、流控制语句等,分为操作符(内部节点)和操作数(叶子)。例如,表达式 i + 9的语法树将运算符 +作为根,变量 i作为运算符的左子,数字 9作为右子。
i + 9
+
i
9
这里的区别在于,非终端和终端不起作用,因为 AST 不处理语法和字符串生成,而是编程构造,因此它们代表这些构造之间的关系,而不是它们由语法生成的方式。
请注意,操作符本身是给定语言中的编程构造,并且不一定是实际的计算操作符(如 +) : for循环也将以这种方式处理。例如,您可以有一个语法树,比如 for [ expr, expr, expr, stmnt ](内联表示) ,其中 for是 接线员,方括号内的元素是它的子元素(代表 C 的 for语法)-也由运算符等组成。
for
for [ expr, expr, expr, stmnt ]
AST 通常也是由编译器在语法分析(解析)阶段生成的,后来用于语义分析、中间表示、代码生成等。
下面是 AST 的图形表示:
在解析树中,内部节点是非终端的,叶子是终端的。 在语法树中,内部节点是操作符,叶子是操作数。
接受帕斯卡的任务 年龄: = 42;
语法树看起来就像源代码。 [年龄][ : = ][42][ ; ]
抽象树应该是这样的 [ = ][年龄][42]
赋值变成一个有两个元素的节点,年龄和42。这个想法就是你可以执行这个任务。
还要注意帕斯卡语法消失了。因此,有可能有不止一种语言生成相同的 AST。这对跨语言脚本引擎很有用。
维基百科说
解析树具体地反映了输入语言的语法,使它们不同于计算机编程中使用的抽象语法树。
Quora 上的一个答案是
解析树是用于匹配某些输入文本的规则(和标记)的记录,而语法树记录输入的结构,并且对产生输入的语法不敏感。
结合上述两个定义,
Abstract Syntax Tree在逻辑上描述解析树。它不需要包含解析某些源代码(空格、大括号、关键字、括号等)所需的所有语法结构。这就是为什么 Parse Tree也被称为 Concrete Syntax Tree,而 AST 被称为 Syntax Tree。语法分析器的输出实际上就是语法树。
Abstract Syntax Tree
Parse Tree
Concrete Syntax Tree
Syntax Tree