All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.duelengine.duel.compiler.DuelCompiler Maven / Gradle / Ivy

There is a newer version: 0.9.7
Show newest version
package org.duelengine.duel.compiler;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.LineNumberReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

import org.duelengine.duel.ast.VIEWCommandNode;
import org.duelengine.duel.codegen.ClientCodeGen;
import org.duelengine.duel.codegen.CodeGenSettings;
import org.duelengine.duel.codegen.CodeGenerator;
import org.duelengine.duel.codegen.JavaCodeGen;
import org.duelengine.duel.parsing.DuelLexer;
import org.duelengine.duel.parsing.DuelParser;
import org.duelengine.duel.parsing.SyntaxException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DuelCompiler {

	private final Logger log = LoggerFactory.getLogger(DuelCompiler.class);
	private boolean verbose;
	private File inputDir;
	private File outputClientDir;
	private File outputServerDir;
	private String clientPrefix;
	private String serverPrefix;

	public String getInputDir() {
		return inputDir.getAbsolutePath();
	}

	public void setInputDir(String value) {
		inputDir = (value != null) ? new File(value.replace('\\', '/')) : null;
	}

	public String getOutputClientDir() {
		return outputClientDir.getAbsolutePath();
	}

	public void setOutputClientDir(String value) {
		outputClientDir = (value != null) ? new File(value.replace('\\', '/')) : null;
	}

	public String getOutputServerDir() {
		return outputServerDir.getAbsolutePath();
	}

	public void setOutputServerDir(String value) {
		outputServerDir = (value != null) ? new File(value.replace('\\', '/')) : null;
	}

	public String getClientPrefix() {
		return clientPrefix;
	}

	public void setClientPrefix(String value) {
		clientPrefix = value;
	}

	public String getServerPrefix() {
		return serverPrefix;
	}

	public void setServerPrefix(String value) {
		serverPrefix = value;
	}

	private boolean ensureSettings() {
		if (inputDir == null || !inputDir.exists()) {
			throw new IllegalArgumentException("ERROR: input directory is empty: "+inputDir);
		}

		if (outputClientDir == null) {
			outputClientDir = inputDir.isDirectory() ? inputDir :  inputDir.getParentFile();
		}

		if (outputServerDir == null) {
			outputServerDir = inputDir.isDirectory() ? inputDir :  inputDir.getParentFile();
		}

		return true;
	}

	/**
	 * Compiles view files
	 * @throws IOException 
	 */
	public void execute() throws IOException {
		if (!ensureSettings()) {
			return;
		}

		List inputFiles = findFiles(inputDir);
		if (inputFiles.size() < 1) {
			throw new IllegalArgumentException("ERROR: no input files found: "+inputDir);
		}

		for (File inputFile : inputFiles) {
			List views;
			try {
				FileReader reader = new FileReader(inputFile);
				views = new DuelParser().parse(new DuelLexer(reader));

				if (views == null || views.size() < 1) {
					throw new SyntaxException("Syntax error: no view found in "+inputFile, 0, 0, 0);
				}

			} catch (SyntaxException ex) {
				reportSyntaxError(inputFile, ex);
				continue;
			}

			// TODO: allow setting of more properties from args
			CodeGenSettings settings = new CodeGenSettings();
			settings.setIndent("\t");
			settings.setNewline(System.getProperty("line.separator"));
			settings.setClientNamePrefix(clientPrefix);
			settings.setServerNamePrefix(serverPrefix);

			// compact client-side
			settings.setConvertLineEndings(false);
			settings.setNormalizeWhitespace(true);

			String outputName = null;
			for (VIEWCommandNode view : views) {
				if (view.isServerOnly()) {
					// skip server-only views
					continue;
				}

				// use the first view
				outputName = settings.getClientPath(view.getName());
				if (outputName == null || outputName.isEmpty()) {
					outputName = inputFile.getName().substring(0, inputFile.getName().lastIndexOf('.'));
				}
				break;
			}

			CodeGenerator codegen = new ClientCodeGen(settings);

			// ensure has client-views before generating file
			if (outputName != null) {
				try {
					File outputFile = new File(outputClientDir, outputName+codegen.getFileExtension());
					outputFile.getParentFile().mkdirs();

					FileWriter writer = new FileWriter(outputFile, false);
					try {
						codegen.write(writer, views);
					} finally {
						writer.flush();
						writer.close();
					}

				} catch (SyntaxException ex) {
					reportSyntaxError(inputFile, ex);
				}
			}

			// directly emit server-side
			settings.setConvertLineEndings(true);
			settings.setNormalizeWhitespace(false);

			codegen = new JavaCodeGen(settings);
			for (VIEWCommandNode view : views) {
				if (view.isClientOnly()) {
					// skip client-only views
					continue;
				}

				try {
					File outputFile = new File(outputServerDir, settings.getServerPath(view.getName(), codegen));
					outputFile.getParentFile().mkdirs();

					FileWriter writer = new FileWriter(outputFile, false);
					try {
						codegen.write(writer, view);
					} finally {
						writer.flush();
						writer.close();
					}

				} catch (SyntaxException ex) {
					reportSyntaxError(inputFile, ex);
				}
			}
		}
	}

	private void reportSyntaxError(File inputFile, SyntaxException ex) {
		try {
			String message = ex.getMessage();
			if (message == null) {
				if (ex.getCause() != null) {
					message = ex.getCause().getMessage();
				} else {
					message = "Error";
				}
			}

			log.error(String.format(
				"%s:%d: %s",
				inputFile.getAbsolutePath(),
				ex.getLine(),
				message));

			int col = ex.getColumn(),
				line=ex.getLine();

			String text = "";
			LineNumberReader reader = new LineNumberReader(new FileReader(inputFile));
			try {
				for (int i=-1; i 0) {
				log.error(String.format("%"+col+"s", "^"));
			} else {
				log.error("^");
			}

			if (verbose) {
				ex.printStackTrace();
			}

		} catch (Exception ex2) {
			ex.printStackTrace();

			if (verbose) {
				ex2.printStackTrace();
			}
		}
	}

	private static List findFiles(File inputDir) {

		List files = new ArrayList();
		Queue dirs = new LinkedList();
		dirs.add(inputDir);

		while (!dirs.isEmpty()) {
			File file = dirs.poll();
			if (file.isDirectory()) {
				dirs.addAll(Arrays.asList(file.listFiles()));
			} else if (file.getName().toLowerCase().endsWith(".duel")) {
				files.add(file);
			}
		}

		return files;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy