ST 4 vs 3

28 views
Skip to first unread message

anthon...@gmail.com

unread,
Sep 20, 2017, 2:46:38 PM9/20/17
to stringtemplate-discussion
So this might be a dumb question... but I honestly don't know...

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

Reply all
Reply to author
Forward
0 new messages