diff --git a/include/Parsodus/lrtables/generator.h b/include/Parsodus/lrtables/generator.h
index 1c55b8a..ff3b42a 100644
--- a/include/Parsodus/lrtables/generator.h
+++ b/include/Parsodus/lrtables/generator.h
@@ -5,9 +5,14 @@
 #include "Parsodus/grammar.h"
 #include "Parsodus/lrtables/table.h"
 
+#include <queue>
+
 namespace pds {
 namespace lr {
 
+const std::string EXTENDED_START = "^";
+const std::string EOF_PLACEHOLDER = "$";
+
 /**
  * Base class for LR (and derivative) table generators (such as SLR and LALR)
  * Parametrized on the type of item to be used in the configuration sets
@@ -70,6 +75,128 @@ class Generator {
         std::map<std::string, std::set<std::string>> m_follow;
 };
 
+template <typename Item>
+Generator<Item>::Generator(const std::string& start, const Grammar& g) : m_gram(g), m_startrule(Rule{EXTENDED_START, {start}}), m_first(), m_follow() {
+    m_gram.terminals.insert(EOF_PLACEHOLDER); //End of file
+    m_gram.variables.insert(EXTENDED_START); //modified start rule
+    m_gram.rules[EXTENDED_START].insert(m_startrule);
+
+    if (needsFollowSet()) {
+        buildFirst();
+        buildFollow();
+    }
+}
+
+template <typename Item>
+LRTable Generator<Item>::generate() {
+    //TODO
+    LRTable table;
+    std::vector<std::set<Item>> itemsets;
+    itemsets.emplace_back(closure({initial_item(m_startrule, EOF_PLACEHOLDER)}));
+
+    std::queue<Item> itemqueue;
+    itemqueue.push(itemsets[0]);
+    while (!itemqueue.empty()) {
+        std::set<Item> cur = std::move(itemqueue.front());
+        itemqueue.pop();
+        
+        for (std::pair<std::string, std::set<Item>> succ : successors(cur)) {
+            //Add new itemset or merge
+        }
+    }
+
+    return table;
+}
+
+template <typename Item>
+void Generator<Item>::buildFirst() {
+    for (std::string term : m_gram.terminals) {
+        m_first[term].insert(term);
+    }
+
+
+    bool changes = true;
+
+    auto update = [&changes, this](std::string head, auto& s) {
+        for (std::string elem : s) {
+            if (!m_first[head].count(elem)) {
+                changes = true;
+                m_first[head].insert(s.begin(), s.end());
+                return;
+            }
+        }
+    };
+
+    while (changes) {
+        changes = false;
+
+        for (const auto& p : m_gram.rules) {
+            const std::string& head = p.first;
+            const std::set<Rule>& rules = p.second;
+            for (const Rule& rule : rules) {
+                if (rule.tail.size() == 0) {
+                    update(head, {""});
+                }
+
+                bool ended = false;
+                for (const std::string& replacement : rule.tail) {
+                    if (m_first[replacement].count("")) {
+                        std::set<std::string> tmp = m_first[replacement];
+                        tmp.erase("");
+                        update(head, tmp);
+                    } else {
+                        update(head, m_first[replacement]);
+                        ended = true;
+                        break;
+                    }
+                }
+                if (!ended) {
+                    update(head, {""});
+                }
+            }
+        }
+    }
+}
+
+template <typename Item>
+void Generator<Item>::buildFollow() {
+    //EOF follow the added start rule.
+    m_follow[EXTENDED_START].insert(EOF_PLACEHOLDER);
+
+    bool changes = true;
+
+    auto update = [&changes, this](std::string head, auto s) {
+        s.erase("");
+        for (std::string elem : s) {
+            if (!m_follow[head].count(elem)) {
+                changes = true;
+                m_follow[head].insert(s.begin(), s.end());
+                return;
+            }
+        }
+    };
+
+    while (changes) {
+        changes = false;
+        for (const auto& p : m_gram.rules) {
+            std::string& head = p.first;
+            for (const auto& rule : p.second) {
+                for (std::size_t i = 0; i < rule.tail.size(); i++) {
+                    if (!m_gram.terminals.count(rule.tail[i])) {
+                        if (i == rule.tail.size() - 1 || m_first[rule.tail[i + 1]].count("")) {
+                            update(rule.tail[i], m_follow[head]);
+                        }
+                        if (i < rule.tail.size() - 1) {
+                            update(rule.tail[i], m_first[rule.tail[i + 1]]);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+
 } /* lr */
 } /* pdf */
 
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index de992e5..259ff60 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,9 +1,8 @@
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h @ONLY)
 include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
 
