我已经找了很多关于这个的东西,但是我找不到任何有用的东西来帮助我建立一个ast。我已经知道antlr4不像antlr3那样构建ast。每个人都说:“嘿,利用访客!”,但我找不到任何例子或更详细的解释,我如何才能做到这一点。。。
我的语法一定很像c,但是每一个命令都是用葡萄牙语(葡萄牙编程语言)写的。我可以使用antlr4轻松地生成解析树。我的问题是:我现在需要做什么来创建ast?
顺便说一句,我正在使用java和intellij。。。
edit1:我能得到的最接近的答案是使用这个主题的答案:有没有一个简单的例子使用antlr4从java源代码创建ast并提取方法、变量和注解?但它只打印访问的方法的名称。。
由于第一次尝试并没有像我预期的那样对我有效,我尝试使用antlr3的这个教程,但是我不知道如何使用stringtamplate而不是st。。。
阅读这本书的权威antlr4参考我也找不到任何与asts有关的东西。
edit2:现在我有一个类来创建点文件,我只需要弄清楚如何正确使用访问者
3条答案
按热度按时间cx6n0qe31#
好的,让我们建立一个简单的数学例子。构建一个ast对于这样的任务来说是完全多余的,但是这是一个很好的展示原理的方法。
我会用c语言来做,但是java版本会非常相似。
语法
首先,让我们编写一个非常基本的数学语法:
很基本的东西,我们有一个
expr
处理一切的规则(优先规则等)。ast节点
然后,让我们定义一些我们将使用的ast节点。这些都是完全定制的,你可以用你想要的方式来定义它们。
下面是我们将用于此示例的节点:
将cst转换为ast
antlr为我们生成cst节点(
MathParser.*Context
类)。我们现在必须将这些节点转换为ast节点。这对于访问者来说是很容易做到的,antlr为我们提供了一个
MathBaseVisitor<T>
同学们,让我们一起来。如您所见,这只是使用访问者从cst节点创建ast节点的问题。代码应该是非常自解释的(除了
VisitFuncExpr
但这只是一种将委托连接到合适的方法的快速方法System.Math
类)。这里是ast建筑材料。这就是所需要的。只需从cst中提取相关信息并保存在ast中。
最后的来访者
现在,让我们玩一下ast。我们必须构建一个ast visitor基类来遍历它。让我们做一些类似于
AbstractParseTreeVisitor<T>
由antlr提供。在这里,我利用了c
dynamic
关键字在一行代码中执行双重分派。在java中,您必须自己用一系列if
像这样的陈述:但我只是选择了这个例子的捷径。
与ast合作
那么,我们能用数学表达式树做什么呢?当然,评估一下!让我们实现一个表达式计算器:
一旦我们有了ast就很简单了,不是吗?
把它们放在一起
最后但同样重要的是,我们必须实际编写主程序:
现在我们终于可以玩了:
owfi6suc2#
我创建了一个小的java项目,通过编译antlr在内存中生成的lexer和parser,您可以立即测试antlr语法。您可以通过将字符串传递给解析器来解析它,它将自动从中生成ast,然后可以在应用程序中使用它。
为了减小ast的大小,可以使用nodefilter,向其中添加在构造ast时要考虑的非终端的产生式规则名称。
代码和一些代码示例可以在https://github.com/julianthome/inmemantlr
希望工具有用;—)
ubbxdtey3#
我发现了两种简单的方法,重点是antlr4的testrig.java文件中提供的功能。
通过终端
这是我用相应的cpp14.g4语法文件解析c的示例
java -cp .:antlr-4.9-complete.jar org.antlr.v4.gui.TestRig CPP14 translationunit -tree filename.cpp
. 如果省略filename.cpp,装备将从stdin读取。“translationunit”是我使用的cpp14.g4语法文件的开始规则名称。通过java
我使用了testrig.java文件中的部分代码。让我们再次假设我们有一个c源代码字符串,我们希望从中生成ast(您也可以直接从文件中读取)。
我的进口是:
所有这些都要求您使用命令生成必要的文件(lexer、parser等)
java -jar yournaltrfile.jar yourgrammar.g4
然后编译所有的*.java文件。