编译ISO SQL-2003 ANTLR语法

时间:2015-12-10 13:03:57

标签: java sql parsing antlr

我正在尝试从这里编译ISO-SQL 2003语法 http://www.antlr3.org/grammar/1304304798093/SQL2003_Grammar.zip。它的所有三个版本都可以在http://www.antlr3.org/grammar/list.html找到。

这是我遵循的步骤,

  1. java -jar antlr-3.3-complete.jar -Xmx8G -Xwatchconversion sql2003Lexer.g
  2. java -jar antlr-3.3-complete.jar -Xmx8G -Xwatchconversion sql2003Parser.g
  3. javac ANTLRDemo.java
  4. ANTLRDemo.java文件:

    import org.antlr.runtime.*;
    import java.io.IOException;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    public class ANTLRDemo {
       static String readFile(String path) throws IOException 
       {
           byte[] encoded = Files.readAllBytes(Paths.get(path));
           return new String(encoded, "UTF-8");
       }
    
       public static void main(String[] args) throws Exception {
           ANTLRStringStream in = new ANTLRStringStream( readFile(args[0]) );
           sql2003Lexer lexer = new sql2003Lexer(in);
           CommonTokenStream tokens = new CommonTokenStream(lexer);
           sql2003Parser parser = new sql2003Parser(tokens);
           parser.eval();
       }
    }
    

    前两个步骤工作正常,然后在编译我的主类时,我得到了很多与Java语法相关的错误,如下所示:

      

    ./ sql2003Parser.java:96985:错误:不是声明                 $ UnsignedInteger.text =='1'   ./sql2003Parser.java:96985:错误:';'预期                 $ UnsignedInteger.text =='1'   ./sql2003Parser.java:102659:错误:未关闭的字符文字               if(!(((Unsigned_Integer3887!= null?Unsigned_Integer3887.getText():null)=='01'))){

    如果我在设置解析器时出错了,请告诉我。
    如果有人能告诉我如何使用ANTLR设置这个语法会很有帮助。

    编辑:经过一些小小的调整,我认为这些错误是由词法分析器和解析器规则中的操作引起的。有没有一种安全的方法可以解决这个问题?

2 个答案:

答案 0 :(得分:1)

你没有做错任何事,ANTLR从来没有能够从这些语法文件中生成一个可用的Java解析器。

根据道格拉斯·戈弗雷的一篇文章antlr-interest in Oct 2011

  

我生成了一个C解析器和词法分析器。他们都生成并编译   顺利   在我的机器上,8GB堆分配给Antlr。

     

...

     

我不相信有可能获得一个有效的解析器   Java的。另一方面,C语言解析器很有可能。

答案 1 :(得分:1)

是的,基本上你是对的。语法被打破了。但是ANTLRDemo.java中也存在错误,因为eval()类中没有Parser方法。您应该使用解析器语法的任何规则的名称调用方法,例如query_specification()。在语法本身中有一些错误看起来是一个错字,一些未定义的Java error()方法调用,解析器中的skip()调用仅适用于词法分析器。您会在this commit中看到所有修复内容。我在this GitHub repository发表了我的研究成果。

我开始修复语法的明显错误,这导致生成的java代码中的编译错误。我发布了与您发布的错误相同的错误。最终我修复了所有Java语法错误,但遇到了另一个无法直接修复的问题,因为它源于JVM的限制,compilation error: code too large。阅读ANTLR邮件列表有一个提示,将大型类的一些静态成员提取到单独的接口中,并“实现”它们以具有一种多重继承。通过反复试验,我最终得到了sql2003Parser.java中解析器“imlemented”的6个接口。

但仍有2个问题:

  • 错误的开始规则。 Douglas Godfrey编写的语法以sql2003Parser规则开头。不幸的是,如果你通过这个启动规则调用解析器,它将无法正确解析即使是最简单的select a from b。所以我通过query_specification规则调用解析器来仅解析SELECT子句。
  • 语法中的其他一些错误。我没有深入研究语法,但query_specification无法解析一些随机复杂的SQL。