如何通过实现ANTLR生成的Visitor来创建一个复杂的POJO

How to create a complex POJO by implementing the Visitor generated by ANTLR

我正在使用 ANTLR4 并为我正在设计的一种新语言编写了词法分析器和解析器语法。我想通过解析该语言来创建 Java POJO。

语言

{dept dept-name="human resources"}
   {emp name="john doe" age=23 address="123 Main St, Spring Field, CO 12345" /}
{/dept}

Java POJO

public class Department {
  private final class name;
  private final List<Employee>
}

public class Employee {
  private final String name;
  private final int age;
  private final Address address;
}

public class Address {
  private final String streetAddress;
  private final String city;
  private final String state;
  private final int zip;
  private final int zipExt;
}

我已经能够正确定义语法。我能够使用 Antlr 工具生成访客 class。 Visitor class 采用通用类型 T,并且 return 在访问每个节点时使用类型 T 的实例。我在访问 AST 的地址部分时需要 return 一个地址,在访问 AST 的员工部分时需要一个员工。所以我不确定访问者实现的类型 T 应该是什么。

我很困惑如何通过实现 ANTLR 给出的访问者来构建上述 Department POJO。

PS:请注意,我无法更改部门、员工、地址 classes。另外,请不要建议使用 XML 或 JSON。我只是想了解如何在 ANTLR 中解决此类问题。

谢谢!

假设这是你的 parser.g4 语法的头部 你的整个脚本就是一个filefile可以由多个元素组成。 元素可以是 pagepageGrouppagepageGroup 还有其他成分。

parser grammar MyCustomParser;
file: element* EOF;
element: page | pageGroup;

然后一旦你 运行 Antlr 命令你会得到很多生成的文件,其中大部分可能被命名为 MyCustomParser$XXXContext.class。这些文件代表您的解析树中的节点。在我们的例子中,我们将有 MyCustomParser.PageContextMyCustomParser.PageGroupContext 等等。

一个特别重要的节点是解析树的根节点,MyCustomParser.FileContext。它的子元素将是元素上下文,元素上下文的子元素将是上面提到的页面上下文或页面组上下文。

现在有了这个根节点,您需要做的就是从根开始递归访问解析树中的所有节点。当您访问节点时,您可以根据存储在这些节点中的值生成您的 POJO。

获取根节点

//....
MyCustomParser parser = new MyCustomParser(tokens);
MyCustomParser.FileContext fileContext = parser.file();

注意我们调用了方法file()。方法名称与您的根规则名称相同。

您不必使用生成的树访问器。它只是为了帮助您节省一些锅炉模板代码,因为在大多数情况下,我们以相同的方式穿越这棵树或那棵树。

您提到了通用类型问题。大多数时候,您的 POJO 可能有一个共同的父级 class,或者实现一个共同的接口。然后你可以只使用父 class 或接口。但是在你的情况下,你不能修改POJO,所以使用生成的树可能并不容易。