【问题标题】:ANTLR 4 and StringTemplate 4 - using tree walker with templatesANTLR 4 和 StringTemplate 4 - 使用带有模板的 tree walker
【发布时间】:2015-07-23 16:26:11
【问题描述】:

免责声明:在上个月之前我从未使用过 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 的示例比以前的版本少得多。

【问题讨论】:

    标签: java antlr4 stringtemplate-4


    【解决方案1】:

    给定一个解析器规则

    r : a b c ;
    

    生成的解析树将包含一个节点 rContext 和子节点 aContextbContextcContex,对于输入流中匹配规则的每个实例,每个可能都有更多的子节点。

    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
        }
    }
    

    何时分析(进入、退出或两者)以及何时输出的细节将取决于特定的应用程序。实施以适合您的目的。

    【讨论】:

    • 所以我要更新 MyGrammarListener.java 文件的进入/退出方法?使用ctx 参数?还是我在侦听器文件之外引用 ctx 以插入 StringTemplate?
    • 谢谢,这真的很有帮助。这是我应该从阅读 ANTLR 4 Reference 中得到的东西吗?还有其他地方可以让我了解有关如何执行此操作的更多信息吗?我在课堂上使用 C++ 时学习了 OOP,但 Java 将其提升到了另一个层次。
    • 我只是对你从哪里得到analysisPhase 以及你如何知道创建descriptor 感到困惑。我已经深入研究了 ANTLR 和 ST API,但我不知道有时应该做什么。
    • GenProjectModel 为例。 GenPackage Wizard 可用于(重新)生成根据您的语法定制的包。
    • 嗨,Grose,我一直在尝试设置 GenPackage 向导,但遇到了一些麻烦。我克隆了 repo 并在 Eclipse 中创建了一个新的 Java 项目来测试它,但我不确定如何实际生成包。我需要编写自己的 main 吗?
    猜你喜欢
    • 1970-01-01
    • 2014-05-28
    • 1970-01-01
    • 1970-01-01
    • 2012-01-23
    • 2012-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多