Question

I am trying to construct a translator that could convert PL/SQL code to Java using Antlr 4 and StringTemplate 4. I have the grammar of PL/SQl and have already build a parser for PL/SQL but i have no idea how to approach the problem further. I found many articles of language translation using antlr and stringtemplate but they all use ANTLR 3 or ANTLR 2 . So is there any difference when using Antlr 4 to translate along with Stringtemplate as the parser for PL/SQL using Antlr 4 had some differences than Antlr3

I am completely new to Programming language translation and don't know if there is any better way to approach the problem.

Was it helpful?

Solution

ANTLR prior to v4 had intrinsic support for StringTemplate (you could specify that your grammar output is ST). As of v4, this support seems to be dropped.

One option is to use Listener or Visitor interfaces to manually construct your templates. Visitor is likely more useful in this context.

The other option I'm currently investigating is assigning ParseTree (result from parsing) as a parameter to the template. I use custom ModelAdapter for ParserRuleContext so I can access sub-contexts from the templates.

Example: I'm assuming you are using grammar for PL/SQL. Then you could have a template group like:

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>"

You would also need ModelAdapter for ParserRuleContext (this is just an example of the only method in it):

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

Now you can do the following:

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

Hope this helps!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top