使用Antlr 4和stringtemplate 4将PL/SQL代码转换为Java

ayu*_*ula 6 code-translation stringtemplate-4 antlr4

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

我是编程语言翻译的新手,不知道是否有更好的方法来解决问题.

Mar*_*cci 10

v4之前的ANTLR对StringTemplate有内在的支持(你可以指定你的语法输出是ST).截至第4节,这种支持似乎被取消了.

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

我正在研究的另一个选项是将ParseTree(解析结果)作为参数分配给模板.我使用自定义ModelAdapter for 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>"
Run Code Online (Sandbox Code Playgroud)

你还需要ModelAdapter for 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);
}
Run Code Online (Sandbox Code Playgroud)

现在您可以执行以下操作:

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());
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!