Prechádzať zdrojové kódy

new program size calculation

Wilfried Klaas 6 rokov pred
rodič
commit
eda89b0467
2 zmenil súbory, kde vykonal 539 pridanie a 515 odobranie
  1. 2 1
      .classpath
  2. 537 514
      src/main/java/de/mcs/tools/sps/SPSAssembler.java

+ 2 - 1
.classpath

@@ -24,8 +24,9 @@
 			<attribute name="maven.pomderived" value="true"/>
 		</attributes>
 	</classpathentry>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jdk-11.0.1">
 		<attributes>
+			<attribute name="module" value="true"/>
 			<attribute name="maven.pomderived" value="true"/>
 		</attributes>
 	</classpathentry>

+ 537 - 514
src/main/java/de/mcs/tools/sps/SPSAssembler.java

@@ -71,518 +71,541 @@ import de.mcs.utils.jsap.SwitchOption;
 @Command(help = "SPS Assembler \r\n usage java -jar SPSEmulator-x.x.x.jar <options>")
 public class SPSAssembler {
 
-	private static final String INCLUDE_FILE = ".include";
-	private static final String END_MACRO_DEFINITION = ".endmacro";
-	private static final String START_MACRO_DEFINITION = ".macro";
-	private static final String DEFAULT_PACKAGE_FILTER = "de.mcs.tools.sps"; //$NON-NLS-1$
-	private static File source;
-	private static HARDWARE destination;
-	private static File destinationFile;
-	private static String outputFormat;
-	private static File includes;
-	private static Outputter outputter;
-	private static String destinationStr;
-
-	private int lineNumber;
-	// private int srcLineNumber;
-	private Map<String, Integer> labels;
-	private boolean inBlockComment;
-	private List<Mnemonic> mnemonics;
-	private boolean inMacro;
-	private Macro actualMacro;
-	private Map<String, Macro> macros;
-
-	@SwitchOption(shortKey = 'h', longKey = "help", name = "help", help = "show this help page", required = false, defaultValue = false)
-	public static void doHelp(boolean value) {
-		if (value) {
-			CommandlineProcessor.showHelp();
-			System.exit(0);
-		}
-	}
-
-	@StringOption(shortKey = 'f', longKey = "format", name = "format", defaultValue = "HEX", help = "the output format. HEX: IntelHEX, TPSTXT: TPS programming text", required = false)
-	public static void setOutputFormat(String value) {
-		outputFormat = value.toUpperCase();
-	}
-
-	@StringOption(shortKey = 'd', longKey = "hardware", name = "hardware system", defaultValue = "HOLTEK", help = "the hardware system to compile to. Passible options are: HOLTEK, ATMEGA8, ARDUINOSPS, TINYSPS", required = false)
-	public static void setDestinationSystem(String value) {
-		destinationStr = value;
-	}
-
-	@FileOption(shortKey = 'i', longKey = "includes", name = "includes", defaultValue = "", help = "where to find the includes files.", required = false)
-	public static void setDestinationSystem(File file) {
-		if ((file != null) && !file.getName().equals("")) {
-			includes = file;
-		}
-	}
-
-	@FileOption(index = 1, name = "source file", help = "source file to compile", required = true, mustExists = true)
-	public static void setSourceFile(File file) {
-		if ((file != null) && !file.getName().equals("")) {
-			source = file;
-		}
-	}
-
-	@FileOption(index = 2, name = "destination file", help = "destination file to compile to", required = false)
-	public static void setDestinationFile(File file) {
-		if ((file != null) && !file.getName().equals("")) {
-			destinationFile = file;
-		}
-	}
-
-	/**
-	 * @param args
-	 * @throws IOException
-	 */
-	public static void main(String[] args) {
-		try {
-			destination = HARDWARE.HOLTEK;
-
-			CommandlineProcessor.processCommandline(SPSAssembler.class, args);
-
-			try {
-				destination = HARDWARE.valueOf((destinationStr.toUpperCase()));
-			} catch (IllegalArgumentException e) {
-				throw new HardwareException(String.format("Hardware %s unknow for this assembler", destinationStr));
-			}
-
-			registerAllOutputter();
-
-			if ((source == null) || (!source.exists())) {
-				CommandlineProcessor.showHelp(String.format("source file null or not found. %s", (source == null) ? "" : source.getAbsolutePath()));
-				System.exit(-1);
-			}
-
-			if (destinationFile == null) {
-				String name = source.getName();
-				name = name.substring(0, source.getName().lastIndexOf("."));
-				String ext = outputter.getDefaultExtension();
-				destinationFile = new File(source.getParentFile(), name + ext);
-			}
-
-			System.out.printf("source file: %s \r\n", source.getName());
-			System.out.printf("destination file: %s \r\n", destinationFile.getName());
-			System.out.printf("output format: %s \r\n", outputFormat);
-			System.out.printf("hardware: %s \r\n", destination.name());
-			if (includes != null) {
-				System.out.printf("includes foldes: %s \r\n", includes.getCanonicalPath());
-			}
-			System.out.println();
-
-			try {
-				SPSAssembler spsAssembler = new SPSAssembler();
-				spsAssembler.doWork(source);
-
-				List<Mnemonic> mnemonics = spsAssembler.getMnemonics();
-
-				outputMnemonics(mnemonics);
-
-				outputLabels(spsAssembler);
-
-				outputMacros(spsAssembler);
-
-				outputFile(mnemonics);
-
-				System.out.println("assembling succesfully");
-			} catch (SyntaxError e) {
-				e.printStackTrace();
-				System.err.println(e.getMessage());
-				System.exit(-1);
-			}
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
-	}
-
-	/**
-	 * @throws InstantiationException
-	 * @throws IllegalAccessException
-	 * @throws Exception
-	 */
-	private static void registerAllOutputter() throws InstantiationException, IllegalAccessException, Exception {
-		Set<Class<?>> outputClasses = searchOutputter(SPSOutputter.class);
-		for (Class<?> outClass : outputClasses) {
-			SPSOutputter annotation = outClass.getAnnotation(SPSOutputter.class);
-			if (annotation.name().equalsIgnoreCase(outputFormat)) {
-				outputter = (Outputter) outClass.newInstance();
-			}
-		}
-
-		if (outputter == null) {
-			throw new Exception(String.format("can't find outputter for format: %s", outputFormat));
-		}
-	}
-
-	private static Set<Class<?>> searchOutputter(Class<? extends Annotation> annotationClass) {
-		ConfigurationBuilder builder = new ConfigurationBuilder();
-		builder.addUrls(ClasspathHelper.forPackage(DEFAULT_PACKAGE_FILTER));
-		Reflections reflections = new Reflections(builder);
-		Set<Class<?>> classes = new HashSet<Class<?>>();
-		classes.addAll(reflections.getTypesAnnotatedWith(annotationClass));
-		return classes;
-	}
-
-	/**
-	 * @param mnemonics
-	 * @throws IOException
-	 * @throws FileNotFoundException
-	 */
-	private static void outputFile(List<Mnemonic> mnemonics) throws IOException, FileNotFoundException {
-		try (FileOutputStream output = new FileOutputStream(destinationFile)) {
-			outputter.output(mnemonics, output);
-		} finally {
-		}
-	}
-
-	/**
-	 * @param spsAssembler
-	 */
-	private static void outputMacros(SPSAssembler spsAssembler) {
-		Map<String, Macro> macros = spsAssembler.getMacros();
-		if ((macros != null) && (macros.size() > 0)) {
-			System.out.println();
-			System.out.println("macros");
-			for (Macro macro : macros.values()) {
-				System.out.printf("%s: %s\r\n", macro.getName(), macro.toString());
-			}
-		}
-	}
-
-	/**
-	 * @param spsAssembler
-	 */
-	private static void outputLabels(SPSAssembler spsAssembler) {
-		Map<String, Integer> labels = spsAssembler.getLabels();
-		if ((labels != null) && (labels.size() > 0)) {
-			System.out.println();
-			System.out.println("labels");
-			for (Entry<String, Integer> entry : labels.entrySet()) {
-				System.out.printf("%s: 0x%03x\r\n", entry.getKey(), entry.getValue());
-			}
-		}
-	}
-
-	/**
-	 * @param mnemonics
-	 */
-	private static void outputMnemonics(List<Mnemonic> mnemonics) {
-		System.out.println("Mnemonics");
-		int pos = 0;
-		for (Iterator<Mnemonic> iterator = mnemonics.iterator(); iterator.hasNext();) {
-			Mnemonic mnemonic = iterator.next();
-			System.out.printf("0x%03x: %s\r\n", pos, mnemonic.toString());
-			pos++;
-		}
-	}
-
-	/**
-	 * 
-	 */
-	public SPSAssembler() {
-		lineNumber = 0;
-		// srcLineNumber = 0;
-		labels = new HashMap<>();
-		inBlockComment = false;
-		mnemonics = new ArrayList<>();
-		inMacro = false;
-		actualMacro = null;
-		macros = new HashMap<>();
-	}
-
-	private void doWork(File source) throws IOException, SyntaxError {
-		System.out.printf("start parsing file: %s\r\n", source.getName());
-
-		List<String> sourceFile = Files.readAllLines(source.toPath(), Charset.forName("UTF-8"));
-		for (int i = 0; i < sourceFile.size(); i++) {
-			String line = sourceFile.get(i);
-
-			List<String> linesToAdd;
-			do {
-				linesToAdd = parseLine(i, line);
-				if (linesToAdd != null) {
-					sourceFile.remove(i);
-					sourceFile.addAll(i, linesToAdd);
-					line = sourceFile.get(i);
-					linesToAdd = parseLine(i, line);
-				}
-			} while (linesToAdd != null);
-		}
-
-		// Checking destination
-		checkingHardware();
-
-		calculatingJumps();
-
-		paddingSubroutines();
-
-		// checking size of program
-		checkingProgramSize();
-	}
-
-	private void paddingSubroutines() throws SyntaxError {
-		// checking location of Subroutines
-		if (destination.equals(HARDWARE.ARDUINOSPS) || destination.equals(HARDWARE.TINYSPS)) {
-			int position = 0;
-			boolean foundSub = false;
-			for (int i = 0; i < mnemonics.size(); i++) {
-				Mnemonic mnemonic = mnemonics.get(i);
-				if (mnemonic instanceof DFSB) {
-					foundSub = true;
-					break;
-				}
-				position++;
-			}
-			if (foundSub && (position < 256)) {
-				int count = 256 - position;
-				for (int i = 0; i < count; i++) {
-					mnemonics.add(position, new NOP(""));
-				}
-			}
-		}
-	}
-
-	private void checkingProgramSize() throws HardwareException {
-		int prgSize = 0;
-		for (Mnemonic mnemonic : mnemonics) {
-			if (mnemonic instanceof DFSB) {
-				break;
-			}
-			prgSize++;
-		}
-		int maxSize = 128;
-		switch (destination) {
-		case ARDUINOSPS:
-		case TINYSPS:
-			maxSize = 256;
-			break;
-		default:
-			break;
-		}
-		if (prgSize > maxSize) {
-			throw new HardwareException(String.format("Program exceeding size (%d) for hardeware %s (%d).", prgSize, destination, maxSize));
-		}
-	}
-
-	private void calculatingJumps() throws SyntaxError {
-		int address = 0;
-		Mnemonic predecessor = null;
-		for (Iterator<Mnemonic> iterator = mnemonics.iterator(); iterator.hasNext();) {
-			Mnemonic mnemonic = iterator.next();
-			if ((mnemonic instanceof JMP) || (mnemonic instanceof LOOPC) || (mnemonic instanceof LOOPD) || (mnemonic instanceof CALL)) {
-				if (mnemonic.isLabel()) {
-					processJMP(mnemonic, predecessor);
-				}
-			}
-			if (mnemonic instanceof RJMP) {
-				if (mnemonic.isLabel()) {
-					processRJMP(address, mnemonic);
-				}
-			}
-			address++;
-			predecessor = mnemonic;
-		}
-	}
-
-	/**
-	 * @throws SyntaxError
-	 */
-	private void checkingHardware() throws SyntaxError {
-		for (Iterator<Mnemonic> iterator = mnemonics.iterator(); iterator.hasNext();) {
-			Mnemonic mnemonic = iterator.next();
-			if (!mnemonic.allowedHardware().contains(destination)) {
-				throw new SyntaxError(mnemonic.getLineNumber(),
-						String.format("the mnemonic \"%s\" with the argument \"%s\" is not availble on the choosen hardware \"%s\"", mnemonic.getName(),
-								mnemonic.getArgument() == null ? "" : mnemonic.getArgument(), destination.name()));
-			}
-		}
-	}
-
-	private void processJMP(Mnemonic mnemonic, Mnemonic predecessor) throws SyntaxError {
-		String label = mnemonic.getArgument();
-		if (!labels.containsKey(label)) {
-			throw new SyntaxError(mnemonic.getLineNumber(), String.format("used label %s on mnemonic \"%s\" is not defined.", label, mnemonic.getName()));
-		}
-		int lineNumber = (Integer) labels.get(label);
-		int page = lineNumber / 16;
-		lineNumber = lineNumber % 16;
-		mnemonic.setArgument(Integer.toString(lineNumber));
-		mnemonic.checkArgument();
-		if ((predecessor != null) && (predecessor instanceof PAGE)) {
-			PAGE pageMne = (PAGE) predecessor;
-			if (pageMne.isCalculate()) {
-				pageMne.setArgument(Integer.toString(page));
-				pageMne.checkArgument();
-			}
-		}
-	}
-
-	private void processRJMP(int address, Mnemonic mnemonic) throws SyntaxError {
-		String label = mnemonic.getArgument();
-		if (!labels.containsKey(label)) {
-			throw new SyntaxError(mnemonic.getLineNumber(), String.format("used label %s on mnemonic \"%s\" is not defined.", label, mnemonic.getName()));
-		}
-		int lineNumber = (Integer) labels.get(label);
-		lineNumber = address - lineNumber;
-		if (lineNumber < 0) {
-			throw new SyntaxError(mnemonic.getLineNumber(),
-					String.format("label %s defined after mnemonic \"%s\". JMP can only step back!", label, mnemonic.getName()));
-		}
-		mnemonic.setArgument(Integer.toString(lineNumber));
-		mnemonic.checkArgument();
-	}
-
-	private List<String> parseLine(int srcLineNumber, String srcLine) throws SyntaxError, IOException {
-		String line = srcLine.trim();
-		if (line.startsWith(".")) {
-			// process pre compiler part
-			String label = getLabel(line);
-			return precompiler(srcLineNumber, label);
-		} else {
-			if (inMacro) {
-				actualMacro.addLine(line);
-			} else {
-				if (line.startsWith(":")) {
-					String label = getLabel(line);
-					if (labels.containsKey(label)) {
-						throw new SyntaxError(srcLineNumber, String.format("Label \"%s\" already definied in line %d.", label, labels.get(label)));
-					}
-					labels.put(label, lineNumber);
-				} else {
-					Mnemonic mnemonic = getMnemonic(line, srcLineNumber);
-					if (mnemonic != null) {
-						lineNumber++;
-						mnemonics.add(mnemonic);
-					}
-				}
-			}
-		}
-		return null;
-	}
-
-	private List<String> precompiler(int srcLineNumber, String value) throws IOException, SyntaxError {
-		String label = value.trim().toLowerCase();
-		String name = label;
-		if (label.indexOf(" ") > 0) {
-			name = label.substring(0, label.indexOf(" "));
-		}
-		if (INCLUDE_FILE.equals(name)) {
-			includeFile(srcLineNumber, label);
-		} else if (START_MACRO_DEFINITION.equals(name)) {
-			startMacroDefinition(srcLineNumber, label);
-			inMacro = true;
-		} else if (END_MACRO_DEFINITION.equalsIgnoreCase(label)) {
-			// end of macro definition
-			inMacro = false;
-			macros.put(actualMacro.getName(), actualMacro);
-		} else {
-			// seems to be a macro usage
-			name = name.substring(1);
-			String[] arguments = label.split(" ");
-			if (arguments.length < 1) {
-				throw new IllegalArgument(srcLineNumber, "Need at least one argument for the macro name.");
-			}
-			String[] args = null;
-			if (arguments.length > 1) {
-				args = Arrays.copyOfRange(arguments, 1, arguments.length);
-			}
-			Macro macro = macros.get(name);
-			if (macro == null) {
-				throw new SyntaxError(srcLineNumber, String.format("macro with name %s not define.", name));
-			}
-			List<String> macroMnemonics = macro.processMacro(args, srcLineNumber);
-			return macroMnemonics;
-		}
-		return null;
-	}
-
-	/**
-	 * @param srcLineNumber
-	 * @param label
-	 * @throws IllegalArgument
-	 */
-	private void startMacroDefinition(int srcLineNumber, String label) throws IllegalArgument {
-		// macro definition
-		String[] arguments = label.split(" ");
-		if (arguments.length < 2) {
-			throw new IllegalArgument(srcLineNumber, "Need at least one argument for the macro name.");
-		}
-		String macroName = arguments[1];
-		String[] args = null;
-		if (arguments.length > 2) {
-			args = Arrays.copyOfRange(arguments, 2, arguments.length);
-		}
-		actualMacro = new Macro(macroName, args);
-	}
-
-	/**
-	 * @param srcLineNumber
-	 * @param label
-	 * @throws IllegalArgument
-	 * @throws IOException
-	 * @throws SyntaxError
-	 */
-	private void includeFile(int srcLineNumber, String label) throws IllegalArgument, IOException, SyntaxError {
-		String[] arguments = label.split(" ");
-		if (arguments.length < 2) {
-			throw new IllegalArgument(srcLineNumber, "Need at least one argument for the filename to include.");
-		}
-		File includeFile = new File(includes, String.format("%s.tps", arguments[1]));
-		if (!includeFile.exists()) {
-			throw new IllegalArgument(srcLineNumber, String.format("include file not found: %s", includeFile.getName()));
-		}
-		System.out.println("=====");
-		System.out.printf("include file: %s \r\n", includeFile.getName());
-		SPSAssembler spsAssembler = new SPSAssembler();
-		spsAssembler.doWork(includeFile);
-		outputMnemonics(spsAssembler.getMnemonics());
-		outputLabels(spsAssembler);
-		outputMacros(spsAssembler);
-		System.out.println("=====");
-	}
-
-	private Mnemonic getMnemonic(String line, int srcLineNumber) throws SyntaxError {
-		String newLine = stripComments(line);
-		if (StringUtils.isNotEmpty(newLine)) {
-			Mnemonic mnemonic = MnemonicFactory.getMnemonic(newLine, srcLineNumber);
-			return mnemonic;
-		}
-		return null;
-	}
-
-	private String stripComments(String line) {
-		if (line.indexOf("*/") >= 0) {
-			inBlockComment = false;
-			return null;
-		}
-		if (inBlockComment) {
-			return null;
-		}
-		if (line.indexOf(";") >= 0) {
-			line = line.substring(0, line.indexOf(";")).trim();
-			return line;
-		}
-		if (line.startsWith("/*")) {
-			inBlockComment = true;
-			return null;
-		}
-		return line.trim();
-	}
-
-	private String getLabel(String line) {
-		line = stripComments(line);
-		return line;
-	}
-
-	private List<Mnemonic> getMnemonics() {
-		return mnemonics;
-	}
-
-	private Map<String, Macro> getMacros() {
-		return macros;
-	}
-
-	private Map<String, Integer> getLabels() {
-		return labels;
-	}
+  private static final String INCLUDE_FILE = ".include";
+  private static final String END_MACRO_DEFINITION = ".endmacro";
+  private static final String START_MACRO_DEFINITION = ".macro";
+  private static final String DEFAULT_PACKAGE_FILTER = "de.mcs.tools.sps"; //$NON-NLS-1$
+  private static File source;
+  private static HARDWARE destination;
+  private static File destinationFile;
+  private static String outputFormat;
+  private static File includes;
+  private static Outputter outputter;
+  private static String destinationStr;
+
+  private int lineNumber;
+  // private int srcLineNumber;
+  private Map<String, Integer> labels;
+  private boolean inBlockComment;
+  private List<Mnemonic> mnemonics;
+  private boolean inMacro;
+  private Macro actualMacro;
+  private Map<String, Macro> macros;
+
+  @SwitchOption(shortKey = 'h', longKey = "help", name = "help", help = "show this help page", required = false, defaultValue = false)
+  public static void doHelp(boolean value) {
+    if (value) {
+      CommandlineProcessor.showHelp();
+      System.exit(0);
+    }
+  }
+
+  @StringOption(shortKey = 'f', longKey = "format", name = "format", defaultValue = "HEX", help = "the output format. HEX: IntelHEX, TPSTXT: TPS programming text", required = false)
+  public static void setOutputFormat(String value) {
+    outputFormat = value.toUpperCase();
+  }
+
+  @StringOption(shortKey = 'd', longKey = "hardware", name = "hardware system", defaultValue = "HOLTEK", help = "the hardware system to compile to. Passible options are: HOLTEK, ATMEGA8, ARDUINOSPS, TINYSPS", required = false)
+  public static void setDestinationSystem(String value) {
+    destinationStr = value;
+  }
+
+  @FileOption(shortKey = 'i', longKey = "includes", name = "includes", defaultValue = "", help = "where to find the includes files.", required = false)
+  public static void setDestinationSystem(File file) {
+    if ((file != null) && !file.getName().equals("")) {
+      includes = file;
+    }
+  }
+
+  @FileOption(index = 1, name = "source file", help = "source file to compile", required = true, mustExists = true)
+  public static void setSourceFile(File file) {
+    if ((file != null) && !file.getName().equals("")) {
+      source = file;
+    }
+  }
+
+  @FileOption(index = 2, name = "destination file", help = "destination file to compile to", required = false)
+  public static void setDestinationFile(File file) {
+    if ((file != null) && !file.getName().equals("")) {
+      destinationFile = file;
+    }
+  }
+
+  /**
+   * @param args
+   * @throws IOException
+   */
+  public static void main(String[] args) {
+    try {
+      destination = HARDWARE.HOLTEK;
+
+      CommandlineProcessor.processCommandline(SPSAssembler.class, args);
+
+      try {
+        destination = HARDWARE.valueOf((destinationStr.toUpperCase()));
+      } catch (IllegalArgumentException e) {
+        throw new HardwareException(String.format("Hardware %s unknow for this assembler", destinationStr));
+      }
+
+      registerAllOutputter();
+
+      if ((source == null) || (!source.exists())) {
+        CommandlineProcessor.showHelp(
+            String.format("source file null or not found. %s", (source == null) ? "" : source.getAbsolutePath()));
+        System.exit(-1);
+      }
+
+      if (destinationFile == null) {
+        String name = source.getName();
+        name = name.substring(0, source.getName().lastIndexOf("."));
+        String ext = outputter.getDefaultExtension();
+        destinationFile = new File(source.getParentFile(), name + ext);
+      }
+
+      System.out.printf("source file: %s \r\n", source.getName());
+      System.out.printf("destination file: %s \r\n", destinationFile.getName());
+      System.out.printf("output format: %s \r\n", outputFormat);
+      System.out.printf("hardware: %s \r\n", destination.name());
+      if (includes != null) {
+        System.out.printf("includes foldes: %s \r\n", includes.getCanonicalPath());
+      }
+      System.out.println();
+
+      try {
+        SPSAssembler spsAssembler = new SPSAssembler();
+        spsAssembler.doWork(source);
+
+        List<Mnemonic> mnemonics = spsAssembler.getMnemonics();
+
+        outputMnemonics(mnemonics);
+
+        outputLabels(spsAssembler);
+
+        outputMacros(spsAssembler);
+
+        outputFile(mnemonics);
+
+        System.out.println("assembling succesfully");
+      } catch (SyntaxError e) {
+        e.printStackTrace();
+        System.err.println(e.getMessage());
+        System.exit(-1);
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+
+  /**
+   * @throws InstantiationException
+   * @throws IllegalAccessException
+   * @throws Exception
+   */
+  private static void registerAllOutputter() throws InstantiationException, IllegalAccessException, Exception {
+    Set<Class<?>> outputClasses = searchOutputter(SPSOutputter.class);
+    for (Class<?> outClass : outputClasses) {
+      SPSOutputter annotation = outClass.getAnnotation(SPSOutputter.class);
+      if (annotation.name().equalsIgnoreCase(outputFormat)) {
+        outputter = (Outputter) outClass.newInstance();
+      }
+    }
+
+    if (outputter == null) {
+      throw new Exception(String.format("can't find outputter for format: %s", outputFormat));
+    }
+  }
+
+  private static Set<Class<?>> searchOutputter(Class<? extends Annotation> annotationClass) {
+    ConfigurationBuilder builder = new ConfigurationBuilder();
+    builder.addUrls(ClasspathHelper.forPackage(DEFAULT_PACKAGE_FILTER));
+    Reflections reflections = new Reflections(builder);
+    Set<Class<?>> classes = new HashSet<Class<?>>();
+    classes.addAll(reflections.getTypesAnnotatedWith(annotationClass));
+    return classes;
+  }
+
+  /**
+   * @param mnemonics
+   * @throws IOException
+   * @throws FileNotFoundException
+   */
+  private static void outputFile(List<Mnemonic> mnemonics) throws IOException, FileNotFoundException {
+    try (FileOutputStream output = new FileOutputStream(destinationFile)) {
+      outputter.output(mnemonics, output);
+    } finally {
+    }
+  }
+
+  /**
+   * @param spsAssembler
+   */
+  private static void outputMacros(SPSAssembler spsAssembler) {
+    Map<String, Macro> macros = spsAssembler.getMacros();
+    if ((macros != null) && (macros.size() > 0)) {
+      System.out.println();
+      System.out.println("macros");
+      for (Macro macro : macros.values()) {
+        System.out.printf("%s: %s\r\n", macro.getName(), macro.toString());
+      }
+    }
+  }
+
+  /**
+   * @param spsAssembler
+   */
+  private static void outputLabels(SPSAssembler spsAssembler) {
+    Map<String, Integer> labels = spsAssembler.getLabels();
+    if ((labels != null) && (labels.size() > 0)) {
+      System.out.println();
+      System.out.println("labels");
+      for (Entry<String, Integer> entry : labels.entrySet()) {
+        System.out.printf("%s: 0x%03x\r\n", entry.getKey(), entry.getValue());
+      }
+    }
+  }
+
+  /**
+   * @param mnemonics
+   */
+  private static void outputMnemonics(List<Mnemonic> mnemonics) {
+    System.out.println("Mnemonics");
+    int pos = 0;
+    for (Iterator<Mnemonic> iterator = mnemonics.iterator(); iterator.hasNext();) {
+      Mnemonic mnemonic = iterator.next();
+      System.out.printf("0x%03x: %s\r\n", pos, mnemonic.toString());
+      pos++;
+    }
+  }
+
+  /**
+   * 
+   */
+  public SPSAssembler() {
+    lineNumber = 0;
+    // srcLineNumber = 0;
+    labels = new HashMap<>();
+    inBlockComment = false;
+    mnemonics = new ArrayList<>();
+    inMacro = false;
+    actualMacro = null;
+    macros = new HashMap<>();
+  }
+
+  private void doWork(File source) throws IOException, SyntaxError {
+    System.out.printf("start parsing file: %s\r\n", source.getName());
+
+    List<String> sourceFile = Files.readAllLines(source.toPath(), Charset.forName("UTF-8"));
+    for (int i = 0; i < sourceFile.size(); i++) {
+      String line = sourceFile.get(i);
+
+      List<String> linesToAdd;
+      do {
+        linesToAdd = parseLine(i, line);
+        if (linesToAdd != null) {
+          sourceFile.remove(i);
+          sourceFile.addAll(i, linesToAdd);
+          line = sourceFile.get(i);
+          linesToAdd = parseLine(i, line);
+        }
+      } while (linesToAdd != null);
+    }
+
+    // Checking destination
+    checkingHardware();
+
+    calculatingJumps();
+
+    paddingSubroutines();
+
+    // checking size of program
+    checkingProgramSize();
+  }
+
+  private void paddingSubroutines() throws SyntaxError {
+    // checking location of Subroutines
+    if (destination.equals(HARDWARE.ARDUINOSPS) || destination.equals(HARDWARE.TINYSPS)) {
+      int position = 0;
+      boolean foundSub = false;
+      for (int i = 0; i < mnemonics.size(); i++) {
+        Mnemonic mnemonic = mnemonics.get(i);
+        if (mnemonic instanceof DFSB) {
+          foundSub = true;
+          break;
+        }
+        position++;
+      }
+      if (foundSub && (position < 256)) {
+        int count = 256 - position;
+        for (int i = 0; i < count; i++) {
+          mnemonics.add(position, new NOP(""));
+        }
+      }
+    }
+  }
+
+  private void checkingProgramSize() throws HardwareException {
+    int prgSize = 0;
+    boolean usingDFSB = false;
+    for (Mnemonic mnemonic : mnemonics) {
+      if (mnemonic instanceof DFSB) {
+        usingDFSB = true;
+        break;
+      }
+      prgSize++;
+    }
+    int maxSize = 128;
+    switch (destination) {
+    case ARDUINOSPS:
+    case TINYSPS:
+    case ATMEGA8:
+      maxSize = 256;
+      break;
+    default:
+      break;
+    }
+    if (prgSize > maxSize) {
+      throw new HardwareException(
+          String.format("Program exceeding size (%d) for hardeware %s (%d).", prgSize, destination, maxSize));
+    }
+
+    switch (destination) {
+    case ARDUINOSPS:
+      maxSize = 1024;
+    case TINYSPS:
+      maxSize = 512;
+      break;
+    default:
+      break;
+    }
+    if (mnemonics.size() > maxSize) {
+      throw new HardwareException(
+          String.format("Program exceeding size (%d) for hardeware %s (%d).", prgSize, destination, maxSize));
+    }
+  }
+
+  private void calculatingJumps() throws SyntaxError {
+    int address = 0;
+    Mnemonic predecessor = null;
+    for (Iterator<Mnemonic> iterator = mnemonics.iterator(); iterator.hasNext();) {
+      Mnemonic mnemonic = iterator.next();
+      if ((mnemonic instanceof JMP) || (mnemonic instanceof LOOPC) || (mnemonic instanceof LOOPD)
+          || (mnemonic instanceof CALL)) {
+        if (mnemonic.isLabel()) {
+          processJMP(mnemonic, predecessor);
+        }
+      }
+      if (mnemonic instanceof RJMP) {
+        if (mnemonic.isLabel()) {
+          processRJMP(address, mnemonic);
+        }
+      }
+      address++;
+      predecessor = mnemonic;
+    }
+  }
+
+  /**
+   * @throws SyntaxError
+   */
+  private void checkingHardware() throws SyntaxError {
+    for (Iterator<Mnemonic> iterator = mnemonics.iterator(); iterator.hasNext();) {
+      Mnemonic mnemonic = iterator.next();
+      if (!mnemonic.allowedHardware().contains(destination)) {
+        throw new SyntaxError(mnemonic.getLineNumber(),
+            String.format("the mnemonic \"%s\" with the argument \"%s\" is not availble on the choosen hardware \"%s\"",
+                mnemonic.getName(), mnemonic.getArgument() == null ? "" : mnemonic.getArgument(), destination.name()));
+      }
+    }
+  }
+
+  private void processJMP(Mnemonic mnemonic, Mnemonic predecessor) throws SyntaxError {
+    String label = mnemonic.getArgument();
+    if (!labels.containsKey(label)) {
+      throw new SyntaxError(mnemonic.getLineNumber(),
+          String.format("used label %s on mnemonic \"%s\" is not defined.", label, mnemonic.getName()));
+    }
+    int lineNumber = (Integer) labels.get(label);
+    int page = lineNumber / 16;
+    lineNumber = lineNumber % 16;
+    mnemonic.setArgument(Integer.toString(lineNumber));
+    mnemonic.checkArgument();
+    if ((predecessor != null) && (predecessor instanceof PAGE)) {
+      PAGE pageMne = (PAGE) predecessor;
+      if (pageMne.isCalculate()) {
+        pageMne.setArgument(Integer.toString(page));
+        pageMne.checkArgument();
+      }
+    }
+  }
+
+  private void processRJMP(int address, Mnemonic mnemonic) throws SyntaxError {
+    String label = mnemonic.getArgument();
+    if (!labels.containsKey(label)) {
+      throw new SyntaxError(mnemonic.getLineNumber(),
+          String.format("used label %s on mnemonic \"%s\" is not defined.", label, mnemonic.getName()));
+    }
+    int lineNumber = (Integer) labels.get(label);
+    lineNumber = address - lineNumber;
+    if (lineNumber < 0) {
+      throw new SyntaxError(mnemonic.getLineNumber(),
+          String.format("label %s defined after mnemonic \"%s\". JMP can only step back!", label, mnemonic.getName()));
+    }
+    mnemonic.setArgument(Integer.toString(lineNumber));
+    mnemonic.checkArgument();
+  }
+
+  private List<String> parseLine(int srcLineNumber, String srcLine) throws SyntaxError, IOException {
+    String line = srcLine.trim();
+    if (line.startsWith(".")) {
+      // process pre compiler part
+      String label = getLabel(line);
+      return precompiler(srcLineNumber, label);
+    } else {
+      if (inMacro) {
+        actualMacro.addLine(line);
+      } else {
+        if (line.startsWith(":")) {
+          String label = getLabel(line);
+          if (labels.containsKey(label)) {
+            throw new SyntaxError(srcLineNumber,
+                String.format("Label \"%s\" already definied in line %d.", label, labels.get(label)));
+          }
+          labels.put(label, lineNumber);
+        } else {
+          Mnemonic mnemonic = getMnemonic(line, srcLineNumber);
+          if (mnemonic != null) {
+            lineNumber++;
+            mnemonics.add(mnemonic);
+          }
+        }
+      }
+    }
+    return null;
+  }
+
+  private List<String> precompiler(int srcLineNumber, String value) throws IOException, SyntaxError {
+    String label = value.trim().toLowerCase();
+    String name = label;
+    if (label.indexOf(" ") > 0) {
+      name = label.substring(0, label.indexOf(" "));
+    }
+    if (INCLUDE_FILE.equals(name)) {
+      includeFile(srcLineNumber, label);
+    } else if (START_MACRO_DEFINITION.equals(name)) {
+      startMacroDefinition(srcLineNumber, label);
+      inMacro = true;
+    } else if (END_MACRO_DEFINITION.equalsIgnoreCase(label)) {
+      // end of macro definition
+      inMacro = false;
+      macros.put(actualMacro.getName(), actualMacro);
+    } else {
+      // seems to be a macro usage
+      name = name.substring(1);
+      String[] arguments = label.split(" ");
+      if (arguments.length < 1) {
+        throw new IllegalArgument(srcLineNumber, "Need at least one argument for the macro name.");
+      }
+      String[] args = null;
+      if (arguments.length > 1) {
+        args = Arrays.copyOfRange(arguments, 1, arguments.length);
+      }
+      Macro macro = macros.get(name);
+      if (macro == null) {
+        throw new SyntaxError(srcLineNumber, String.format("macro with name %s not define.", name));
+      }
+      List<String> macroMnemonics = macro.processMacro(args, srcLineNumber);
+      return macroMnemonics;
+    }
+    return null;
+  }
+
+  /**
+   * @param srcLineNumber
+   * @param label
+   * @throws IllegalArgument
+   */
+  private void startMacroDefinition(int srcLineNumber, String label) throws IllegalArgument {
+    // macro definition
+    String[] arguments = label.split(" ");
+    if (arguments.length < 2) {
+      throw new IllegalArgument(srcLineNumber, "Need at least one argument for the macro name.");
+    }
+    String macroName = arguments[1];
+    String[] args = null;
+    if (arguments.length > 2) {
+      args = Arrays.copyOfRange(arguments, 2, arguments.length);
+    }
+    actualMacro = new Macro(macroName, args);
+  }
+
+  /**
+   * @param srcLineNumber
+   * @param label
+   * @throws IllegalArgument
+   * @throws IOException
+   * @throws SyntaxError
+   */
+  private void includeFile(int srcLineNumber, String label) throws IllegalArgument, IOException, SyntaxError {
+    String[] arguments = label.split(" ");
+    if (arguments.length < 2) {
+      throw new IllegalArgument(srcLineNumber, "Need at least one argument for the filename to include.");
+    }
+    File includeFile = new File(includes, String.format("%s.tps", arguments[1]));
+    if (!includeFile.exists()) {
+      throw new IllegalArgument(srcLineNumber, String.format("include file not found: %s", includeFile.getName()));
+    }
+    System.out.println("=====");
+    System.out.printf("include file: %s \r\n", includeFile.getName());
+    SPSAssembler spsAssembler = new SPSAssembler();
+    spsAssembler.doWork(includeFile);
+    outputMnemonics(spsAssembler.getMnemonics());
+    outputLabels(spsAssembler);
+    outputMacros(spsAssembler);
+    System.out.println("=====");
+  }
+
+  private Mnemonic getMnemonic(String line, int srcLineNumber) throws SyntaxError {
+    String newLine = stripComments(line);
+    if (StringUtils.isNotEmpty(newLine)) {
+      Mnemonic mnemonic = MnemonicFactory.getMnemonic(newLine, srcLineNumber);
+      return mnemonic;
+    }
+    return null;
+  }
+
+  private String stripComments(String line) {
+    if (line.indexOf("*/") >= 0) {
+      inBlockComment = false;
+      return null;
+    }
+    if (inBlockComment) {
+      return null;
+    }
+    if (line.indexOf(";") >= 0) {
+      line = line.substring(0, line.indexOf(";")).trim();
+      return line;
+    }
+    if (line.startsWith("/*")) {
+      inBlockComment = true;
+      return null;
+    }
+    return line.trim();
+  }
+
+  private String getLabel(String line) {
+    line = stripComments(line);
+    return line;
+  }
+
+  private List<Mnemonic> getMnemonics() {
+    return mnemonics;
+  }
+
+  private Map<String, Macro> getMacros() {
+    return macros;
+  }
+
+  private Map<String, Integer> getLabels() {
+    return labels;
+  }
 }