Перевод кода 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, эта поддержка, похоже, отпадает.
Один из вариантов - использовать интерфейсы слушателя или посетителя для ручного построения шаблонов. Посетитель, вероятно, более полезен в этом контексте.
Другой вариант, который я сейчас исследую, - это назначение 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());Надеюсь, это поможет!
Comments