Reputation: 101
I am writing a simple parser to translate the query to SQL.
I've completed the parser and got the AST, but now I need to translate those grammar to SQL using ANTLR 4.
Does anybody knows how to print or translate the query "SELECT" as "SELECT", "FROM" to "FROM"
, etc in ANTLR 4?
I have followed the definitive ANTLR 4 reference book. In that we have to create 2 java files.
In the 1st java file I thought to follow these steps but instead of
public void enterInit(ArrayInitParser.InitContext ctx)
{
System.out.print('"');
}
I have changed to
public void enterSelect(ArrayInitParser.SelectContext ctx)
{
System.out.print('SELECT');
}
ShortToUnicodeString.java
public class ShortToUnicodeString extends ArrayInitBaseListener
{
/** Translate { to " */
@Override
public void enterInit(ArrayInitParser.InitContext ctx)
{
System.out.print('"');
}
/** Translate } to " */
@Override
public void exitInit(ArrayInitParser.InitContext ctx)
{
System.out.print('"');
}
/** Translate integers to 4-digit hexadecimal strings prefixed with \\u */
@Override
public void enterValue(ArrayInitParser.ValueContext ctx)
{
// Assumes no nested array initializers
int value = Integer.valueOf(ctx.INT().getText());
System.out.printf("\\u%04x", value);
}
}
In the 2nd java file I followed these steps:
Translate.java
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;
public class Translate
{
public static void main(String[] args) throws Exception
{
// create a CharStream that reads from standard input
ANTLRInputStream input = new ANTLRInputStream(System.in);
// create a lexer that feeds off of input CharStream
ArrayInitLexer lexer = new ArrayInitLexer(input);
// create a buffer of tokens pulled from the lexer
CommonTokenStream tokens = new CommonTokenStream(lexer);
// create a parser that feeds off the tokens buffer
ArrayInitParser parser = new ArrayInitParser(tokens);
ParseTree tree = parser.init(); // begin parsing at init rule
// Create a generic parse tree walker that can trigger callbacks
ParseTreeWalker walker = new ParseTreeWalker();
// Walk the tree created during the parse, trigger callbacks
walker.walk(new ShortToUnicodeString(), tree);
System.out.println(); // print a \n after translation
}
}
TRIED WITH STRINGTEMPLATE
I have tried with StringTemplate in antlr 4. I can able to translate the query select, from, where
but when I translate the query and
I couldn't. My code looks like:
import org.stringtemplate.v4.*;
public class ToSql extends BaseListener
{
/** Translate select to select */
@Override
public void enterSelect( Parser.SelectContext ctx)
{
ST select = new ST("select");
System.out.print(select.render()+"\t");
}
/** Translate from to from */
@Override
public void enterFrom( Parser.FromContext ctx)
{
ST from = new ST("from");
System.out.print(from.render()+"\t");
}
/** Translate where to where */
@Override
public void enterWhere( Parser.WhereContext ctx)
{
ST where = new ST("where");
System.out.print(where.render()+"\t");
}
/** Translate boolOp to AND|OR|XOR */
@Override
public void enterBoolOp( Parser.BoolOpContext ctx)
{
ST boolOp = new ST("<and>");
if (boolOp == and)
{
boolOp.add("and", "AND");
System.out.print(boolOp.render()+"\t");
}
}
}
PART OF MY GRAMMAR:
boolOp : OR|XOR|AND;
Thank you.
Upvotes: 2
Views: 3488
Reputation: 649
I don't know how code generation works in v4, but in my little experience, i think you could accomplish this by doing syntax directed translation by making your rules in your grammar spit out the generated output.
boolOp returns[String output] : OR {$output=$OR.text}
| XOR {$output=$XOR.text}
| AND{$output=$AND.text}
;
Then in your select statement, you could also do same to return string "select" "where" etc. You could walk the tree and print out the output by passing the object of the walker to sysout.
You just have to work on your formatting(newline,tab etc) to have a good pretty print output.
Upvotes: 1