我正在尝试从这里编译ISO-SQL 2003语法 http://www.antlr3.org/grammar/1304304798093/SQL2003_Grammar.zip。它的所有三个版本都可以在http://www.antlr3.org/grammar/list.html找到。
这是我遵循的步骤,
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设置这个语法会很有帮助。
编辑:经过一些小小的调整,我认为这些错误是由词法分析器和解析器规则中的操作引起的。有没有一种安全的方法可以解决这个问题?
答案 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个问题:
sql2003Parser
规则开头。不幸的是,如果你通过这个启动规则调用解析器,它将无法正确解析即使是最简单的select a from b
。所以我通过query_specification
规则调用解析器来仅解析SELECT
子句。query_specification
无法解析一些随机复杂的SQL。