在ANTLR 3中,如何在运行时而不是提前生成词法分析器(和解析器)?

我想在运行时生成一个antlr词法分析器 – 也就是说,生成语法并从语法生成lexer类,并在运行时生成它的支持位。 我很乐意将它提供给java编译器,它可以在运行时访问。

这是一个快速而肮脏的方式:

  1. 生成一个组合的 (!)ANTLR语法.g文件,给定一个String作为语法源,
  2. 并从此.g文件创建一个Parser&Lexer,
  3. 编译这些Parser&Lexer .java文件,
  4. 创建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 "abc" 

或在Windows上

 java -cp .;antlr-3.2.jar Main "abc" 

,产生以下输出:

 ANY =一
 ANY = B
 ANY = C

您必须使用org.antlr.Tool()类才能使其正常工作。

您可以在github上查看ANTLRWorks源代码以了解如何使用它,特别是这里的generate()方法:

 ErrorListener el = ErrorListener.getThreadInstance(); ErrorManager.setErrorListener(el); String[] params; if(debug) params = new String[] { "-debug", "-o", getOutputPath(), "-lib", window.getFileFolder(), window.getFilePath() }; else params = new String[] { "-o", getOutputPath(), "-lib", window.getFileFolder(), window.getFilePath() }; new File(getOutputPath()).mkdirs(); Tool antlr = new Tool(Utils.concat(params, AWPrefs.getANTLR3Options())); antlr.process(); boolean success = !el.hasErrors(); if(success) { dateOfModificationOnDisk = window.getDocument().getDateOfModificationOnDisk(); } lastError = el.getFirstErrorMessage(); el.clear(); ErrorManager.removeErrorListener(); return success; 

您是否尝试使用适当的String []参数调用org.antlr.Tool.main(String[])

如果这太麻烦,您可以对Tool类( 源代码 )进行反向工程,以弄清楚它是如何工作的,以及如何执行您需要执行的特定任务。