2

我正在编写一个简单的解析器来将查询转换为 SQL。我已经完成了解析器并获得了 AST,但现在我需要使用 ANTLR 4 将这些语法翻译成 SQL。有人知道如何"SELECT" as "SELECT", "FROM" to "FROM"在 ANTLR 4 中打印或翻译查询等吗?

我遵循了权威的 ANTLR 4 参考书。我们必须创建 2 个 java 文件。

在第一个 java 文件中,我想遵循这些步骤,但不是

public void enterInit(ArrayInitParser.InitContext ctx)
{
    System.out.print('"');
} 

我已更改为

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

在第二个 java 文件中,我按照以下步骤操作:

翻译.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
}
}

尝试使用字符串模板

我在 antlr 4 中尝试过使用 StringTemplate。我可以翻译查询select, from, where,但是当我翻译查询时and我不能。我的代码如下所示:

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

我的语法的一部分:

布尔运算:或|异或|与;

谢谢你。

4

1 回答 1

1

我不知道代码生成在 v4 中是如何工作的,但根据我的经验,我认为你可以通过在语法中的规则吐出生成的输出来进行语法定向翻译来实现这一点。

  boolOp returns[String output] : OR {$output=$OR.text}
                                 | XOR {$output=$XOR.text}
                                 | AND{$output=$AND.text}
                                 ;

然后在您的 select 语句中,您也可以执行相同的操作来返回字符串“select”“where”等。您可以通过将 walker 的对象传递给 sysout 来遍历树并打印输出。

您只需处理格式(换行符、制表符等)即可获得漂亮的打印输出。

于 2013-09-01T08:47:18.340 回答