java - 如何动态(在运行时)生成词法分析器和解析器?

标签 java class antlr grammar on-the-fly

我确实找到了问题的答案:Barts answer这正是我需要的原因,但它不起作用(见下文)。

请有人给我一个可行的例子,或者告诉我我在实现 Barts answer 时出错的地方。 ?

这是我从其他答案中得到的结果,我从“第 4 部分”中得到了以下错误

Lexer lexer = (Lexer)Class.forName(grammarName + "Lexer").newInstance();

我有antlr3.4完整版和JDK库。我将其创建为 package createclass; 但我发现答案很奇怪,因为要创建的类没有包??? 所以我尝试添加到字符串中:

"@lexer::header {\n" +
"   package createclass;\n" +
"}        \n" +
"@parser::header {\n" +
"   package createclass;\n" +
"}\n" +

但仍然没有变化。

这是输出:

debug:
Exception in thread "main" java.lang.ClassNotFoundException: TLexer
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:169)
    at createclass.Createclass.main(Createclass.java:61)
Java Result: 1
BUILD SUCCESSFUL (total time: 31 seconds)

给出的示例代码是:

import java.io.*;
import javax.tools.*;
import java.lang.reflect.*;
import org.antlr.runtime.*;
import org.antlr.Tool;

public class Main {

    public static void main(String[] args) throws Exception {

        // The grammar which echos the parsed characters to theconsole,
        // skipping any white space chars.
        final String grammar =
                "grammar T;                                                  \n" +
                "                                                            \n" +
                "parse                                                       \n" +
                "  :  (ANY {System.out.println(\"ANY=\" + $ANY.text);})* EOF \n" +
                "  ;                                                         \n" +
                "                                                            \n" +
                "SPACE                                                       \n" +
                "  :  (' ' | '\\t' | '\\r' | '\\n') {skip();}                \n" +
                "  ;                                                         \n" +
                "                                                            \n" +
                "ANY                                                         \n" +
                "  :  .                                                      \n" +
                "  ;                                                           ";
        final String grammarName = "T";
        final String entryPoint = "parse";

        // 1 - Write the `.g` grammar file to disk.
        Writer out = new BufferedWriter(new FileWriter(new File(grammarName + ".g")));
        out.write(grammar);
        out.close();

        // 2 - Generate the lexer and parser.
        Tool tool = new Tool(new String[]{grammarName + ".g"});
        tool.process();

        // 3 - Compile the lexer and parser.
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        compiler.run(null, System.out, System.err, "-sourcepath", "", grammarName + "Lexer.java");
        compiler.run(null, System.out, System.err, "-sourcepath", "", grammarName + "Parser.java");

        // 4 - Parse the command line parameter using the dynamically created lexer and 
        //     parser with a bit of reflection Voodoo :)
        Lexer lexer = (Lexer)Class.forName(grammarName + "Lexer").newInstance();
        lexer.setCharStream(new ANTLRStringStream(args[0]));
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        Class<?> parserClass = Class.forName(grammarName + "Parser");
        Constructor parserCTor = parserClass.getConstructor(TokenStream.class);
        Parser parser = (Parser)parserCTor.newInstance(tokens);
        Method entryPointMethod = parserClass.getMethod(entryPoint);
        entryPointMethod.invoke(parser);
    }
}

最佳答案

我的猜测是您为此使用了 IDE,并且没有正确设置类路径。我的答案中的演示有效(也使用 v3.4)。这是我刚刚所做的:

我将文件 Main.java 复制到目录中(在我的例子中为 ~/Temp/demo),并在此目录中打开一个 shell 并执行以下操作:

bart@hades:~/Temp/demo$ java -version
> java version "1.6.0_24"
> OpenJDK Runtime Environment (IcedTea6 1.11.4) (6b24-1.11.4-1ubuntu0.12.04.1)
> OpenJDK 64-Bit Server VM (build 20.0-b12, mixed mode)

bart@hades:~/Temp/demo$ wget http://www.antlr.org/download/antlr-3.4-complete.jar
> --2012-10-17 19:26:01--  http://www.antlr.org/download/antlr-3.4-complete.jar
> Resolving www.antlr.org (www.antlr.org)... 138.202.170.10
> Connecting to www.antlr.org (www.antlr.org)|138.202.170.10|:80... connected.
> HTTP request sent, awaiting response... 200 OK
> Length: 2388361 (2.3M) [application/java-archive]
> Saving to: `antlr-3.4-complete.jar'
> 
> 100%[===============================================================================================================>] 2,388,361    317K/s   in 8.9s    
> 
> Last-modified header invalid -- time-stamp ignored.
> 2012-10-17 19:26:11 (261 KB/s) - `antlr-3.4-complete.jar' saved [2388361/2388361]

bart@hades:~/Temp/demo$ javac -cp antlr-3.4-complete.jar *.java

bart@hades:~/Temp/demo$ java -cp .:antlr-3.4-complete.jar Main "a b    c"
> ANY=a
> ANY=b
> ANY=c

(> 输出打印到控制台)

关于java - 如何动态(在运行时)生成词法分析器和解析器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12931301/

相关文章:

java - 如何在命令行参数中使用省略号?

java - 如何归档 Java 和 C++ 应用程序之间的分布式(数据库)事务?

Java 通过最终数组定义类成员

eclipse - 如何在eclipse IDE中查看Java的字节码?

python - 在antlr4 python目标中重用词法分析器对象

java - ANTLR toStringTree() 未被识别

java - 是否推荐使用 GAE 类型?

java - Apache Commons Net FTP 正在上传损坏的文件

c++ - 如何初始化未知的字符串类型?

parsing - ANTLR语法: parser- and lexer literals