I'm writing an application to convert one language to another (if anyone cares, PL/SQL to C#).
So I have a grammar for PL/SQL... works beautifully and creates my AST.
I'm now using the example for the Antl4 Reference book:
ANTLRInputStream input = new ANTLRInputStream(is);
plsqlLexer lexer = new plsqlLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
plsqlParser parser = new plsqlParser(tokens);
parser.setBuildParseTree(true);
ParseTree tree = parser.unit_statement();
// show tree in text form
System.out.println(tree.toStringTree(parser));
ParseTreeWalker walker = new ParseTreeWalker();
ConverterEmitter converter = new ConverterEmitter();
walker.walk(converter, tree);
And my emitter class has stuff like:
@Override
public void exitCreate_procedure_body(plsqlParser.Create_procedure_bodyContext ctx) {
ST tag = templates.getInstanceOf("proc");
tag.add("name", ctx.getChild(1).getText());
ptp.put(ctx, tag);
}
This is all fine and good...
Problem I'm encountering is:
In Antlr3, we had the grammar, and the tree grammar. In the tree grammar, we would specify stuff like:
methodDeclaration
: ^(METHOD_DECL type ID a+=parameter* block)
-> method(name={$ID.text}, retType={$type.st}, args={$a}, block={$block.st})
;
so the $a that got passed to the template "args" variables, was a multivalue variable with all the arguments to the procedure/method/whatever.
So the template would be something like this:
// START: proc
proc(name, args, stats) ::= <<
public static void <name>(<args; separator=", ">)
{
<stats>
}
>>
// END: proc
where all the args would be rendered properly... so would <stats> for that matter...
How do we do this in ST 4?
Only way I've managed, which seems very kludgy is below. In the example below, as I'm "exiting" Package_body, I search its children for create_procedure_body and create_function_body elements and add them to the package_body "members" variable.
@Override
public void exitPackage_body(plsqlParser.Package_bodyContext ctx) {
ST tag = templates.getInstanceOf("class");
tag.add("name", ctx.getChild(1).getText());
for (int i = 0; i < ctx.children.size(); i++) {
Object pp = ctx.getChild(i);
if (pp.getClass().toString().equals("class com.pplweb.plsql2cs.plsqlParser$Package_obj_bodyContext")) {
if (((plsqlParser.Package_obj_bodyContext)pp).children.size() > 0) {
Object pt = ((plsqlParser.Package_obj_bodyContext)pp).getChild(0);
if (pt.getClass().toString().equals("class plsqlParser$Create_procedure_bodyContext")) {
tag.add("members", ptp.get((plsqlParser.Create_procedure_bodyContext)pt));
}
if (pt.getClass().toString().equals("class plsqlParser$Create_function_bodyContext")) {
tag.add("members", ptp.get((cplsqlParser.Create_function_bodyContext)pt));
}
}
}
}
ptp.put(ctx, tag);
}
Any help would be appreciated...
Tony