【问题标题】:Compiling ISO SQL-2003 ANTLR Grammar编译 ISO SQL-2003 ANTLR 语法
【发布时间】:2015-12-10 13:03:56
【问题描述】:

我正在尝试从这里编译 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

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 设置此语法,将会很有帮助。

编辑:经过一番折腾,我认为这些错误是由词法分析器和解析器规则中存在的操作引起的。有没有安全的方法来克服这个问题?

【问题讨论】:

    标签: java sql parsing antlr


    【解决方案1】:

    您没有做错任何事,ANTLR 从未能够从这些语法文件中生成有效的 Java 解析器。

    根据 Douglas Godfrey 发给 antlr-interest in Oct 2011 的帖子:

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

    ...

    我不相信有可能得到一个可以工作的解析器 爪哇。另一方面,C 语言解析器是很有可能的。

    【讨论】:

    • 我不确定这是否完全正确。同一个人 'Douglas Godfrey' 之前在同一个线程上发布过,他设法用 8GB 的​​堆空间编译它 [antlr3.org/pipermail/antlr-interest/2011-October/042850.html]。 SQL2003 也列在 antlr2 [antlr2.org/] 和 3 的官方页面上,我认为(感谢同一个人)。感谢您调查这个问题:)
    • 我认为排除整个语法与 ANTLR 不兼容不是正确的方法:)
    • @noob333 如果你不相信戈弗雷先生的话,他曾经以构建 SQL 语法分析器为生,那么我不知道还有谁能说服你。另一方面,很多伟大的东西都是由那些不知道这是不可能的人创造的,所以祝你好运。
    【解决方案2】:

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

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

    但还是有2个问题:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-31
      • 1970-01-01
      相关资源
      最近更新 更多