Parsing LL自顶向下解析器,从CST到AST

Parsing LL自顶向下解析器,从CST到AST,parsing,abstract-syntax-tree,state-machine,Parsing,Abstract Syntax Tree,State Machine,我目前正在学习语法分析,尤其是自顶向下的语法分析 我知道自下而上的LR解析器的术语和区别,而且自上而下的LL解析器更容易手工实现,因此我期待着自己的解析器 我见过两种方法: 递归下降法是一种使用递归函数集合的方法 基于堆栈和表驱动的自动机 我对后者更感兴趣,因为它的强大和消除了调用堆栈递归。但是,我不明白如何从隐式解析树构建AST 一个基于堆栈的有限自动机的实例显示解析器分析输入缓冲区,仅在语法被接受时给出是/否回答 我听说过为了构建AST而使用堆栈注释,但我不知道如何实现它们。有人能提供这

我目前正在学习语法分析,尤其是自顶向下的语法分析

我知道自下而上的LR解析器的术语和区别,而且自上而下的LL解析器更容易手工实现,因此我期待着自己的解析器

我见过两种方法:

  • 递归下降法是一种使用递归函数集合的方法
  • 基于堆栈和表驱动的自动机
我对后者更感兴趣,因为它的强大和消除了调用堆栈递归。但是,我不明白如何从隐式解析树构建AST

一个基于堆栈的有限自动机的实例显示解析器分析输入缓冲区,仅在语法被接受时给出是/否回答


我听说过为了构建AST而使用堆栈注释,但我不知道如何实现它们。有人能提供这种技术的实际实现吗?

您需要理解背后的概念。你需要理解下推自动机的概念。在你们理解了如何用铅笔在纸上进行计算后,你们将能够理解通过递归下降或堆栈实现其想法的多种方法。思想是一样的,当您使用递归下降时,您隐式地拥有程序用于执行的堆栈,其中执行数据与解析自动机数据相结合

我建议您从Ullman(automata)或Dick Grune教授的课程开始,这门课程最专注于解析。(格伦的书是),寻找第二版

对于LR解析来说,关键是理解Earley的思想,Don Knuth根据这些思想创建了LR方法

对于LL解析,Grune的书非常优秀,Ullman在纸上介绍了计算,解析的数学背景对于了解您是否想要实现自己的解析器至关重要


关于AST,这是解析的输出。解析器将生成在AST中转换的解析树,或者可以直接生成并输出AST。

您需要理解背后的概念。你需要理解下推自动机的概念。在你们理解了如何用铅笔在纸上进行计算后,你们将能够理解通过递归下降或堆栈实现其想法的多种方法。思想是一样的,当您使用递归下降时,您隐式地拥有程序用于执行的堆栈,其中执行数据与解析自动机数据相结合

我建议您从Ullman(automata)或Dick Grune教授的课程开始,这门课程最专注于解析。(格伦的书是),寻找第二版

对于LR解析来说,关键是理解Earley的思想,Don Knuth根据这些思想创建了LR方法

对于LL解析,Grune的书非常优秀,Ullman在纸上介绍了计算,解析的数学背景对于了解您是否想要实现自己的解析器至关重要

关于AST,这是解析的输出。解析器将生成在AST中转换的解析树,或者可以直接生成和输出AST。

“自顶向下”和“自下而上”是对这两种解析策略的极好描述,因为它们精确地描述了如果构造语法树,将如何构造语法树。(您也可以将其视为隐式解析树上的遍历顺序,但这里我们实际上对真正的解析树感兴趣。)

显然,自下而上的树结构有一个优势。当需要向树中添加节点时,您已经知道其子节点是什么。您可以在一个(功能)动作中构造完全成形的节点。所有子信息都在那里等待着您,因此您可以根据其子节点的语义信息向节点添加语义信息,甚至可以按从左到右以外的顺序使用子节点

相反,自顶向下的解析器构造节点时没有任何子节点,然后需要将每个子节点依次添加到已构造的节点中。这当然有可能,但有点难看。此外,节点构造函数的增量性质意味着附加到节点的语义信息也需要增量计算,或者推迟到节点完全构造为止

在许多方面,这类似于使用反向波兰符号(RPN)编写的表达式与使用(正向)波兰符号编写的表达式之间的差异【注1】。RPN的发明正是为了简化评估,这可以通过一个简单的值堆栈实现。显然,可以对前向波兰表达式进行求值:最简单的方法是使用递归求值器,但在无法依赖调用堆栈的环境中,可以使用运算符堆栈进行求值,从而有效地将表达式动态转换为RPN

因此,这可能也是从自顶向下的解析器构建语法树的首选机制。我们在每一条右手边的末端添加一个“减少”标记。因为标记在右手边的末端,所以它首先被推

我们还需要一个值堆栈来记录正在构造的AST节点(或语义值)

在基本算法中,我们现在还有一种情况。我们首先弹出解析器堆栈的顶部,然后检查此对象:

  • 解析器堆栈的顶部是一个终端。如果当前输入符号是同一个终端,我们将从输入中删除输入符号,并将其(或其语义值)推送到值堆栈上

  • 解析器堆栈的顶部是一个标记。触发相关的缩减操作,该操作将通过从值堆栈中弹出适当数量的值并将它们组合到新的AST节点中来创建新的AST节点,然后将该节点推送到v上