diff --git a/build.gradle b/build.gradle
index 5baa6a6d6ad0824fb813cf582c10e64d10b3f557..cac319cdc22df735b8ed27a43d84e1f626b14160 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,5 +1,5 @@
 group 'de.tudresden.inf.st'
-version '1.0-SNAPSHOT'
+version '0.1'
 
 apply plugin: 'java'
 apply plugin: 'application'
@@ -65,6 +65,10 @@ jar {
                 'Main-Class': 'de.tudresden.inf.st.e2j.Main'
         )
     }
+
+    from {
+        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
+    }
 }
 
 task preprocess(type: JavaExec) {
diff --git a/src/main/java/de/tudresden/inf/st/e2j/Main.java b/src/main/java/de/tudresden/inf/st/e2j/Main.java
index a85a68fe8d9f2f40680bad0a59734f50f57faa4c..11bdb72af2c93f048fe4f3d4d25b649cd9c17478 100644
--- a/src/main/java/de/tudresden/inf/st/e2j/Main.java
+++ b/src/main/java/de/tudresden/inf/st/e2j/Main.java
@@ -1,9 +1,102 @@
 package de.tudresden.inf.st.e2j;
 
+import de.tudresden.inf.st.e2j.jastadd.model.EObject;
+import de.tudresden.inf.st.e2j.jastadd.model.EPackage;
+import de.tudresden.inf.st.e2j.jastadd.model.Grammar;
+import de.tudresden.inf.st.e2j.parser.EcoreParser;
+import de.tudresden.inf.st.e2j.parser.XMIParseException;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+
 public class Main {
 
+  private static final String VERSION = "0.1";
+
   public static void main(String[] args) {
-    System.out.println("Hello, world!");
+
+    if (args.length != 2) {
+      printUsage();
+    } else {
+      transformFile(args[0], args[1]);
+    }
+
+  }
+
+  private static void transformFile(String sourceFileName, String targetFileName) {
+
+    List<EObject> ePackages = null;
+
+    EcoreParser parser = new EcoreParser();
+
+    // check if the input file exists
+    Path sourcePath = Paths.get(sourceFileName);
+    if (Files.notExists(sourcePath)) {
+      exitWithError("the source file does not exist.");
+    }
+    Path targetPath = Paths.get(targetFileName);
+    if (Files.exists(targetPath)) {
+      exitWithError("the target file already exists.");
+    }
+
+    try (InputStream stream = Files.newInputStream(sourcePath)) {
+      ePackages = parser.parse(stream);
+    } catch (IOException e) {
+      exitWithError("Unable to open or read source file.");
+    } catch(XMIParseException e) {
+      exitWithError("Parse error occurred: " + e.getMessage());
+    }
+
+    if (ePackages == null || ePackages.size() == 0) {
+      exitWithError("No ecore packages were parsed.");
+    }
+
+    StringBuilder b = new StringBuilder();
+
+    for (EObject eObject : ePackages) {
+      if (!(eObject instanceof EPackage)) {
+        exitWithError("One of the parsed top-level objects is no EPackage.");
+      }
+
+      EPackage ePackage = ((EPackage) eObject);
+
+      try {
+        Grammar grammar = ePackage.getGrammar();
+        grammar.print(b);
+      } catch (Exception e) {
+        exitWithError("Unable to transform Ecore package " + ePackage.getName() + " to grammar.");
+      }
+      b.append("\n\n");
+    }
+
+    if (!targetFileName.endsWith(".relast")) {
+      targetFileName += ".relast";
+    }
+
+    try (PrintWriter out = new PrintWriter(targetFileName, StandardCharsets.UTF_8.name())) {
+      out.print(b.toString());
+    } catch (FileNotFoundException | UnsupportedEncodingException e) {
+      exitWithError("Unable to write relast file");
+    }
+  }
+
+  private static void exitWithError(String message) {
+    System.err.println("ERROR: " + message);
+    System.err.println("exiting...");
+    System.exit(-1);
+  }
+
+  private static void printUsage() {
+    System.out.println("Ecore2Relast version " + VERSION + ": generate a relational JastAdd grammar from an ecore model");
+    System.out.println("Attention: this is a very early version that might contain bugs. please review the generated grammars.");
+    System.out.println("Limitations: Only essential structural parts of ecore models are transformed. Multiple inheritance is not supported.");
+    System.out.println("Usage:");
+    System.out.println("  -h, --help                    print this message");
+    System.out.println("  <input.ecore> <output.relast> transform the input ecore model into an equivalent grammar with the given name");
   }
 
 }