summaryrefslogtreecommitdiffstats
path: root/src/output_source_slr.cpp
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2015-04-16 22:07:29 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2015-04-17 17:20:25 +0200
commit6c8cd11dad10587e5dde9ab7706384927b961bb6 (patch)
tree83df2371191ee2dea8ba2154ef538b91d38089ed /src/output_source_slr.cpp
parentbb018683c93673679bb54b63c8aff43f507948de (diff)
downloadsolar-6c8cd11dad10587e5dde9ab7706384927b961bb6.tar
solar-6c8cd11dad10587e5dde9ab7706384927b961bb6.zip
Completely refactor code generation
Diffstat (limited to 'src/output_source_slr.cpp')
-rw-r--r--src/output_source_slr.cpp151
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");
+ }
+}
+
+}