Move template implementation to a header, where it belongs
This commit is contained in:
parent
b2a62daed1
commit
0db1ed5a8c
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
Loading…
Reference in New Issue