我有以下IRTree语法: (N *表示N的0、1或多个重复)
IRSequence IRTree*
IRTree **MOVE(TEMP** id, IRExp)
**MOVE(MEM**(IRExp), IRExp)
**JUMP** id
**CJUMP(**IRExp, Op, IRExp, id, id**)**
**OUTPUT(**IRExp**)**
**LABEL** id
**SEQ(**IRTree, IRTree**)**
IRExp **CONST** SIGNED_INT
**BINOP(**IRExp, Op, IRExp**)**
**TEMP** id
**MEM(**IRExp**)**
Op **LT|LE|EQ|ADD|SUB|MUL|DIV**
我将如何实现上述语法的解析器。 我将如何建立AST?
答案 0 :(得分:2)
这是一个很大的话题,在实现之前需要大量研究和理解。我建议解决此问题的方式是使用解析器/词法分析器生成器,例如JFlex和cup,以进行基础学习。一旦掌握了这一点,就可以继续使用其他有助于生成的选项,例如ANTLR。
首先,让我们讨论实现一种语言的三个基本步骤-第一个步骤是词法分析器。
这是JFlex生成词法分析器的地方-一种程序,该程序本质上读取输入文件并确定字符序列中的模式,并分配适当的组“令牌”或本质上是稍后解析器将使用的小标志。
第二步是解析器-程序的一部分,它从词法分析器获取输入的令牌序列,然后对它们进行排序。这是cup派上用场的地方-它可以与JFlex生成的词法分析器配合使用并解析标记。解析器可以包含几个部分,但现在让我们集中讨论语法部分。对于cup,我建议将给定的语法转换为其他形式-称为BNF或EBNF。完成该步骤后,您可以继续进行此问题的下一步,即“抽象语法树”。
AST是解析器的操作部分;以前,您的解析器将标记序列与语法中定义的BNF / EBNF序列匹配,但并未对其进行任何处理。当序列匹配时,您可以选择在CUP中执行动作代码。使用此动作代码,您可以形成一棵树-可以使用多种选择。有些人喜欢使用列表,双向链接列表或树形图列出一些选项。 AST的目标是创建一个映射结构,该结构绘制出语法并将语法关系应用到语法中的称为终端和非终端的部分。
我已经有点头脑了,所以简单地解释一下,终点就是听起来的样子-语法的终点。在您的示例中,这些将是您的比较运算符(LT,GT等)。同样,非终结点是语法中的点,可以分解为其他非终结点或合并的终结点。一个示例是非终端起点,IRSequence是非终端IRTree的父代,IRTree可以具有某些终端,但还是非终端IRExp的父代,IRExp可以在终端终止或包含附加非-终端。
语言的最后一步是编译。但这似乎超出了您的问题,因此我将暂时保留它,并在需要时进行修改。