output_slr: collapse duplicate case branches
This commit is contained in:
parent
0e9b564f8c
commit
c2728e4c83
3 changed files with 181 additions and 838 deletions
|
@ -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;
|
||||
void output_slr_t::emit_state_shift(unsigned state) {
|
||||
std::map<unsigned, std::set<symbol_t>> shifts;
|
||||
|
||||
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");
|
||||
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;
|
||||
|
||||
std::set<symbol_t> &symbols = shifts.insert(std::make_pair(it->second, std::set<symbol_t>())).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(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());
|
||||
|
||||
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<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())
|
||||
continue;
|
||||
|
||||
std::set<symbol_t> &symbols = reductions.insert(std::make_pair(it->second, std::set<symbol_t>())).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");
|
||||
|
|
|
@ -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() {
|
||||
|
|
932
src/parse.cpp
932
src/parse.cpp
File diff suppressed because it is too large
Load diff
Reference in a new issue