Перевод кода PL/SQL в Java с использованием Antlr 4 и stringtemplate 4
Я пытаюсь создать переводчик, который может конвертировать PL/SQL-код в Java с использованием Antlr 4 и StringTemplate 4. У меня есть грамматика PL/SQl и я уже создал парсер для PL/SQL, но я не знаю, как подойти к проблема дальше. Я нашел много статей о переводе языка с использованием antlr и stringtemplate, но все они используют ANTLR 3 или ANTLR 2 . Так есть ли какая-то разница при использовании Antlr 4 для перевода вместе со Stringtemplate, так как синтаксический анализатор для PL/SQL с использованием Antlr 4 имел некоторые отличия от Antlr3?
Я совершенно новичок в переводе с языка программирования и не знаю, есть ли лучший способ решить проблему.
1 ответ
ANTLR до v4 имел встроенную поддержку StringTemplate (вы можете указать, что ваш вывод грамматики - ST). Начиная с версии v4 эта поддержка, похоже, прекращена.
Одним из вариантов является использование интерфейсов Listener или Visitor для создания шаблонов вручную. Посетитель, вероятно, более полезен в этом контексте.
Другой вариант, который я сейчас изучаю, - это присвоение ParseTree (результат анализа) в качестве параметра для шаблона. Я использую пользовательский ModelAdapter для ParserRuleContext, чтобы получить доступ к подконтекстам из шаблонов.
Пример: я предполагаю, что вы используете грамматику для PL/SQL. Тогда вы можете создать группу шаблонов, например:
plsql_block(block) ::= <<{ <declarations(block.declare_section)> <body(block.body)> }>> declarations(ds) ::= "<ds.item_declaration:itemDecl()>" itemDecl(id) ::= "<id.variable_declaration:varDecl()>" varDecl(vd) ::= "<vd.datatype.text> <vd.ID>;" body(b) ::= "<b.text>"
Вам также понадобится ModelAdapter для ParserRuleContext (это всего лишь пример единственного метода в нем):
@Override
public Object getProperty(Interpreter interpreter, ST seld, Object o, Object property, String propertyName) throws STNoSuchPropertyException
{
Method m = null;
try {
String mn = "get" + Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1);
m = o.getClass().getMethod(mn);
} catch (Exception e) {
}
if (m == null)
try {
m = o.getClass().getDeclaredMethod(propertyName);
} catch (Exception e) {
}
if (m != null) try {
return m.invoke(o);
} catch (Exception e) {
throw new STNoSuchPropertyException(e, property, propertyName);
}
else
throw new STNoSuchPropertyException(null, property, propertyName);
}
Теперь вы можете сделать следующее:
ANTLRInputStream input = new ANTLRInputStream(new FileInputStream("block_test.sql"));
PLSQLLexer lexer = new PLSQLLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
PLSQLParser parser = new PLSQLParser(tokens);
parser.setBuildParseTree(true);
ParseTree tree = parser.plsql_block();
STGroupFile stg = new STGroupFile("test.stg");
stg.registerModelAdaptor(ParserRuleContext.class, new ContextModelAdapter());
ST t = stg.getInstanceOf("plsql_block");
t.add("block", tree);
System.out.println(t.render());
Надеюсь это поможет!