我一直在寻找很多关于这一点,我找不到任何有用的,真正帮助我 Build 一个AST . 我已经知道ANTLR4不像以前的ANTLR3那样构建AST . 每个人都说:“嘿,使用访客!”,但我找不到任何示例或更详细的解释如何我这样做...
我的语法必须像C一样,但每个命令都用葡萄牙语(portuga编程语言)编写 . 我可以使用ANTLR4轻松生成解析树 . 我的问题是:现在我需要做些什么才能创建AST?
顺便说一下,我正在使用Java和IntelliJ ......
EDIT1: 我能得到的最接近的是使用这个主题的答案:Is there a simple example of using antlr4 to create an AST from java source code and extract methods, variables and comments?但它只打印被访问方法的名称..
由于第一次尝试对我不起作用,我试图使用来自ANTLR3的this tutorial,但我无法弄清楚如何使用StringTamplate而不是ST ...
读这本书The Definitive ANTLR 4 Reference我也找不到与AST有关的任何东西 .
EDIT2: 现在我有一个类来创建DOT文件,我只需要弄清楚如何正确使用访问者
2 回答
好的,让我们构建一个简单的数学示例 . 构建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访客
现在,让's play a bit with the AST. We' ll必须构建一个AST访问者基类来遍历它 . 让我们做一些类似于ANTLR提供的
AbstractParseTreeVisitor<T>
的事情 .在这里,我利用C#的
dynamic
关键字在一行代码中执行双重调度 . 在Java中,您必须使用如下所示的一系列if
语句自行连接:但我只是去寻找这个例子的捷径 .
使用AST
那么,我们可以用数学表达式树做什么呢?当然要评估它!让我们实现一个表达式求值器:
一旦我们有了AST就很简单,不是吗?
把它们放在一起
最后但并非最不重要的是,我们必须实际编写主程序:
现在我们终于可以玩了:
我创建了一个小型Java项目,允许您通过编译内存中ANTLR生成的词法分析器和解析器来立即测试您的ANTLR语法 . 您可以通过将字符串传递给解析器来解析字符串,它将自动生成一个AST,然后可以在您的应用程序中使用它 .
为了减小AST的大小,您可以使用NodeFilter,您可以在构建AST时添加您希望考虑的非终端的 生产环境 规则名称 .
代码和一些代码示例可以在https://github.com/julianthome/inmemantlr找到
希望这个工具很有用;-)