【问题标题】:Translation of PL/SQL code to Java using Antlr 4 and stringtemplate 4使用 Antlr 4 和 stringtemplate 4 将 PL/SQL 代码翻译成 Java
【发布时间】:2013-12-12 10:35:12
【问题描述】:

我正在尝试构建一个可以使用 Antlr 4 和 StringTemplate 4 将 PL/SQL 代码转换为 Java 的翻译器。我有 PL/SQl 的语法并且已经为 PL/SQL 构建了一个解析器,但我不知道如何进一步解决问题。 我发现许多使用 antlr 和 stringtemplate 的语言翻译文章,但它们都使用 ANTLR 3 或 ANTLR 2 。那么使用 Antlr 4 与 Stringtemplate 一起翻译作为 PL/SQL 的解析器使用 Antlr 4 与 Antlr3 有一些差异时有什么区别

我对编程语言翻译完全陌生,不知道是否有更好的方法来解决这个问题。

【问题讨论】:

标签: antlr4 code-translation stringtemplate-4


【解决方案1】:

在 v4 之前的 ANTLR 具有对 StringTemplate 的内在支持(您可以指定您的语法输出为 ST)。从 v4 开始,这种支持似乎已被放弃。

一种选择是使用 Listener 或 Visitor 接口手动构建您的模板。在这种情况下,访问者可能更有用。

我目前正在研究的另一个选项是将 ParseTree(解析结果)作为参数分配给模板。我为 ParserRuleContext 使用自定义 ModelAdapter,因此我可以从模板访问子上下文。

示例: 我假设您正在使用 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>"

ParserRuleContext 还需要 ModelAdapter(这只是其中唯一方法的一个示例):

    @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());

希望这会有所帮助!

【讨论】:

  • 你能举一个使用监听器或访问者界面或与 ParseTree 一起使用的例子吗?
  • 谢谢!你太棒了!
  • 多么了不起的答案!投票不够。我已经停止为我的任务使用监听器,我已经切换到这个。我注意到侦听器方法最终还是 ST 的代理。你可以提供关于这种方法的任何其他提示 Marin 吗?再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-25
相关资源
最近更新 更多