Доступ к именам правил шаблонов строк из базового прослушивателя ANTLR
Работаю над красивым принтером. Основываясь на моем понимании ANTLR и StringTemplate, если я хочу сопоставить все свои правила грамматики с шаблонами и применять шаблон каждый раз, когда вызывается правило грамматики, я могу создавать свои шаблоны с именами, соответствующими моим правилам грамматики.
[Дополнительный вопрос: это то, как я должен подходить к этому? Кажется, что ANTLR должен выполнять работу по сопоставлению анализируемого текста с выходными шаблонами. Моя работа заключается в том, чтобы убедиться, что правила синтаксического анализатора и шаблоны заполнены / правильны.]
Я думаю, что ANTLR 3 позволял непосредственно устанавливать шаблоны внутри грамматики ANTLR, но ANTLR 4, похоже, отошел от этого.
Исходя из вышеизложенных предположений, похоже, что класс MyGrammarBaseListener, который генерирует ANTLR, будет выполнять всю работу.
Я смог собрать имена правил, вызванных при разборе ввода текста, преобразовав этот пример в 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? Что я должен импортировать и т. Д.?
(Я, вероятно, вернусь, чтобы спросить о сопоставлении дочерних правил с параметрами шаблона в другом вопросе...)
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();
}
}