-add_library(Parsodus-tables
-    lrtables/generator.cpp
-    )
+# add_library(Parsodus-tables
+    # )
 
 add_library(Parsodus-backends
     backends/cpp.cpp
@@ -18,13 +17,21 @@ add_library(pds
 add_executable(Parsodus
     main.cpp
     )
-target_link_libraries(Parsodus Parsodus-backends pds mstch::mstch)
+target_link_libraries(Parsodus
+    #Parsodus-tables
+    Parsodus-backends
+    pds
+    mstch::mstch)
 
 if (CMAKE_BUILD_TYPE MATCHES Debug)
     add_executable(Parsodus-test
         test.cpp
         )
-    target_link_libraries(Parsodus-test Parsodus-backends pds mstch::mstch)
+    target_link_libraries(Parsodus-test
+        #Parsodus-tables
+        Parsodus-backends
+        pds
+        mstch::mstch)
 endif()
 
 install(TARGETS Parsodus
diff --git a/src/lrtables/generator.cpp b/src/lrtables/generator.cpp
deleted file mode 100644
index 8cf8a17..0000000
--- a/src/lrtables/generator.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-#include "Parsodus/lrtables/generator.h"
-
-#include <queue>
-
-namespace pds {
-namespace lr
-{
-
-const std::string EXTENDED_START = "^";
-const std::string EOF_PLACEHOLDER = "$";
-   
-template <typename Item>
-Generator<Item>::Generator(const std::string& start, const Grammar& g) : m_gram(g), m_startrule(Rule{EXTENDED_START, {start}}), m_first(), m_follow() {
-    m_gram.terminals.insert(EOF_PLACEHOLDER); //End of file
-    m_gram.variables.insert(EXTENDED_START); //modified start rule
-    m_gram.rules[EXTENDED_START].insert(m_startrule);
-
-    if (needsFollowSet()) {
-        buildFirst();
-        buildFollow();
-    }
-}
-
-template <typename Item>
-LRTable Generator<Item>::generate() {
-    //TODO
-    LRTable table;
-    std::vector<std::set<Item>> itemsets;
-    itemsets.emplace_back(closure({initial_item(m_startrule, EOF_PLACEHOLDER)}));
-
-    std::queue<Item> itemqueue;
-    itemqueue.push(itemsets[0]);
-    while (!itemqueue.empty()) {
-        std::set<Item> cur = std::move(itemqueue.front());
-        itemqueue.pop();
-        
-        for (std::pair<std::string, std::set<Item>> succ : successors(cur)) {
-            //Add new itemset or merge
-        }
-    }
-
-    return table;
-}
-
-template <typename Item>
-void Generator<Item>::buildFirst() {
-    for (std::string term : m_gram.terminals) {
-        m_first[term].insert(term);
-    }
-
-
-    bool changes = true;
-
-    auto update = [&changes, this](std::string head, auto& s) {
-        for (std::string elem : s) {
-            if (!m_first[head].count(elem)) {
-                changes = true;
-                m_first[head].insert(s.begin(), s.end());
-                return;
-            }
-        }
-    };
-
-    while (changes) {
-        changes = false;
-
-        for (const auto& p : m_gram.rules) {
-            const std::string& head = p.first;
-            const std::set<Rule>& rules = p.second;
-            for (const Rule& rule : rules) {
-                if (rule.tail.size() == 0) {
-                    update(head, {""});
-                }
-
-                bool ended = false;
-                for (const std::string& replacement : rule.tail) {
-                    if (m_first[replacement].count("")) {
-                        std::set<std::string> tmp = m_first[replacement];
-                        tmp.erase("");
-                        update(head, tmp);
-                    } else {
-                        update(head, m_first[replacement]);
-                        ended = true;
-                        break;
-                    }
-                }
-                if (!ended) {
-                    update(head, {""});
-                }
-            }
-        }
-    }
-}
-
-template <typename Item>
-void Generator<Item>::buildFollow() {
-    //EOF follow the added start rule.
-    m_follow[EXTENDED_START].insert(EOF_PLACEHOLDER);
-
-    bool changes = true;
-
-    auto update = [&changes, this](std::string head, auto s) {
-        s.erase("");
-        for (std::string elem : s) {
-            if (!m_follow[head].count(elem)) {
-                changes = true;
-                m_follow[head].insert(s.begin(), s.end());
-                return;
-            }
-        }
-    };
-
-    while (changes) {
-        changes = false;
-        for (const auto& p : m_gram.rules) {
-            std::string& head = p.first;
-            for (const auto& rule : p.second) {
-                for (std::size_t i = 0; i < rule.tail.size(); i++) {
-                    if (!m_gram.terminals.count(rule.tail[i])) {
-                        if (i == rule.tail.size() - 1 || m_first[rule.tail[i + 1]].count("")) {
-                            update(rule.tail[i], m_follow[head]);
-                        }
-                        if (i < rule.tail.size() - 1) {
-                            update(rule.tail[i], m_first[rule.tail[i + 1]]);
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
-
-} /* lr */  
-} /* pds  */