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 <queue>
|
||||
|
||||
|
||||
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) {
|
||||
for (item_t rule : rules0) {
|
||||
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<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:
|
||||
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()++;
|
||||
}
|
||||
|
||||
symbol_t get_next_symbol() const {
|
||||
const symbol_t & get_next_symbol() const {
|
||||
return get_rhs()[get_point()];
|
||||
}
|
||||
};
|
||||
|
|
Reference in a new issue