generator: add methods to generate closed item sets
This commit is contained in:
parent
8b94b9cf2c
commit
129b81e093
3 changed files with 72 additions and 1 deletions
|
@ -26,9 +26,70 @@
|
||||||
|
|
||||||
#include "generator.hpp"
|
#include "generator.hpp"
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
|
||||||
namespace solar {
|
namespace solar {
|
||||||
|
|
||||||
|
std::set<item_t> generator_t::get_set(const std::string &nonterm) {
|
||||||
|
std::set<item_t> set;
|
||||||
|
|
||||||
|
auto entries = rules.equal_range(nonterm);
|
||||||
|
for (auto entry = entries.first; entry != entries.second; ++entry)
|
||||||
|
set.insert(entry->second);
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
void generator_t::close_set(std::set<item_t> *set) {
|
||||||
|
std::queue<item_t> queue;
|
||||||
|
for (const item_t &item : *set)
|
||||||
|
queue.emplace(item);
|
||||||
|
|
||||||
|
for (; !queue.empty(); queue.pop()) {
|
||||||
|
const item_t &cur = queue.front();
|
||||||
|
if (!cur.has_next())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const symbol_t &sym = cur.get_next_symbol();
|
||||||
|
if (sym.get_type() != SYMBOL_TYPE_NONTERM)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (const item_t &item : get_set(sym.get_value())) {
|
||||||
|
if (set->insert(item).second)
|
||||||
|
queue.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void generator_t::print_item(const item_t &item) {
|
||||||
|
printf("%s |=", item.get_lhs().c_str());
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= item.get_rhs().size(); i++) {
|
||||||
|
if (i == item.get_point())
|
||||||
|
printf(" .");
|
||||||
|
|
||||||
|
if (i == item.get_rhs().size())
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (item.get_rhs()[i].get_type()) {
|
||||||
|
case SYMBOL_TYPE_CHAR:
|
||||||
|
printf(" '%c'", item.get_rhs()[i].get_value()[0]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf(" %s", item.get_rhs()[i].get_value().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void generator_t::print_set(const std::set<item_t> &set) {
|
||||||
|
for (const item_t &item : set)
|
||||||
|
print_item(item);
|
||||||
|
}
|
||||||
|
|
||||||
generator_t::generator_t(const std::set<item_t> &rules0) {
|
generator_t::generator_t(const std::set<item_t> &rules0) {
|
||||||
for (item_t rule : rules0) {
|
for (item_t rule : rules0) {
|
||||||
rules.emplace(rule.get_lhs(), rule);
|
rules.emplace(rule.get_lhs(), rule);
|
||||||
|
@ -39,6 +100,10 @@ generator_t::generator_t(const std::set<item_t> &rules0) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::set<item_t> set0 = get_set("");
|
||||||
|
close_set(&set0);
|
||||||
|
|
||||||
|
print_set(set0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,12 @@ private:
|
||||||
std::multimap<std::string, item_t> rules;
|
std::multimap<std::string, item_t> rules;
|
||||||
std::multimap<symbol_t, item_t> items;
|
std::multimap<symbol_t, item_t> items;
|
||||||
|
|
||||||
|
void close_set(std::set<item_t> *set);
|
||||||
|
std::set<item_t> get_set(const std::string &nonterm);
|
||||||
|
|
||||||
|
void print_item(const item_t &item);
|
||||||
|
void print_set(const std::set<item_t> &set);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
generator_t(const std::set<item_t> &rules0);
|
generator_t(const std::set<item_t> &rules0);
|
||||||
};
|
};
|
||||||
|
|
|
@ -69,7 +69,7 @@ struct item_t : public std::tuple<std::string, std::vector<symbol_t>, unsigned>
|
||||||
get_point()++;
|
get_point()++;
|
||||||
}
|
}
|
||||||
|
|
||||||
symbol_t get_next_symbol() const {
|
const symbol_t & get_next_symbol() const {
|
||||||
return get_rhs()[get_point()];
|
return get_rhs()[get_point()];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Reference in a new issue