diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2015-04-16 22:07:29 +0200 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2015-04-17 17:20:25 +0200 |
commit | 6c8cd11dad10587e5dde9ab7706384927b961bb6 (patch) | |
tree | 83df2371191ee2dea8ba2154ef538b91d38089ed /src/output_source_slr.cpp | |
parent | bb018683c93673679bb54b63c8aff43f507948de (diff) | |
download | solar-6c8cd11dad10587e5dde9ab7706384927b961bb6.tar solar-6c8cd11dad10587e5dde9ab7706384927b961bb6.zip |
Completely refactor code generation
Diffstat (limited to 'src/output_source_slr.cpp')
-rw-r--r-- | src/output_source_slr.cpp | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/src/output_source_slr.cpp b/src/output_source_slr.cpp new file mode 100644 index 0000000..4c82922 --- /dev/null +++ b/src/output_source_slr.cpp @@ -0,0 +1,151 @@ +/* + Copyright (c) 2015, Matthias Schiffer <mschiffer@universe-factory.net> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "output_source_slr.hpp" + + +namespace solar { + +void output_source_slr_t::emit_state_shift(unsigned state) { + std::map<unsigned, std::set<symbol_t>> shifts; + + for (const symbol_t &token : get_generator()->get_terminals()) { + auto it = get_generator()->get_shifts().find(std::make_pair(state, token)); + if (it == get_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) + write_case(symbol_case(sym)); + + write_line_("parser->stack[++parser->top].state = ", entry.first); + write_line_("return 1"); + write_line(); + } +} + +void output_source_slr_t::emit_state_reduce_code(const item_t &item, unsigned rule_id) { + const auto &rhs = item.get_rhs(); + const std::string &type = get_generator()->get_grammar().get_nonterm_type(item.get_lhs()); + const auto &vars = get_generator()->get_grammar().rules[rule_id].variables; + + function_t reduce_func("", prefixed(combine("reduce_", rule_id))); + + for (unsigned i = 0; i < vars.size(); i++) { + if (vars[i].first.empty()) + continue; + + reduce_func.add_arg("", combine("parser->stack[parser->top + ", i, "].value.", symbol_value(rhs[i]))); + } + + for (const auto &arg : get_generator()->get_grammar().extra_args) + reduce_func.add_arg(arg); + + if (type.empty()) + write_line_(call(reduce_func)); + else + write_line_("result.symbol_", item.get_lhs(), " = ", call(reduce_func)); + + for (unsigned i = 0; i < vars.size(); i++) { + if (!vars[i].second) + continue; + + auto it = get_generator()->get_grammar().destructors.find(rhs[i]); + if (it == get_generator()->get_grammar().destructors.end()) + continue; + + write_line_(it->second, "(parser->stack[parser->top + ", i, "].value.", symbol_value(rhs[i]), ")"); + } + + if (!type.empty()) + write_line_("parser->stack[parser->top].value.symbol_", item.get_lhs(), " = result.symbol_", item.get_lhs()); +} + +bool output_source_slr_t::emit_state_reduce(unsigned state) { + std::map<unsigned, std::set<symbol_t>> reductions; + + for (const symbol_t &token : get_generator()->get_terminals()) { + auto it = get_generator()->get_reductions().find(std::make_pair(state, token)); + if (it == get_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) { + write_default(); + } + else { + for (const symbol_t &sym : entry.second) + write_case(symbol_case(sym)); + } + + const rule_t &rule = get_generator()->get_grammar().rules[entry.first]; + + if (rule.item.get_rhs().size()) + write_line_("parser->top -= ", rule.item.get_rhs().size()); + + if (!rule.action.empty()) + emit_state_reduce_code(rule.item, entry.first); + + emit_gotos(rule.item.get_lhs()); + + if (reductions.size() != 1) { + write_line_("break"); + write_line(); + } + + } + + return (reductions.size() == 1); +} + +void output_source_slr_t::emit_state(unsigned state) { + block_t switch_token(this, "switch (token)"); + + if (get_generator()->get_shifts().find(std::make_pair(state, symbol_t::make_nonterm(""))) != get_generator()->get_shifts().end()) { + write_case(0); + write_line_("return 0"); + write_line(); + } + + emit_state_shift(state); + + bool def = emit_state_reduce(state); + + if (!def) { + write_default(); + write_line_("return -1"); + } +} + +} |