diff --git a/include/Lexesis/backendmanager.h b/include/Lexesis/backendmanager.h
index 5821c86..73c993d 100644
--- a/include/Lexesis/backendmanager.h
+++ b/include/Lexesis/backendmanager.h
@@ -6,9 +6,9 @@
 #include <string>
 #include <vector>
 
-namespace lxs {
-    class Backend;
+#include "Lexesis/backend.h"
 
+namespace lxs {
     class BackendManager {
         public:
             void registerBackend(std::unique_ptr<Backend> backend);
diff --git a/include/Lexesis/backends/cpp.h b/include/Lexesis/backends/cpp.h
index f6ddc63..b7a15c1 100644
--- a/include/Lexesis/backends/cpp.h
+++ b/include/Lexesis/backends/cpp.h
@@ -13,15 +13,16 @@ namespace backends
             CppBackend();
             virtual ~CppBackend();
 
+            virtual std::string getName();
             virtual bool canProcessLang(std::string lang);
 
             virtual void generateLexer(std::function<std::unique_ptr<std::ostream>(std::string)> getOstreamForFileName, std::string lexerName, const DFA& dfa);
 
         private:
-            templ::TemplateContext buildTable(const DFA& dfa, const std::vector<char>& transition_idx, int num_transitions_per_state) const;
+            templ::TemplateContext buildTable(const DFA& dfa, const std::vector<unsigned char>& transition_idx, int num_transitions_per_state) const;
             templ::TemplateContext buildTokenList(const DFA& dfa) const;
-            std::pair<std::vector<char>, int> buildTransitionIndices(const DFA& dfa) const;
-            templ::TemplateContext transformTransitionIndices(std::vector<char> transition_indices) const;
+            std::pair<std::vector<unsigned char>, int> buildTransitionIndices(const DFA& dfa) const;
+            templ::TemplateContext transformTransitionIndices(const std::vector<unsigned char>& transition_indices) const;
     };
 
 }
diff --git a/src/main.cpp b/src/main.cpp
index 257902e..458aa53 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,13 +1,45 @@
-#include "Lexesis/automata.h"
-#include "Lexesis/re.h"
+#include "Lexesis/backendmanager.h"
+#include "Lexesis/backends/cpp.h"
+#include "Lexesis/driver.h"
 
+#include "OptionParser.h"
+
+#include <fstream>
 #include <iostream>
 
-int main() {
-    lxs::ENFA enfa;
-    std::shared_ptr<lxs::RE> re = lxs::parseRE("[]-a-dA-D]");
-    re->toENFA(enfa, 0);
-    enfa.numStates++;
-    enfa.starting = 0;
-    std::cout << lxs::toDot(enfa) << std::endl;
+int main(int argc, char** argv) {
+    optparse::OptionParser parser = optparse::OptionParser().description("Lexesis, the lexical analyser generator.").usage("Lexesis [-d <outputdir>] [-l <language>] [-n <lexername>] <inputfile.lxs>");
+    parser.add_help_option(true);
+    parser.version("%prog 1.0");
+    parser.add_option("-d", "--outputdir").dest("outputdir").help("Output the generated files to this directory\n[default: .]").metavar("<directory>").set_default(".");
+    parser.add_option("-l", "--lang", "--language").dest("language").help("The programming language to generate source files for\n[default: c++]").metavar("<language>").set_default("c++");
+    parser.add_option("-n", "--name").dest("lexername").help("Use this name for the generated lexer, the default is based on the input file name").metavar("<lexername>");
+
+    optparse::Values options = parser.parse_args(argc, argv);
+    std::vector<std::string> args = parser.args();
+
+    if (args.size() != 1) {
+        parser.print_usage(std::cerr);
+        return 1;
+    }
+
+    std::ifstream infile(args[0]);
+    if (!infile.good()) {
+        std::cerr << "Could not open file '" << args[0] << "' for reading" << std::endl;
+        return 1;
+    }
+
+    std::string lexername = options["lexername"];
+    if (!lexername.length()) {
+        if (args[0].length() >= 4 && args[0].substr(args[0].length() - 4, 4) == ".lxs") {
+            lexername = args[0].substr(0, args[0].length() - 4); //Drop the .lxs
+        } else {
+            lexername = args[0];
+        }
+    }
+
+    std::unique_ptr<lxs::BackendManager> backends(new lxs::BackendManager());
+    backends->registerBackend(std::unique_ptr<lxs::Backend>(new lxs::backends::CppBackend()));
+    lxs::Driver driver(std::move(backends), infile, options["outputdir"], options["language"], lexername);
+    return driver.run();
 }