我想在运行时生成一个antlr词法分析器-也就是说,生成语法,并从语法中生成lexer类及其在运行时的支持位。我很高兴将其输入Java编译器中,该编译器可在运行时访问。

最佳答案

这是一种快速而肮脏的方法:

  • 给定一个字符串作为语法源
  • ,生成一个组合的(!)ANTLR语法.g文件
  • ,然后从此.g文件
  • 创建解析器和词法分析器
  • 编译这些解析器和词法分析器.java文件
  • 创建Parser&Lexer类的实例,并调用解析器的入口点。

  • Main.java
    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);
        }
    }
    

    在这样编译并运行它之后(在* nix上):
    java -cp .:antlr-3.2.jar Main "a b    c"
    

    或在Windows上
    java -cp .;antlr-3.2.jar Main "a b    c"
    

    ,产生以下输出:

    ANY = a
    ANY = b
    ANY = c

    07-24 09:36
    查看更多