免责声明:我上个月之前从未使用过Java,之前我从未听说过ANTLR或StringTemplate。对于今年夏天的实习,我获得了一个项目,使用的工具是该公司从未使用的其他工具。每个人都对我有信心"我会"弄明白。"因此,我的理解存在巨大差距。我喜欢这个项目并且我学到了很多东西,所以不要抱怨这个。我只是想让它发挥作用。
现在,我正在研究一种针对旧域特定语言的漂亮打印机概念验证。我的ANTLR语法正在生成很好的解析树,并且我能够输出简单的StringTemplate示例,如引言中的那些。
假设我的.stg
文件中有一个简单的模板:
module(type, name, content) ::= "<type> MODULE <name>; <content>; END MODULE."
在Java中,我能够使用add()
为每个模板参数设置值:
STGroup g = new STGroupFile("example.stg");
ST st = g.getInstanceOf("module");
st.add("type", "MAIN");
st.add("name", "test");
st.add("content", "abc");
System.out.println(st.render());
// prints "MAIN MODULE test; abc; END MODULE."
如何让ANTLR和ST读入文本文件并生成漂亮的打印输出?
MAIN MODULE test;
abc;
END MODULE.
应该成为
MAIN MODULE test; abc; END MODULE.
例如。 (那不是我计划如何格式化所有输出,不用担心。它打印得比那更漂亮。)
在this answer中,我了解到ANTLR 4会自动生成助行器。 假设我的ANTLR语法正确/写得很好,我如何将ANTLR规则/令牌与我的模板参数匹配以从输入文本文件生成输出?
如果我在某个地方的文档中错过了,请告诉我。与以前的版本相比,ANTLR 4和ST 4的例子要少得多。
答案 0 :(得分:3)
给出解析器规则
r : a b c ;
生成的解析树将包含一个节点rContext
,其中包含子节点aContext
,bContext
,cContex
,每个节点可能还有其他子节点。匹配规则的输入流。
walk将产生一系列听众(或访客)电话
enterR
enterA
....
exitA
enterB
....
exitB
enterC
....
exitC
exitR
每个调用都包含对解析树中实例上下文的引用,允许访问可以相对于插入的子节点以前缀/后缀顺序传递给ST的实际值。
如果单独的简单前缀/后缀访问顺序不够(或不合需要的复杂),请使用一个或多个先前的分析树遍历来分析更复杂的节点并使用分析产品注释节点实例。在最终的输出步骤中,引用要传递给ST的值的分析产品。
根据实际情况,分析节点从其子节点收集值,将批次传递给模板以进行细节扩展,格式化等,并将结果存储为节点注释字符串等待,这并不罕见在最终输出步骤输出。
<强>更新强>
要注释解析树节点,您可以使用ParseTreeProperty。
如果注释集变得超过“微不足道”,典型的选择是将节点类型特定的“装饰器”类实例与解析树节点/上下文实例关联,主要是作为更好的数据容器。当然,然后可以将节点类型特定的方法嵌入到它们相应的装饰器类中,以使关注点保持良好分离。
监听器方法变成这样:
public void exitNodeB(NodeBContext ctx) {
super.exitNodeB(ctx);
NodeBDescriptor descriptor = (NodeBDescriptor) getDescriptor(ctx);
if (analysisPhase) {
descriptor.process(); // node-type specific analysis
} else {
descriptor.output(); // node-type specific output generation
}
}
何时分析(进入,退出或两者)以及何时输出的具体细节取决于具体应用。实施以满足您的目的。