From 0db1ed5a8c6d2e6dff3cd34fa816596b7eda20de Mon Sep 17 00:00:00 2001 From: Robin Jadoul Date: Sun, 27 Nov 2016 13:20:08 +0100 Subject: [PATCH] Move template implementation to a header, where it belongs --- include/Parsodus/lrtables/generator.h | 127 ++++++++++++++++++++++++ src/CMakeLists.txt | 17 +++- src/lrtables/generator.cpp | 134 -------------------------- 3 files changed, 139 insertions(+), 139 deletions(-) delete mode 100644 src/lrtables/generator.cpp 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 + 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> m_follow; }; +template +Generator::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 +LRTable Generator::generate() { + //TODO + LRTable table; + std::vector> itemsets; + itemsets.emplace_back(closure({initial_item(m_startrule, EOF_PLACEHOLDER)})); + + std::queue itemqueue; + itemqueue.push(itemsets[0]); + while (!itemqueue.empty()) { + std::set cur = std::move(itemqueue.front()); + itemqueue.pop(); + + for (std::pair> succ : successors(cur)) { + //Add new itemset or merge + } + } + + return table; +} + +template +void Generator::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& 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 tmp = m_first[replacement]; + tmp.erase(""); + update(head, tmp); + } else { + update(head, m_first[replacement]); + ended = true; + break; + } + } + if (!ended) { + update(head, {""}); + } + } + } + } +} + +template +void Generator::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 - -namespace pds { -namespace lr -{ - -const std::string EXTENDED_START = "^"; -const std::string EOF_PLACEHOLDER = "$"; - -template -Generator::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 -LRTable Generator::generate() { - //TODO - LRTable table; - std::vector> itemsets; - itemsets.emplace_back(closure({initial_item(m_startrule, EOF_PLACEHOLDER)})); - - std::queue itemqueue; - itemqueue.push(itemsets[0]); - while (!itemqueue.empty()) { - std::set cur = std::move(itemqueue.front()); - itemqueue.pop(); - - for (std::pair> succ : successors(cur)) { - //Add new itemset or merge - } - } - - return table; -} - -template -void Generator::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& 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 tmp = m_first[replacement]; - tmp.erase(""); - update(head, tmp); - } else { - update(head, m_first[replacement]); - ended = true; - break; - } - } - if (!ended) { - update(head, {""}); - } - } - } - } -} - -template -void Generator::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 */