summaryrefslogtreecommitdiffstats
path: root/src/output.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/output.cpp')
-rw-r--r--src/output.cpp111
1 files changed, 98 insertions, 13 deletions
diff --git a/src/output.cpp b/src/output.cpp
index d4f86a9..7e9029b 100644
--- a/src/output.cpp
+++ b/src/output.cpp
@@ -45,9 +45,14 @@ output_t::output_t(const generator_t *generator0, const char *header, const char
if (!source_file)
throw std::system_error(errno, std::generic_category(), "unable to open source output file for writing");
- for (const auto &token : generator->get_terminals()) {
- if (token.get_type() == SYMBOL_TYPE_TERM)
- tokens.emplace(token.get_value(), tokens.size());
+ for (const std::string &nonterm : generator->get_nonterminals())
+ symbol_values.emplace(symbol_t::make_nonterm(nonterm.c_str()), "symbol_" + nonterm);
+
+ for (const symbol_t &term : generator->get_terminals()) {
+ if (term.get_type() == SYMBOL_TYPE_TERM)
+ tokens.emplace(term.get_value(), tokens.size());
+
+ symbol_values.emplace(term, "token." + generator->get_term_type(term).second);
}
}
@@ -65,6 +70,18 @@ void output_t::emit_tokens() {
void output_t::emit_token_value() {
std::fprintf(header_file, "typedef struct %stoken_value {\n", prefix());
+
+ std::map<std::string, std::string> token_values;
+
+ for (const auto &term : generator->get_terminals()) {
+ const auto &type = generator->get_term_type(term);
+ if (!type.first.empty())
+ token_values.emplace(type.second, type.first);
+ }
+
+ for (const auto &value : token_values)
+ std::fprintf(header_file, "\t%s %s;\n", value.second.c_str(), value.first.c_str());
+
std::fprintf(header_file, "} %stoken_value_t;\n\n", prefix());
}
@@ -75,9 +92,40 @@ void output_t::emit_header() {
std::fprintf(header_file, "typedef struct %scontext %scontext_t;\n", prefix(), prefix());
}
-void output_t::emit_reduction(unsigned rule_id, const std::string &action) {
- std::fprintf(source_file, "static inline void %sreduce_%u(void) {", prefix(), rule_id);
- std::fprintf(source_file, "%s", action.c_str());
+void output_t::emit_reduction(unsigned rule_id) {
+ const auto &rule = generator->get_rules()[rule_id];
+
+ std::fprintf(source_file, "static inline ");
+
+ const item_t &item = std::get<0>(rule);
+ const std::string &type = generator->get_nonterm_type(item.get_lhs());
+ if (type.empty())
+ std::fprintf(source_file, "void");
+ else
+ std::fprintf(source_file, "%s", type.c_str());
+
+ std::fprintf(source_file, " %sreduce_%u(", prefix(), rule_id);
+
+ bool empty = true;
+ for (unsigned i = 0; i < std::get<1>(rule).size(); i++) {
+ const std::string &var = std::get<1>(rule)[i];
+
+ if (var.empty())
+ continue;
+
+ if (!empty)
+ std::fprintf(source_file, ", ");
+
+ std::fprintf(source_file, "%s %s", generator->get_type(item.get_rhs()[i]).c_str(), var.c_str());
+
+ empty = false;
+ }
+
+ if (empty)
+ std::fprintf(source_file, "void");
+
+ std::fprintf(source_file, ") {");
+ std::fprintf(source_file, "%s", std::get<2>(rule).c_str());
std::fprintf(source_file, "}\n\n");
}
@@ -86,8 +134,8 @@ void output_t::emit_reductions() {
const auto &rules = generator->get_rules();
for (size_t i = 0; i < rules.size(); i++) {
- if (!rules[i].second.empty())
- emit_reduction(i, rules[i].second);
+ if (!std::get<2>(rules[i]).empty())
+ emit_reduction(i);
}
}
@@ -110,6 +158,7 @@ void output_t::emit_state_shift(unsigned i) {
std::fprintf(source_file, "\t\t\tcase %s%s:\n", token_prefix(), token.get_value().c_str());
std::fprintf(source_file, "\t\t\t\tparser->stack[++parser->top].state = %u;\n", unsigned(it->second));
+ std::fprintf(source_file, "\t\t\t\tparser->stack[parser->top].value.token = *value;\n");
std::fprintf(source_file, "\t\t\t\treturn 1;\n\n");
}
@@ -120,11 +169,34 @@ void output_t::emit_state_shift(unsigned i) {
}
void output_t::emit_state_reduce(const item_t &item, int rule_id) {
- if (item.get_rhs().size())
- std::fprintf(source_file, "\t\t\tparser->top -= %u;\n", unsigned(item.get_rhs().size()));
+ const auto &rhs = item.get_rhs();
+ if (rhs.size())
+ std::fprintf(source_file, "\t\t\tparser->top -= %u;\n", unsigned(rhs.size()));
+
+ if (rule_id >= 0) {
+ const std::string &type = generator->get_nonterm_type(item.get_lhs());
+
+ std::fprintf(source_file, "\t\t\t");
+ if (!type.empty())
+ std::fprintf(source_file, "parser->stack[parser->top].value.symbol_%s = ", item.get_lhs().c_str());
+ std::fprintf(source_file, "%sreduce_%i(", prefix(), rule_id);
+
+ bool empty = true;
+ const auto &vars = std::get<1>(generator->get_rules()[rule_id]);
+ for (unsigned i = 0; i < vars.size(); i++) {
+ const std::string &var = vars[i];
+ if (var.empty())
+ continue;
- if (rule_id >= 0)
- std::fprintf(source_file, "\t\t\t%sreduce_%i();\n", prefix(), rule_id);
+ if (!empty)
+ std::fprintf(source_file, ", ");
+
+ std::fprintf(source_file, "parser->stack[parser->top + %u].value.%s", i, symbol_values[rhs[i]].c_str());
+ empty = false;
+ }
+
+ std::fprintf(source_file, ");\n");
+ }
std::vector<std::pair<unsigned, unsigned>> gotos;
@@ -166,7 +238,7 @@ void output_t::emit_state(unsigned i) {
}
else {
const auto &rule = generator->get_rules()[it->second];
- emit_state_reduce(rule.first, rule.second.empty() ? -1 : it->second);
+ emit_state_reduce(std::get<0>(rule), std::get<2>(rule).empty() ? -1 : it->second);
}
std::fprintf(source_file, "\t\t\tbreak;\n\n");
@@ -178,8 +250,21 @@ void output_t::emit_states() {
}
void output_t::emit_source() {
+ std::fprintf(source_file, "typedef union %ssymbol_value {\n", prefix());
+ std::fprintf(source_file, "\t%stoken_value_t token;\n", prefix());
+
+ for (const auto &nonterm : generator->get_nonterminals()) {
+ const std::string &type = generator->get_nonterm_type(nonterm);
+
+ if (!type.empty())
+ std::fprintf(source_file, "\t%s symbol_%s;\n", type.c_str(), nonterm.c_str());
+ }
+
+ std::fprintf(source_file, "} %ssymbol_value_t;\n\n", prefix());
+
std::fprintf(source_file, "typedef struct %scontext_state {\n", prefix());
std::fprintf(source_file, "\tunsigned state;\n");
+ std::fprintf(source_file, "\t%ssymbol_value_t value;\n", prefix());
std::fprintf(source_file, "} %scontext_state_t;\n\n", prefix());
std::fprintf(source_file, "struct %scontext {\n", prefix());