user2085189
user2085189

Reputation: 101

How to translate the AST generated by ANTLR 4 to its source code

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

Answers (1)

Undisputed007
Undisputed007

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

Related Questions