diff options
Diffstat (limited to 'src/output.cpp')
-rw-r--r-- | src/output.cpp | 344 |
1 files changed, 0 insertions, 344 deletions
diff --git a/src/output.cpp b/src/output.cpp deleted file mode 100644 index 6a54f71..0000000 --- a/src/output.cpp +++ /dev/null @@ -1,344 +0,0 @@ -/* - 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.hpp" - -#include <cerrno> -#include <cstring> -#include <system_error> - - -namespace solar { - -output_t::output_t(const char *header, const char *source) - : prefix_str("parse_"), - token_prefix_str("TOK_"), - stack_size(100), - header_filename(header) { - header_file = std::fopen(header, "w"); - if (!header_file) - throw std::system_error(errno, std::generic_category(), "unable to open header output file for writing"); - - source_file = std::fopen(source, "w"); - if (!source_file) - throw std::system_error(errno, std::generic_category(), "unable to open source output file for writing"); -} - -output_t::~output_t() { - std::fclose(header_file); - std::fclose(source_file); -} - -void output_t::initialize() { - for (const std::string &nonterm : get_generator()->get_nonterminals()) - symbol_values.insert(std::make_pair(symbol_t::make_nonterm(nonterm.c_str()), "symbol_" + nonterm)); - - for (const symbol_t &term : get_generator()->get_terminals()) { - if (term.get_type() == SYMBOL_TYPE_TERM) - tokens.insert(std::make_pair(term.get_value(), tokens.size())); - - symbol_values.insert(std::make_pair(term, "token." + get_generator()->get_grammar().get_term_type(term).second)); - } -} - -std::string output_t::symbol_case(const symbol_t &sym) { - if (sym.get_type() == SYMBOL_TYPE_CHAR) { - switch (sym.get_value()[0]) { - case '\a': - return "'\\a'"; - - case '\b': - return "'\\b'"; - - case '\f': - return "'\\f'"; - - case '\n': - return "'\\n'"; - - case '\r': - return "'\\r'"; - - case '\t': - return "'\\t'"; - - case '\v': - return "'\\v'"; - - case '\\': - return "'\\\\'"; - - case '\'': - return "'\\''"; - - default: - return "'" + sym.get_value() + "'"; - } - } - else { - if (sym.get_value().empty()) - return "0"; - else - return token_prefix_str + sym.get_value(); - } -} - -void output_t::emit_tokens() { - if (tokens.empty()) - return; - - std::fprintf(header_file, "enum %stoken_t {\n", prefix()); - - for (const auto &token : tokens) - std::fprintf(header_file, "\t%s%s = %u,\n", token_prefix(), token.first.c_str(), token.second + 256); - - std::fprintf(header_file, "};\n\n"); -} - -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 symbol_t &term : get_generator()->get_terminals()) { - const auto &type = get_generator()->get_grammar().get_term_type(term); - if (!type.first.empty()) - token_values.insert(std::make_pair(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()); -} - -void output_t::emit_header() { - std::fprintf(header_file, "#pragma once\n\n"); - - if (!get_generator()->get_grammar().header_block.empty()) - std::fprintf(header_file, "%s\n", get_generator()->get_grammar().header_block.c_str()); - - emit_tokens(); - emit_token_value(); - - std::fprintf(header_file, "typedef struct %scontext %scontext_t;\n\n", prefix(), prefix()); - - std::fprintf(header_file, "%scontext_t * %salloc(void *(*alloc_func)(size_t));\n", prefix(), prefix()); - std::fprintf(header_file, "void %sfree(%scontext_t *parser, void (*free_func)(void *));\n\n", prefix(), prefix()); - - std::fprintf(header_file, "int %spush(%scontext_t *parser, int token, const %stoken_value_t *value", prefix(), prefix(), prefix()); - - for (const auto &arg : get_generator()->get_grammar().extra_args) - std::fprintf(header_file, ", %s %s", arg.first.c_str(), arg.second.c_str()); - - std::fprintf(header_file, ");\n"); -} - -void output_t::emit_reduction(unsigned rule_id) { - const rule_t &rule = get_generator()->get_grammar().rules[rule_id]; - - std::fprintf(source_file, "static inline "); - - const item_t &item = rule.item; - const std::string &type = get_generator()->get_grammar().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 < rule.variables.size(); i++) { - const auto &var = rule.variables[i]; - - if (var.first.empty()) - continue; - - if (!empty) - std::fprintf(source_file, ", "); - - std::fprintf(source_file, "%s %s", get_generator()->get_grammar().get_type(item.get_rhs()[i]).c_str(), var.first.c_str()); - - empty = false; - } - - for (const auto &arg : get_generator()->get_grammar().extra_args) { - if (!empty) - std::fprintf(source_file, ", "); - - std::fprintf(source_file, "%s %s", arg.first.c_str(), arg.second.c_str()); - - empty = false; - } - - if (empty) - std::fprintf(source_file, "void"); - - std::fprintf(source_file, ") {"); - std::fprintf(source_file, "%s", rule.action.c_str()); - std::fprintf(source_file, "}\n\n"); - -} - -void output_t::emit_reductions() { - const auto &rules = get_generator()->get_grammar().rules; - - for (size_t i = 0; i < rules.size(); i++) { - if (!rules[i].action.empty()) - emit_reduction(i); - } -} - -void output_t::emit_gotos(const std::string &lhs) { - std::map<unsigned, std::set<unsigned>> gotos; - - for (size_t state = 0; state < get_generator()->get_state_count(); state++) { - auto it = get_generator()->get_gotos().find(std::make_pair(state, lhs)); - if (it == get_generator()->get_gotos().end()) - continue; - - std::set<unsigned> &states = gotos.insert(std::make_pair(it->second, std::set<unsigned>())).first->second; - states.insert(state); - } - - if (gotos.size() == 1) { - auto it = gotos.begin(); - std::fprintf(source_file, "\t\t\t\tparser->stack[++parser->top].state = %u;\n", it->first); - } - else { - std::fprintf(source_file, "\t\t\t\tswitch (parser->stack[parser->top].state) {\n"); - - for (const auto &entry : gotos) { - for (unsigned state : entry.second) - std::fprintf(source_file, "\t\t\t\tcase %u:\n", state); - std::fprintf(source_file, "\t\t\t\t\tparser->stack[++parser->top].state = %u;\n", entry.first); - std::fprintf(source_file, "\t\t\t\t\tbreak;\n\n"); - } - - std::fprintf(source_file, "\t\t\t\t}\n"); - } -} - -void output_t::emit_states() { - for (size_t state = 0; state < get_generator()->get_state_count(); state++) - emit_state(state); -} - -void output_t::emit_header_include() { -#ifdef _WIN32 - const char sep = '\\'; -#else - const char sep = '/'; -#endif - - const char *slash = std::strrchr(header_filename.c_str(), sep); - const char *basename = slash ? slash+1 : header_filename.c_str(); - - std::fprintf(source_file, "#include \"%s\"\n\n", basename); -} - -void output_t::emit_source() { - emit_header_include(); - - if (!get_generator()->get_grammar().source_block.empty()) - std::fprintf(source_file, "%s\n\n", get_generator()->get_grammar().source_block.c_str()); - - 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 : get_generator()->get_nonterminals()) { - const std::string &type = get_generator()->get_grammar().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()); - std::fprintf(source_file, "\tunsigned top;\n"); - std::fprintf(source_file, "\t%scontext_state_t stack[%u];\n", prefix(), stack_size); - std::fprintf(source_file, "};\n\n\n"); - - std::fprintf(source_file, "%scontext_t * %salloc(void *(*alloc_func)(size_t)) {\n", prefix(), prefix()); - std::fprintf(source_file, "\t%scontext_t *parser = (%scontext_t *)alloc_func(sizeof(%scontext_t));\n", prefix(), prefix(), prefix()); - std::fprintf(source_file, "\tparser->top = 0;\n"); - std::fprintf(source_file, "\tparser->stack[0].state = 0;\n"); - std::fprintf(source_file, "\treturn parser;\n"); - std::fprintf(source_file, "}\n\n"); - - std::fprintf(source_file, "void %sfree(%scontext_t *parser, void (*free_func)(void *)) {\n", prefix(), prefix()); - std::fprintf(source_file, "\tfree_func(parser);\n"); - std::fprintf(source_file, "}\n\n"); - - emit_reductions(); - - std::fprintf(source_file, "static int %sdo_push(%scontext_t *parser, int token", prefix(), prefix()); - for (const auto &arg : get_generator()->get_grammar().extra_args) - std::fprintf(source_file, ", %s %s", arg.first.c_str(), arg.second.c_str()); - std::fprintf(source_file, ") {\n"); - - std::fprintf(source_file, "\t%ssymbol_value_t result;\n\n", prefix()); - - std::fprintf(source_file, "\twhile (1) {\n"); - std::fprintf(source_file, "\t\tswitch (parser->stack[parser->top].state) {\n"); - - emit_states(); - - std::fprintf(source_file, "\t\t}\n"); - std::fprintf(source_file, "\t}\n"); - std::fprintf(source_file, "}\n\n"); - - std::fprintf(source_file, "int %spush(%scontext_t *parser, int token, const %stoken_value_t *value", prefix(), prefix(), prefix()); - for (const auto &arg : get_generator()->get_grammar().extra_args) - std::fprintf(source_file, ", %s %s", arg.first.c_str(), arg.second.c_str()); - std::fprintf(source_file, ") {\n"); - - std::fprintf(source_file, "\tint ret = %sdo_push(parser, token", prefix()); - for (const auto &arg : get_generator()->get_grammar().extra_args) - std::fprintf(source_file, ", %s", arg.second.c_str()); - std::fprintf(source_file, ");\n\n"); - - std::fprintf(source_file, "\tif (ret > 0)\n"); - std::fprintf(source_file, "\t\tparser->stack[parser->top-1].value.token = *value;\n\n"); - - std::fprintf(source_file, "\treturn ret;\n"); - - std::fprintf(source_file, "}\n"); -} - -void output_t::write() { - emit_header(); - emit_source(); -} - -} |