package pt.ist.fenixframework;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import pt.ist.fenixframework.dml.CodeGenerator;
import pt.ist.fenixframework.dml.CompilerArgs;
import pt.ist.fenixframework.dml.DmlCompilerException;
import pt.ist.fenixframework.dml.DmlLexer;
import pt.ist.fenixframework.dml.DmlParser;
import pt.ist.fenixframework.dml.DmlTreeParser;
import pt.ist.fenixframework.dml.DomainModel;
import antlr.ANTLRException;
import antlr.collections.AST;
public class DmlCompiler {
private static final Logger logger = LoggerFactory.getLogger(DmlCompiler.class);
/** Runs the DML compiler
*
* This is the main entry point for running the DML compiler, from the command line. This
* method will create the {@link CompilerArgs} from the command line parameters, and then invoke
* {@link DmlCompiler#compile}.
*
* @param args All the compiler's parameters
*
* @see CompilerArgs
*/
public static void main(String[] args) throws DmlCompilerException {
CompilerArgs compArgs = new CompilerArgs(args);
compile(compArgs);
}
/** Runs the DML compiler
*
* This is the main entry point for, programmatically, running the DML compiler. The compiler
* will first create the domain model, and then run the code generator.
*
* @param compArgs All the compiler's parameters
* @return The {@link DomainModel}
*
* @see CompilerArgs
*/
public static DomainModel compile(CompilerArgs compArgs) throws DmlCompilerException {
try {
DomainModel model = getDomainModel(compArgs);
CodeGenerator generator = compArgs.getCodeGenerator().
getConstructor(CompilerArgs.class,
DomainModel.class).newInstance(compArgs, model);
generator.generateCode();
return model;
} catch (Exception e) {
throw new DmlCompilerException(e);
}
}
public static DomainModel getDomainModel(CompilerArgs compArgs) throws DmlCompilerException {
// IMPORTANT: external specs must be first. The order is important for the DmlCompiler
List<URL> dmlSpecs = new ArrayList<URL>(compArgs.getExternalDomainSpecs());
dmlSpecs.addAll(compArgs.getLocalDomainSpecs());
return getDomainModel(dmlSpecs, false);
}
public static DomainModel getDomainModel(List<URL> dmlFilesURLs) throws DmlCompilerException {
return getDomainModel(dmlFilesURLs, false);
}
public static DomainModel getDomainModel(List<URL> dmlFilesURLs, boolean checkForMissingExternals)
throws DmlCompilerException {
if (logger.isTraceEnabled()) {
StringBuilder message = new StringBuilder();
for (URL url : dmlFilesURLs) {
message.append(url + " *** ");
}
logger.trace("dmlFilesUrls = " + message.toString());
}
DmlTreeParser walker = new DmlTreeParser();
DomainModel model = new DomainModel();
for (URL dmlFileURL : dmlFilesURLs) {
InputStream urlStream = null;
DataInputStream in = null;
try {
urlStream = dmlFileURL.openStream();
in = new DataInputStream(new BufferedInputStream(urlStream));
DmlLexer lexer = new DmlLexer(in);
DmlParser parser = new DmlParser(lexer);
parser.domainDefinitions();
AST t = parser.getAST();
// System.out.println(t.toStringTree());
// ASTFrame fr = new ASTFrame("Tree Viewer", t);
// fr.setVisible(true);
walker.domainDefinitions(t, model, dmlFileURL);
// System.out.println("Model = " + model);
} catch (ANTLRException e) {
throw new DmlCompilerException(e);
} catch (IOException ioe) {
System.err.println("Cannot read " + dmlFileURL + ". Ignoring it...");
// System.exit(3);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException ioe) {
}
}
if (urlStream != null) {
try {
urlStream.close();
} catch (IOException ioe) {
}
}
}
}
model.finalizeDomain(checkForMissingExternals);
return model;
}
}