output_slr: collapse duplicate case branches

This commit is contained in:
Matthias Schiffer 2015-04-10 22:51:51 +02:00
parent 0e9b564f8c
commit c2728e4c83
3 changed files with 181 additions and 838 deletions

View file

@ -33,20 +33,29 @@
namespace solar {
void output_slr_t::emit_state_shift(unsigned state, const symbol_t &token) {
void output_slr_t::emit_state_shift(unsigned state) {
std::map<unsigned, std::set<symbol_t>> shifts;
for (const symbol_t &token : generator->get_terminals()) {
auto it = generator->get_shifts().find(std::make_pair(state, token));
if (it == generator->get_shifts().end())
return;
continue;
std::fprintf(source_file, "\t\t\tcase %s:\n", symbol_case(token).c_str());
std::fprintf(source_file, "\t\t\t\tparser->stack[parser->top].value.token = *value;\n");
std::fprintf(source_file, "\t\t\t\tparser->stack[++parser->top].state = %u;\n", unsigned(it->second));
std::fprintf(source_file, "\t\t\t\treturn 1;\n\n");
std::set<symbol_t> &symbols = shifts.insert(std::make_pair(it->second, std::set<symbol_t>())).first->second;
symbols.insert(token);
}
void output_slr_t::emit_state_reduce(const item_t &item, const symbol_t &token, int rule_id) {
std::fprintf(source_file, "\t\t\tcase %s:\n", symbol_case(token).c_str());
for (const auto &entry : shifts) {
for (const symbol_t &sym : entry.second)
std::fprintf(source_file, "\t\t\tcase %s:\n", symbol_case(sym).c_str());
std::fprintf(source_file, "\t\t\t\tparser->stack[parser->top].value.token = *value;\n");
std::fprintf(source_file, "\t\t\t\tparser->stack[++parser->top].state = %u;\n", entry.first);
std::fprintf(source_file, "\t\t\t\treturn 1;\n\n");
}
}
void output_slr_t::emit_state_reduce_code(const item_t &item, int rule_id) {
const auto &rhs = item.get_rhs();
if (rhs.size())
std::fprintf(source_file, "\t\t\t\tparser->top -= %u;\n", unsigned(rhs.size()));
@ -114,19 +123,38 @@ void output_slr_t::emit_state_reduce(const item_t &item, const symbol_t &token,
std::fprintf(source_file, "\t\t\t\t}\n");
}
std::fprintf(source_file, "\t\t\t\tbreak;\n\n");
}
void output_slr_t::do_emit_state(unsigned state, const symbol_t &token) {
bool output_slr_t::emit_state_reduce(unsigned state) {
std::map<unsigned, std::set<symbol_t>> reductions;
for (const symbol_t &token : generator->get_terminals()) {
auto it = generator->get_reductions().find(std::make_pair(state, token));
if (it == generator->get_reductions().end()) {
emit_state_shift(state, token);
if (it == generator->get_reductions().end())
continue;
std::set<symbol_t> &symbols = reductions.insert(std::make_pair(it->second, std::set<symbol_t>())).first->second;
symbols.insert(token);
}
for (const auto &entry : reductions) {
if (reductions.size() == 1) {
std::fprintf(source_file, "\t\t\tdefault:\n");
}
else {
const rule_t &rule = generator->get_grammar().rules[it->second];
emit_state_reduce(rule.item, token, rule.action.empty() ? -1 : it->second);
for (const symbol_t &sym : entry.second)
std::fprintf(source_file, "\t\t\tcase %s:\n", symbol_case(sym).c_str());
}
const rule_t &rule = generator->get_grammar().rules[entry.first];
emit_state_reduce_code(rule.item, rule.action.empty() ? -1 : entry.first);
if (reductions.size() != 1)
std::fprintf(source_file, "\t\t\t\tbreak;\n\n");
}
return (reductions.size() == 1);
}
void output_slr_t::emit_state(unsigned state) {
@ -138,13 +166,14 @@ void output_slr_t::emit_state(unsigned state) {
std::fprintf(source_file, "\t\t\t\treturn 0;\n\n");
}
do_emit_state(state, symbol_t::empty());
emit_state_shift(state);
for (const symbol_t &token : generator->get_terminals())
do_emit_state(state, token);
bool def = emit_state_reduce(state);
if (!def) {
std::fprintf(source_file, "\t\t\tdefault:\n");
std::fprintf(source_file, "\t\t\t\treturn -1;\n");
}
std::fprintf(source_file, "\t\t\t}\n");
std::fprintf(source_file, "\t\t\tbreak;\n\n");

View file

@ -36,9 +36,11 @@ class output_slr_t : public output_t {
private:
const generator_slr_t *generator;
void emit_state_shift(unsigned state, const symbol_t &token);
void emit_state_reduce(const item_t &item, const symbol_t &token, int rule_id);
void do_emit_state(unsigned state, const symbol_t &token);
void emit_state_shift(unsigned state);
void emit_state_reduce_code(const item_t &item, int rule_id);
bool emit_state_reduce(unsigned state);
protected:
virtual const generator_t * get_generator() {

File diff suppressed because it is too large Load diff