0

かわいいプリンターで作業しています。これまでの ANTLR と StringTemplate の理解に基づいて、すべての文法規則をテンプレートに一致させ、文法規則が呼び出されるたびにテンプレートを適用する場合は、文法規則に一致する名前でテンプレートを作成できます。

[副次的な質問: これは私がそれに取り組むべき方法ですか? 解析されたテキストを出力テンプレートに一致させる作業を ANTLR が行う必要があるようです。私の仕事は、パーサーのルールとテンプレートが完全で正しいことを確認することです。]

ANTLR 3 では ANTLR 文法内でテンプレートを直接設定することができたと思いますが、ANTLR 4 ではそこから離れたようです。

上記の仮定に基づいて、ANTLR が生成する MyGrammarBaseListener クラスがすべての作業を行うように見えます。

この例を 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()ため、テンプレート マッチング アルゴリズムを実際に実装する場所がわかりません。enter両方を試して、exit何が最適かを確認します。

私の主な質問は、MyTemplates.stg のテンプレート名にアクセスするにはどうすればよいですか? 何をインポートする必要がありますか?

(おそらく、別の質問で、ルールの子をテンプレート パラメーターに一致させることについて質問するために戻ってきます...)

4

1 に答える 1

0

以下は、名前付き 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();
    }
}
于 2015-08-05T19:04:07.233 に答える