在一台漂亮的打印机上工作。基于我到目前为止对ANTLR和StringTemplate的理解,如果我想将所有语法规则与模板匹配,并在每次调用语法规则时应用模板,我可以用与语法规则匹配的名称创建模板。
[附带问题:我应该这样做吗?看起来ANTLR应该完成将解析文本与输出模板匹配的工作。我的工作将是确保解析器规则和模板是完整/正确的[/strong>
我认为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中的模板名称?我需要导入什么,等等?
(我可能会回来问关于匹配规则子模板参数在一个不同的问题…)
下面演示了动态访问和呈现名为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();
}
}