diff --git a/include/Parsodus/lrtables/generator.h b/include/Parsodus/lrtables/generator.h index f49988d..423be1c 100644 --- a/include/Parsodus/lrtables/generator.h +++ b/include/Parsodus/lrtables/generator.h @@ -18,9 +18,10 @@ class Generator { /** * Constructor * + * @param start The start symbol for the grammar * @param g The grammar to translate */ - Generator(const Grammar& g); + Generator(const std::string& start, const Grammar& g); /** * Generate an LRTable based on given grammar @@ -35,6 +36,15 @@ class Generator { */ virtual bool needsFollowSet() = 0; + /** + * Build the starting item to build all item sets from + * + * @param startrule The constructed extended starting rule + * @param eof The token used as end of file + */ + virtual Item initial_item(Rule startrule, std::string eof) = 0; + + std::set<std::string> first(std::string s); std::set<std::string> follow(std::string s); @@ -49,7 +59,13 @@ class Generator { */ void buildFollow(); + /** + * Compute the closure of an item set + */ + std::set<Item> closure(const std::set<Item>& its); + Grammar m_gram; + Rule m_startrule; std::map<std::string, std::set<std::string>> m_first; std::map<std::string, std::set<std::string>> m_follow; }; diff --git a/src/lrtables/generator.cpp b/src/lrtables/generator.cpp index 665c0a5..8cf8a17 100644 --- a/src/lrtables/generator.cpp +++ b/src/lrtables/generator.cpp @@ -1,11 +1,20 @@ #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 Grammar& g) : m_gram(g), m_first(), m_follow() { +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(); @@ -15,6 +24,22 @@ Generator<Item>::Generator(const Grammar& g) : m_gram(g), m_first(), m_follow() 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> @@ -70,7 +95,7 @@ void Generator<Item>::buildFirst() { template <typename Item> void Generator<Item>::buildFollow() { //EOF follow the added start rule. - m_follow["^"].insert("$"); + m_follow[EXTENDED_START].insert(EOF_PLACEHOLDER); bool changes = true;