From c2728e4c835c6ae7db4d23ef60e5df3b9be3061a Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 10 Apr 2015 22:51:51 +0200 Subject: output_slr: collapse duplicate case branches --- src/output_slr.cpp | 81 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 55 insertions(+), 26 deletions(-) (limited to 'src/output_slr.cpp') diff --git a/src/output_slr.cpp b/src/output_slr.cpp index 01b0560..563fd60 100644 --- a/src/output_slr.cpp +++ b/src/output_slr.cpp @@ -33,20 +33,29 @@ namespace solar { -void output_slr_t::emit_state_shift(unsigned state, const symbol_t &token) { - auto it = generator->get_shifts().find(std::make_pair(state, token)); - if (it == generator->get_shifts().end()) - return; - - 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"); -} +void output_slr_t::emit_state_shift(unsigned state) { + std::map> 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()) + continue; -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()); + std::set &symbols = shifts.insert(std::make_pair(it->second, std::set())).first->second; + symbols.insert(token); + } + + 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) { - auto it = generator->get_reductions().find(std::make_pair(state, token)); - if (it == generator->get_reductions().end()) { - emit_state_shift(state, token); +bool output_slr_t::emit_state_reduce(unsigned state) { + std::map> 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()) + continue; + + std::set &symbols = reductions.insert(std::make_pair(it->second, std::set())).first->second; + symbols.insert(token); } - 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 auto &entry : reductions) { + if (reductions.size() == 1) { + std::fprintf(source_file, "\t\t\tdefault:\n"); + } + else { + 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); - std::fprintf(source_file, "\t\t\tdefault:\n"); - std::fprintf(source_file, "\t\t\t\treturn -1;\n"); + 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"); -- cgit v1.2.3