【问题标题】:Accessing string template rule names from ANTLR base listener从 ANTLR 基本侦听器访问字符串模板规则名称
【发布时间】:2015-08-05 16:41:22
【问题描述】:

使用漂亮的打印机。根据我目前对 ANTLR 和 StringTemplate 的理解,如果我想将我的所有语法规则与模板匹配并在每次调用语法规则时应用模板,我可以创建名称与我的语法规则匹配的模板。

[附带问题:我应该这样处理它吗?似乎 ANTLR 应该将解析后的文本与输出模板进行匹配。我的工作是确保解析器规则和模板是完整/正确的。]

我认为 ANTLR 3 允许在 ANTLR 语法中直接设置模板,但 ANTLR 4 似乎已经不再这样做了。

基于上述假设,看起来 ANTLR 生成的 MyGrammarBaseListener 类将完成所有工作。

通过将this example 转换为ANTLR 4,我已经能够收集在解析文本输入时调用的规则的名称。我的enterEveryRule() 最终得到了这个:

@Override public void enterEveryRule(ParserRuleContext ctx) {
    if (builder.length() > 0) {
        builder.append(' ');
    }

    if (ctx.getChildCount() > 0) {
        builder.append('(');
    }

    int ruleIndex = ctx.getRuleIndex();
    String ruleName;
    if (ruleIndex >= 0 && ruleIndex < ruleNames.length) {
        ruleName = ruleNames[ruleIndex];
        System.out.println(ruleName); // this part works as intended
    }
    else {
        ruleName = Integer.toString(ruleIndex);
    }

    builder.append(ruleName);

    // CONFUSION HERE:
    // get template names (looking through the API to figure out how to do this)
    Set<String> templates = (MyTemplates.stg).getTemplateNames()
    // or String[] for return value? Java stuff

    // for each ruleName in ruleNames
    //     if (ruleName == templateName)
    //         run template using rule children as parameters
    //         write pretty-printed version to file
}

链接示例应用更改以在exitEveryRule() 中创建文本输出,因此我不确定在哪里实际实现我的模板匹配算法。我将同时尝试enterexit,看看哪个效果最好。

我的主要问题是:如何访问 MyTemplates.stg 中的模板名称?我必须导入什么等?

(我可能会在另一个问题中再次询问有关将规则子代与模板参数匹配的问题...)

【问题讨论】:

    标签: java antlr4 stringtemplate-4


    【解决方案1】:

    以下演示了一种动态访问和呈现名为 StringTemplates 的简单方法。目的是在监听器(或访问者)的相应上下文中构建varMap 值,以参数名称为键,并调用依赖于上下文的命名模板以增量呈现模板的内容。

    public class Render {
    
        private static final String templateDir = "some/path/to/templates";
        private STGroupFile blocksGroup;
        private STGroupFile stmtGroup;
    
        public Render() {
            blocksGroup = new STGroupFile(Strings.concatAsClassPath(templateDir, "Blocks.stg"));
            stmtGroup = new STGroupFile(Strings.concatAsClassPath(templateDir, "Statements.stg"));
        }
    
        public String gen(GenType type, String name) {
            return gen(type, name, null);
        }
    
        /**
         * type is an enum, identifying the group template
         * name is the template name within the group
         * varMap contains the named values to be passed to the template
         */
        public String gen(GenType type, String name, Map<String, Object> varMap) {
            Log.debug(this, name);
            STGroupFile stf = null;
            switch (type) {
                case BLOCK:
                    stf = blocksGroup;
                    break;
                case STMT:
                    stf = stmtGroup;
                    break;
            }
            ST st = stf.getInstanceOf(name);
            if (varMap != null) {
                for (String varName : varMap.keySet()) {
                    try {
                        st.add(varName, varMap.get(varName));
                    } catch (NullPointerException e) {
                        Log.error(this, "Error adding attribute: " + name + ":" + varName + " [" + e.getMessage() + "]");
                    }
                }
            }
            return st.render();
        }
    }
    

    【讨论】:

    • 你是我的英雄。我认为我应该查看更多示例模板文件,以了解如何将语言单元映射到模板。我看到您如何使用键值对来处理参数。我需要每个模板还是每个文件都需要一个案例?此外,将模板分成不同的 .st/.stg 文件是否常见?我把它想象成与我的 ANTLR 语法类似。
    • 每个.stg 一个case - 每个.stg 文件可以存储许多命名模板。使用多个 .stgs 纯粹是为了您的方便 - 让您更容易找到各个模板。此外,每个.stg 就像一个单独的命名空间——也许你有足够的语义理由来拥有两个不同但名称相同的模板,比如一个用于语句,一个用于块。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-11
    相关资源
    最近更新 更多