ANTLR 4 和 StringTemplate 4 - 使用带有模板的 tree walker
ANTLR 4 and StringTemplate 4 - using tree walker with templates
免责声明:我在上个月之前从未使用过 Java,在那之前我也从未听说过 ANTLR 或 StringTemplate。在今年夏天的实习中,我得到了一个使用公司其他人从未使用过的工具的项目。每个人 "has faith in me" 我会 "figure it out." 因此我的理解存在巨大差距。我喜欢这个项目而且我学到了很多东西,所以不要把这当成抱怨。我只是想让它发挥作用。
现在我正在为一种旧的特定于领域的语言开发一个漂亮的打印机概念证明。我的 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 会自动生成 walker。 假设我的 ANTLR 语法是 correct/well-written,我如何将 ANTLR rules/tokens 匹配到我的模板参数以从输入文本文件生成输出?
如果我在某处的文档中遗漏了它,请告诉我。 ANTLR 4 和 ST 4 的例子比以前的版本少了很多。
给定解析器规则
r : a b c ;
生成的解析树将包含一个节点 rContext
,其子节点为 aContext
、bContext
、cContex
,对于每个实例,每个子节点都可能有更多的子节点在匹配规则的输入流中。
步行将产生一系列听众(或访客)呼叫
enterR
enterA
....
exitA
enterB
....
exitB
enterC
....
exitC
exitR
每个调用都包含对解析树中实例上下文的引用,从而可以访问可以相对于中间子节点按 prefix/suffix 顺序传递给 ST 的实际值。
如果单靠简单的 prefix/suffix 访问排序是不够的(或复杂得不理想),请使用一个或多个先前的解析树遍历来分析更复杂的节点,并使用分析产品对节点实例进行注释。在最终的输出走动中,参考分析产品以获取要传递给 ST 的值。
根据实际情况,分析节点从其子节点收集值,将批次传递给模板进行细节扩展、格式化等,并将结果存储为节点注释并不罕见最终输出遍历中的字符串待处理输出。
更新
要注释分析树节点,您可以使用ParseTreeProperty。
当注释集超过 'trivial' 时,一个典型的选择是将节点类型特定的 'decorator' class 实例与解析树 node/context 相关联实例主要作为更好的数据容器。当然,然后可以将特定于节点类型的方法嵌入到它们相应的装饰器中 classes 以很好地分离关注点。
侦听器方法变成这样:
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
}
}
何时分析(进入、退出或两者)以及何时输出的细节将取决于特定的应用程序。实施以满足您的目的。
免责声明:我在上个月之前从未使用过 Java,在那之前我也从未听说过 ANTLR 或 StringTemplate。在今年夏天的实习中,我得到了一个使用公司其他人从未使用过的工具的项目。每个人 "has faith in me" 我会 "figure it out." 因此我的理解存在巨大差距。我喜欢这个项目而且我学到了很多东西,所以不要把这当成抱怨。我只是想让它发挥作用。
现在我正在为一种旧的特定于领域的语言开发一个漂亮的打印机概念证明。我的 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 会自动生成 walker。 假设我的 ANTLR 语法是 correct/well-written,我如何将 ANTLR rules/tokens 匹配到我的模板参数以从输入文本文件生成输出?
如果我在某处的文档中遗漏了它,请告诉我。 ANTLR 4 和 ST 4 的例子比以前的版本少了很多。
给定解析器规则
r : a b c ;
生成的解析树将包含一个节点 rContext
,其子节点为 aContext
、bContext
、cContex
,对于每个实例,每个子节点都可能有更多的子节点在匹配规则的输入流中。
步行将产生一系列听众(或访客)呼叫
enterR
enterA
....
exitA
enterB
....
exitB
enterC
....
exitC
exitR
每个调用都包含对解析树中实例上下文的引用,从而可以访问可以相对于中间子节点按 prefix/suffix 顺序传递给 ST 的实际值。
如果单靠简单的 prefix/suffix 访问排序是不够的(或复杂得不理想),请使用一个或多个先前的解析树遍历来分析更复杂的节点,并使用分析产品对节点实例进行注释。在最终的输出走动中,参考分析产品以获取要传递给 ST 的值。
根据实际情况,分析节点从其子节点收集值,将批次传递给模板进行细节扩展、格式化等,并将结果存储为节点注释并不罕见最终输出遍历中的字符串待处理输出。
更新
要注释分析树节点,您可以使用ParseTreeProperty。
当注释集超过 'trivial' 时,一个典型的选择是将节点类型特定的 'decorator' class 实例与解析树 node/context 相关联实例主要作为更好的数据容器。当然,然后可以将特定于节点类型的方法嵌入到它们相应的装饰器中 classes 以很好地分离关注点。
侦听器方法变成这样:
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
}
}
何时分析(进入、退出或两者)以及何时输出的细节将取决于特定的应用程序。实施以满足您的目的。