package org.deved.antlride.internal.core.antlr;
import java.io.CharArrayReader;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.LinkedHashSet;
import java.util.Set;
import org.antlr.Tool;
import org.antlr.analysis.DFAOptimizer;
import org.antlr.tool.ANTLRErrorListener;
import org.antlr.tool.CompositeGrammar;
import org.antlr.tool.ErrorManager;
import org.antlr.tool.Grammar;
import org.antlr.tool.GrammarNonDeterminismMessage;
import org.antlr.tool.Message;
import org.antlr.tool.ToolMessage;
import org.deved.antlride.core.AntlrCore;
import org.deved.antlride.core.build.AntlrBuildUnitRepository;
import org.deved.antlride.core.model.IGrammar;
import org.deved.antlride.core.util.AntlrCoreHelper;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import antlr.RecognitionException;
public class ANTLRGrammarProvider {
private static final ANTLRErrorListener DO_NOT_REPORT_ERRORS = new ANTLRErrorListener() {
public void warning(Message msg) {
}
public void info(String msg) {
}
public void error(ToolMessage msg) {
}
public void error(Message msg) {
}
};
private class NonDeterminismListener implements ANTLRErrorListener {
public void error(Message msg) {
if (msg instanceof GrammarNonDeterminismMessage) {
GrammarNonDeterminismMessage gndm = (GrammarNonDeterminismMessage) msg;
nonDeterminismList.add(gndm);
}
}
public void error(ToolMessage msg) {
error((Message) msg);
}
public void info(String msg) {
}
public void warning(Message msg) {
error((Message) msg);
}
}
private Grammar g;
private Grammar lg;
private Set<GrammarNonDeterminismMessage> nonDeterminismList = new LinkedHashSet<GrammarNonDeterminismMessage>();
public IStatus build(IProgressMonitor monitor, IGrammar grammar) {
IStatus status = null;
try {
configureErrorManager(new NonDeterminismListener());
this.g = doCreateGrammar(grammar);
doProcessGrammar(monitor, g, grammar.getSource());
String lexerContent = null;
if (grammar.isCombinedGrammar()) {
lexerContent = g.getLexerGrammar();
} else if (grammar.isParserGrammar()) {
IPath libraryPath = AntlrBuildUnitRepository.create(grammar)
.getAbsoluteLibraryPath();
libraryPath = libraryPath.append(
grammar.getOption("tokenVocab")).addFileExtension("g");
File lexerFile = libraryPath.toFile();
if (lexerFile.exists()) {
lexerContent = AntlrCoreHelper.loadFileAsString(lexerFile);
}
}
if (lexerContent != null) {
this.lg = doCreateLexerGrammar(monitor, g);
doProcessGrammar(monitor, lg, lexerContent);
}
// Nondeterminism nondeterminism = new Nondeterminism();
// for (GrammarNonDeterminismMessage message : nonDeterminismList) {
// System.out.println(nondeterminism.findAltPaths(message));
// }
status = Status.OK_STATUS;
} catch (Exception ex) {
status = new Status(IStatus.ERROR, AntlrCore.PLUGIN_ID,
"Could not create gramnar", ex);
AntlrCore.error(new CoreException(status));
}
return status;
}
public Grammar getGrammar() {
return g;
}
public Grammar getLexerGrammar() {
return lg;
}
private Grammar doCreateGrammar(IGrammar grammar) {
CompositeGrammar composite = new CompositeGrammar();
String grammarFileName = grammar.getAbsoluteFile().toOSString();
// the tool object is used for composite grammars and for parser/tree
// grammars
String lib = null;
if (grammar.isParserGrammar()) {
lib = AntlrBuildUnitRepository.create(grammar)
.getAbsoluteLibraryPath().toOSString();
} else {
lib = grammar.getAbsoluteFolder().toOSString();
}
Tool tool = new Tool(new String[] { "-lib", lib,
grammar.getAbsoluteFile().toOSString() });
Grammar g = new Grammar(tool, grammarFileName, composite);
composite.setDelegationRoot(g);
return g;
}
private Grammar doCreateLexerGrammar(IProgressMonitor monitor, Grammar g)
throws RecognitionException {
Grammar lexerGrammar = new Grammar();
lexerGrammar.tool = g.tool;
lexerGrammar.implicitLexer = true;
lexerGrammar.setFileName(g.name + "__.g");
lexerGrammar.importTokenVocabulary(g);
return lexerGrammar;
}
private void doProcessGrammar(IProgressMonitor monitor, Grammar g,
char[] content) throws RecognitionException {
doProcessGrammar(monitor, g, new CharArrayReader(content));
}
private void doProcessGrammar(IProgressMonitor monitor, Grammar g,
String content) throws RecognitionException {
doProcessGrammar(monitor, g, new StringReader(content));
}
private void doProcessGrammar(IProgressMonitor monitor, Grammar g,
Reader reader) throws RecognitionException {
try {
monitor.subTask("Parsing and building AST");
g.parseAndBuildAST(reader);
monitor.worked(1);
monitor.subTask("Assiging token types");
g.composite.assignTokenTypes();
monitor.worked(1);
monitor.subTask("Defining symbols");
g.composite.defineGrammarSymbols();
monitor.worked(1);
monitor.subTask("Creating NFAs");
g.composite.createNFAs();
monitor.worked(1);
// Build NFAs from the grammar AST
monitor.subTask("Building NFAs");
g.buildNFA();
monitor.worked(1);
// Create the DFA predictors for each decision
g.createLookaheadDFAs();
monitor.worked(1);
// OPTIMIZE DFA
monitor.subTask("Building DFAs");
DFAOptimizer optimizer = new DFAOptimizer(g);
optimizer.optimize();
monitor.worked(1);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void configureErrorManager() {
configureErrorManager(DO_NOT_REPORT_ERRORS);
}
public static void configureErrorManager(ANTLRErrorListener errorListener) {
try {
ErrorManager.resetErrorState();
ErrorManager.setErrorListener(errorListener);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}