在ANTLR 3中,如何在运行时而不是提前生成词法分析器(和解析器)? [英] In ANTLR 3, how do I generate a lexer (and parser) at runtime instead of ahead of time?
本文介绍了在ANTLR 3中,如何在运行时而不是提前生成词法分析器(和解析器)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我想在运行时生成一个antlr词法分析器 - 也就是说,生成语法并从语法生成lexer类及其在运行时的支持位。我很乐意将它提供给java编译器,它可以在运行时访问。
I want to generate an antlr lexer at runtime -- that is, generate the grammar and from the grammar generate the lexer class, and its supporting bits at runtime. I am happy to feed it into the the java compiler, which is accessible at runtime.
推荐答案
这是一个快速而又肮脏的方式:
Here's a quick and dirty way to:
- 生成一个组合的(!)ANTLR语法
.g
文件,给定一个String作为语法源, - 并创建一个Parser& Lexer来自这个
.g
文件, - 编译这些Parser& Lexer
.java
files, - 创建Parser&的实例。 Lexer类并调用解析器的入口点。
- generate a combined (!) ANTLR grammar
.g
file given a String as grammar-source, - and create a Parser & Lexer from this
.g
file, - compile the these Parser & Lexer
.java
files, - create instances of the Parser & Lexer classes and invoke the entry point of the parser.
Main.java
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):
Which, after compiling and running it like this (on *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
这篇关于在ANTLR 3中,如何在运行时而不是提前生成词法分析器(和解析器)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文