具体语法树匹配语法规则所说的语法。 抽象语法树的目的是对“语法树”中的基本内容进行“简单”表示。
AST 恕我直言的真正价值在于它比 CST 小,因此处理时间更短。 (你可能会说,谁在乎呢?但我使用的是我们拥有的工具
数以千万计的节点同时存在!)。
大多数支持构建语法树的解析器生成器都坚持要求您亲自指定它们的构建方式,前提是您的树节点将比 CST“更简单”(在这一点上,它们通常是正确的,因为程序员很懒)。可以说,这意味着您必须编写更少的树访问函数,这也很有价值,因为它可以最大限度地减少工程能量。当您有 3500 条规则时(例如,对于 COBOL),这很重要。而这种“简单”又导致了“小”的良好特性。
但是拥有这样的 AST 会产生一个不存在的问题:它与语法不匹配,现在您必须在心理上跟踪它们。当 3500 个规则语法有 1500 个 AST 节点时,这很重要。如果语法不断发展(他们总是这样!),那么现在你有两套巨大的东西要保持同步。
另一个解决方案是让解析器简单地为您构建 CST 节点并使用它们。这在构建语法时是一个巨大的优势:无需发明 1500 个特殊的 AST 节点来建模 3500 个语法规则。想想这棵树与语法同构。从语法工程师的角度来看,这完全是无脑的,这让他可以专注于正确地编写语法并尽情发挥。可以说您必须编写更多节点访问者规则,但这可以管理。稍后会详细介绍。
我们对DMS Software Reengineering Toolkit 所做的是根据 (GLR) 解析过程的结果自动构建 CST。然后,出于空间效率的原因,DMS 会自动构造一个“压缩的”CST,方法是消除非携带值的终结符(关键字、标点符号)、语义上无用的一元产生式,并为语法规则对形成可直接索引的列表,如下所示:
L = e ;
L = L e ;
L2 = e2 ;
L2 = L2 ',' e2 ;
以及此类形式的各种变体。您根据语法规则和虚拟 CST 进行思考;该工具对压缩表示进行操作。让您的大脑轻松,运行时更快/更小。
值得注意的是,以这种方式构建的压缩 CST 看起来很像您可能手动设计的 AST(参见示例末尾的链接)。特别是,压缩的 CST 不携带任何只是具体语法的节点。
有一些小尴尬:例如,虽然表达式子语法中经典的 '(' 和 ')' 的具体节点不在树中,但“括号节点”确实出现在压缩的 CST 中并且必须处理。真正的 AST 不会有这个。对于不必指定 AST 构造的便利性,这似乎是一个很小的代价。并且树的文档始终可用且正确:语法是文档。
我们如何避免“额外访客”?我们不完全是,但 DMS 提供了一个 AST 库,它遍历 AST 并透明地处理 CST 和 AST 之间的差异。 DMS 还提供了一个“属性语法”评估器 (AGE),它是一种用于在树上和下层传递计算出的值的方法; AGE 处理所有的树表示问题,因此工具工程师只担心直接在语法规则本身上有效地编写计算。最后,DMS 还提供了“表面语法”模式,它允许语法中的代码片段用于查找特定类型的子树,而无需了解所涉及的大多数节点类型。
其他答案之一是,如果您想构建可以重新生成源代码的工具,您的 AST 必须与 CST 匹配。这不太对,但如果您有 CST 节点,则重新生成源要容易得多。 DMS generates most of the prettyprinter automatically 因为它可以访问两者:-}
底线:AST 适合小型的,无论是物理的还是概念的。来自 CST 的自动 AST 构造提供了这两者,并让您避免跟踪两个不同集合的问题。
2015 年 3 月编辑:Link to examples of CST vs. "AST" built this way