[英]In ANTLR 3, how do I generate a lexer (and parser) at runtime instead of ahead of time?
我想在運行時生成一個antlr詞法分析器 - 也就是說,生成語法並從語法生成lexer類,並在運行時生成它的支持位。 我很樂意將它提供給java編譯器,它可以在運行時訪問。
這是一個快速而骯臟的方式:
.g
文件,給定一個String作為語法源, .g
文件創建一個Parser&Lexer, .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
您必須使用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
類( 源代碼 )進行反向工程,以弄清楚它是如何工作的,以及如何執行您需要執行的特定任務。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.