From 6c8cd11dad10587e5dde9ab7706384927b961bb6 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Thu, 16 Apr 2015 22:07:29 +0200 Subject: Completely refactor code generation --- src/CMakeLists.txt | 7 +- src/codegen.cpp | 46 +++++++ src/codegen.hpp | 219 +++++++++++++++++++++++++++++ src/output.cpp | 344 ---------------------------------------------- src/output.hpp | 86 ------------ src/output_common.cpp | 88 ++++++++++++ src/output_common.hpp | 95 +++++++++++++ src/output_header.cpp | 85 ++++++++++++ src/output_header.hpp | 48 +++++++ src/output_lr0.cpp | 126 ----------------- src/output_lr0.hpp | 55 -------- src/output_slr.cpp | 134 ++---------------- src/output_slr.hpp | 24 +--- src/output_source.cpp | 234 +++++++++++++++++++++++++++++++ src/output_source.hpp | 77 +++++++++++ src/output_source_slr.cpp | 151 ++++++++++++++++++++ src/output_source_slr.hpp | 54 ++++++++ src/parse.cpp | 66 ++++----- src/parse.hpp | 9 +- src/solar.cpp | 4 +- 20 files changed, 1151 insertions(+), 801 deletions(-) create mode 100644 src/codegen.cpp create mode 100644 src/codegen.hpp delete mode 100644 src/output.cpp delete mode 100644 src/output.hpp create mode 100644 src/output_common.cpp create mode 100644 src/output_common.hpp create mode 100644 src/output_header.cpp create mode 100644 src/output_header.hpp delete mode 100644 src/output_lr0.cpp delete mode 100644 src/output_lr0.hpp create mode 100644 src/output_source.cpp create mode 100644 src/output_source.hpp create mode 100644 src/output_source_slr.cpp create mode 100644 src/output_source_slr.hpp (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 22c1ea6..a98260a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,11 +1,14 @@ add_executable(solar + codegen.cpp generator.cpp generator_lr0.cpp generator_slr.cpp lex.cpp - output.cpp - output_lr0.cpp + output_common.cpp + output_header.cpp output_slr.cpp + output_source.cpp + output_source_slr.cpp parse.cpp solar.cpp ) diff --git a/src/codegen.cpp b/src/codegen.cpp new file mode 100644 index 0000000..0c4c653 --- /dev/null +++ b/src/codegen.cpp @@ -0,0 +1,46 @@ +/* + Copyright (c) 2013-2015, Matthias Schiffer + 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 "codegen.hpp" + +#include +#include + + +namespace solar { + +codegen_t::codegen_t(const char *filename) : level(0) { + file = std::fopen(filename, "w"); + + if (!file) + throw std::system_error(errno, std::generic_category(), "unable to open output file `" + std::string(filename) + "' for writing"); +} + +codegen_t::~codegen_t() { + std::fclose(file); +} + +} diff --git a/src/codegen.hpp b/src/codegen.hpp new file mode 100644 index 0000000..7dbfd77 --- /dev/null +++ b/src/codegen.hpp @@ -0,0 +1,219 @@ +/* + Copyright (c) 2013-2015, Matthias Schiffer + 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. +*/ + + +#pragma once + +#include +#include +#include +#include +#include + +namespace solar { + +class nocopy_t { +private: + nocopy_t(const nocopy_t &o) = delete; + nocopy_t(nocopy_t &&o) = delete; + nocopy_t & operator=(const nocopy_t &o) = delete; + nocopy_t & operator=(nocopy_t &&o) = delete; + +protected: + nocopy_t() {} +}; + +class codegen_t : private nocopy_t { +public: + struct variable_t { + std::string str; + std::string name; + + + variable_t(const std::pair &value, bool func = false) : str(value.first), name(value.second) { + if (!func) { + char last = str[str.length()-1]; + if (last != '*' && last != '&') + str += ' '; + + str += name; + } + } + }; + + struct function_t { + variable_t type_name; + std::vector args; + + void add_arg(const std::pair &value, bool func = false) { + args.emplace_back(value, func); + } + + void add_arg(const std::string &str, const std::string &name, bool func = false) { + add_arg(std::make_pair(str, name), func); + } + + function_t(const std::string &type, const std::string &name) : type_name({type + ' ' + name, name}, true) {} + }; + +private: + FILE *file; + unsigned level; + + + template void open_block(Args ...args) { + write_line(args..., " {"); + level++; + } + + template void close_block(Args ...args) { + level--; + write_line("}", args...); + } + + + static void handle_arg(std::ostringstream *s, bool is_call, const variable_t &var) { + if (is_call) + *s << var.name; + else + *s << var.str; + } + + static void handle_arg(std::ostringstream *s, bool is_call, const std::vector &vars) { + bool first = true; + for (const variable_t &var : vars) { + if (!first) + *s << ", "; + + handle_arg(s, is_call, var); + first = false; + } + } + + static void handle_arg(std::ostringstream *s, bool is_call, const function_t &f) { + handle_arg(s, is_call, f.type_name); + + *s << "("; + + if (f.args.empty() && !is_call) + *s << "void"; + else + handle_arg(s, is_call, f.args); + + *s << ")"; + } + + template static void handle_arg(std::ostringstream *s, __attribute__((unused)) bool is_call, T arg) { + *s << arg; + } + + static void handle_args(__attribute__((unused)) std::ostringstream *s, __attribute__((unused)) bool is_call) { + } + + template static void handle_args(std::ostringstream *s, bool is_call, T arg, Args ...args) { + handle_arg(s, is_call, arg); + handle_args(s, is_call, args...); + } + + template void write_offset(int offset, Args ...args) { + for (int i = 0; i < int(level) + offset; i++) + std::fputc('\t', file); + + std::fputs(combine(args...).c_str(), file); + } + + void write_line_offset(__attribute__((unused)) int offset) { + std::fputs("\n", file); + } + + template void write_line_offset(int offset, Args ...args) { + write_offset(offset, args..., "\n"); + } + +public: + class block_t : private nocopy_t { + private: + codegen_t *codegen; + std::string close_string; + + public: + template block_t(codegen_t *codegen0, Args ...args) : codegen(codegen0) { + codegen->open_block(args...); + } + + template void close(Args ...args) { + close_string = combine(args...); + } + + template void close_(Args ...args) { + close(args..., ";"); + } + + ~block_t() { + codegen->close_block(close_string); + } + }; + + codegen_t(const char *filename); + ~codegen_t(); + + template static std::string combine(Args ...args) { + std::ostringstream s; + handle_args(&s, false, args...); + return s.str(); + } + + template static std::string call(Args ...args) { + std::ostringstream s; + handle_args(&s, true, args...); + return s.str(); + } + + template void write_line(Args ...args) { + write_line_offset(0, args...); + } + + template void write_line_(Args ...args) { + write_line(args..., ";"); + } + + template void _write_line(Args ...args) { + write_line_offset(1, args...); + } + + template void _write_line_(Args ...args) { + write_line_offset(1, args..., ";"); + } + + template void write_case(Args ...args) { + write_line_offset(-1, "case ", args..., ":"); + } + + template void write_default() { + write_line_offset(-1, "default:"); + } +}; + +} 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 - 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 -#include -#include - - -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 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> 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 &states = gotos.insert(std::make_pair(it->second, std::set())).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(); -} - -} diff --git a/src/output.hpp b/src/output.hpp deleted file mode 100644 index a685ec1..0000000 --- a/src/output.hpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - Copyright (c) 2015, Matthias Schiffer - 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. -*/ - - -#pragma once - -#include "generator.hpp" - -#include - - -namespace solar { - -class output_t { -protected: - std::string prefix_str; - std::string token_prefix_str; - unsigned stack_size; - - std::string header_filename; - - std::FILE *header_file; - std::FILE *source_file; - - std::map tokens; - std::map nonterms; - - std::map symbol_values; - - const char * prefix() const { - return prefix_str.c_str(); - } - - const char * token_prefix() const { - return token_prefix_str.c_str(); - } - - std::string symbol_case(const symbol_t &sym); - - void emit_tokens(); - void emit_token_value(); - void emit_header(); - - void emit_reduction(unsigned rule_id); - void emit_reductions(); - void emit_gotos(const std::string &lhs); - void emit_states(); - void emit_header_include(); - void emit_source(); - - void initialize(); - - virtual const generator_t * get_generator() = 0; - virtual void emit_state(unsigned state) = 0; - - output_t(const char *header, const char *source); - -public: - virtual ~output_t(); - - void write(); -}; - -} diff --git a/src/output_common.cpp b/src/output_common.cpp new file mode 100644 index 0000000..a0ed757 --- /dev/null +++ b/src/output_common.cpp @@ -0,0 +1,88 @@ +/* + Copyright (c) 2015, Matthias Schiffer + 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_common.hpp" + + +namespace solar { + +output_common_t::output_common_t(const generator_t *generator0, const std::string &prefix0, const std::string &token_prefix0) : + generator(generator0), prefix(prefix0), token_prefix(token_prefix0) { + for (const std::string &nonterm : generator->get_nonterminals()) + symbol_values.insert(std::make_pair(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.insert(std::make_pair(token_prefix + term.get_value(), tokens.size())); + + symbol_values.insert(std::make_pair(term, "token." + generator->get_grammar().get_term_type(term).second)); + } + +} + +std::string output_common_t::symbol_case(const symbol_t &sym) const { + 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 + sym.get_value(); + } +} + +} diff --git a/src/output_common.hpp b/src/output_common.hpp new file mode 100644 index 0000000..bbab97b --- /dev/null +++ b/src/output_common.hpp @@ -0,0 +1,95 @@ +/* + Copyright (c) 2015, Matthias Schiffer + 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. +*/ + + +#pragma once + +#include "generator.hpp" +#include "codegen.hpp" + + +namespace solar { + +class output_common_t { +private: + const generator_t *generator; + + std::string prefix; + std::string token_prefix; + + std::map tokens; + std::map symbol_values; + +protected: + std::string prefixed(const std::string &str) const { + return (prefix + str); + } + + std::string symbol_case(const symbol_t &sym) const; + + std::string symbol_value(const symbol_t &sym) const { + return symbol_values.at(sym); + } + + const generator_t * get_generator() const { + return generator; + } + + const std::map & get_tokens() const { + return tokens; + } + + codegen_t::function_t sig_alloc() const { + codegen_t::function_t sig(prefixed("context_t *"), prefixed("alloc")); + sig.add_arg("void *(*alloc_func)(size_t)", "alloc_func", true); + + return sig; + } + + codegen_t::function_t sig_free() const { + codegen_t::function_t sig("void", prefixed("free")); + sig.add_arg(prefixed("context_t *"), "parser"); + sig.add_arg("void (*free_func)(void *)", "free_func", true); + + return sig; + } + + codegen_t::function_t sig_push() const { + codegen_t::function_t sig("int", prefixed("push")); + sig.add_arg(prefixed("context_t *"), "parser"); + sig.add_arg("int", "token"); + sig.add_arg("const " + prefixed("token_value_t *"), "value"); + + for (const auto &arg : generator->get_grammar().extra_args) + sig.add_arg(arg); + + return sig; + } + +public: + output_common_t(const generator_t *generator0, const std::string &prefix0, const std::string &token_prefix0); +}; + +} diff --git a/src/output_header.cpp b/src/output_header.cpp new file mode 100644 index 0000000..a99369c --- /dev/null +++ b/src/output_header.cpp @@ -0,0 +1,85 @@ +/* + Copyright (c) 2015, Matthias Schiffer + 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_header.hpp" + + +namespace solar { + +void output_header_t::emit_tokens() { + if (get_tokens().empty()) + return; + + block_t token(this, "typedef enum ", prefixed("token")); + + for (const auto &token : get_tokens()) + write_line(token.first.c_str(), " = ", token.second + 256, ","); + + token.close_(" ", prefixed("token_t")); +} + +void output_header_t::emit_token_value() { + block_t token_value(this, "typedef struct ", prefixed("token_value")); + + std::map 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) + write_line_(variable_t({value.second.c_str(), value.first.c_str()})); + + token_value.close_(" ", prefixed("token_value_t")); +} + +void output_header_t::write() { + write_line("#pragma once"); + write_line(); + + if (!get_generator()->get_grammar().header_block.empty()) { + write_line(get_generator()->get_grammar().header_block); + write_line(); + } + + emit_tokens(); + write_line(); + + emit_token_value(); + write_line(); + + write_line_("typedef struct ", prefixed("context"), " ", prefixed("context_t")); + write_line(); + + write_line_(sig_alloc()); + write_line_(sig_free()); + write_line(); + write_line_(sig_push()); +} + +}; diff --git a/src/output_header.hpp b/src/output_header.hpp new file mode 100644 index 0000000..119a6c8 --- /dev/null +++ b/src/output_header.hpp @@ -0,0 +1,48 @@ +/* + Copyright (c) 2015, Matthias Schiffer + 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. +*/ + + +#pragma once + +#include "codegen.hpp" +#include "output_common.hpp" + + +namespace solar { + +class output_header_t : protected codegen_t, protected output_common_t { +private: + void emit_tokens(); + void emit_token_value(); + +public: + output_header_t(const output_common_t &common, const char *header) : + codegen_t(header), + output_common_t(common) {} + + void write(); +}; + +}; diff --git a/src/output_lr0.cpp b/src/output_lr0.cpp deleted file mode 100644 index b492744..0000000 --- a/src/output_lr0.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - Copyright (c) 2015, Matthias Schiffer - 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_lr0.hpp" - - -namespace solar { - -void output_lr0_t::emit_state_shift(unsigned state) { - std::fprintf(source_file, "\t\t\tswitch (token) {\n"); - - if (generator->get_shifts().find(std::make_pair(state, symbol_t::make_nonterm(""))) != generator->get_shifts().end()) { - std::fprintf(source_file, "\t\t\tcase 0:\n"); - std::fprintf(source_file, "\t\t\t\treturn 0;\n\n"); - } - - for (const auto &token : generator->get_terminals()) { - auto it = generator->get_shifts().find(std::make_pair(state, token)); - if (it == generator->get_shifts().end()) - continue; - - 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].state = %u;\n", unsigned(it->second)); - std::fprintf(source_file, "\t\t\t\treturn 1;\n\n"); - } - - 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"); -} - -void output_lr0_t::emit_state_reduce(const item_t &item, int rule_id) { - 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_grammar().get_nonterm_type(item.get_lhs()); - - std::fprintf(source_file, "\t\t\t"); - if (!type.empty()) - std::fprintf(source_file, "result.symbol_%s = ", item.get_lhs().c_str()); - std::fprintf(source_file, "%sreduce_%i(", prefix(), rule_id); - - bool empty = true; - const auto &vars = generator->get_grammar().rules[rule_id].variables; - for (unsigned i = 0; i < vars.size(); i++) { - if (vars[i].first.empty()) - continue; - - 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; - } - - for (const auto &arg : generator->get_grammar().extra_args) { - if (!empty) - std::fprintf(source_file, ", "); - - std::fprintf(source_file, "%s", arg.second.c_str()); - - empty = false; - } - - std::fprintf(source_file, ");\n"); - - for (unsigned i = 0; i < vars.size(); i++) { - if (!vars[i].second) - continue; - - auto it = generator->get_grammar().destructors.find(rhs[i]); - if (it == generator->get_grammar().destructors.end()) - continue; - - std::fprintf(source_file, "\t\t\t%s(parser->stack[parser->top + %u].value.%s);\n", it->second.c_str(), i, symbol_values[rhs[i]].c_str()); - } - - if (!type.empty()) - std::fprintf(source_file, "\t\t\tparser->stack[parser->top].value.symbol_%s = result.symbol_%s;\n", item.get_lhs().c_str(), item.get_lhs().c_str()); - } - - emit_gotos(item.get_lhs()); -} - -void output_lr0_t::emit_state(unsigned state) { - std::fprintf(source_file, "\t\tcase %u:\n", state); - - auto it = generator->get_reductions().find(state); - if (it == generator->get_reductions().end()) { - emit_state_shift(state); - } - else { - const rule_t &rule = generator->get_grammar().rules[it->second]; - emit_state_reduce(rule.item, rule.action.empty() ? -1 : it->second); - } - - std::fprintf(source_file, "\t\t\tbreak;\n\n"); -} - -} diff --git a/src/output_lr0.hpp b/src/output_lr0.hpp deleted file mode 100644 index dd95318..0000000 --- a/src/output_lr0.hpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - Copyright (c) 2015, Matthias Schiffer - 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. -*/ - - -#pragma once - -#include "generator_lr0.hpp" -#include "output.hpp" - - -namespace solar { - -class output_lr0_t : public output_t { -private: - const generator_lr0_t *generator; - - void emit_state_shift(unsigned state); - void emit_state_reduce(const item_t &item, int rule_id); - -protected: - virtual const generator_t * get_generator() { - return generator; - } - - virtual void emit_state(unsigned state); - -public: - output_lr0_t(const generator_lr0_t *generator0, const char *header, const char *source) : output_t(header, source), generator(generator0) { - initialize(); - } -}; - -} diff --git a/src/output_slr.cpp b/src/output_slr.cpp index 3c9e1c2..9be1adb 100644 --- a/src/output_slr.cpp +++ b/src/output_slr.cpp @@ -24,139 +24,21 @@ */ +#include "output_header.hpp" #include "output_slr.hpp" +#include "output_source_slr.hpp" namespace solar { -void output_slr_t::emit_state_shift(unsigned state) { - std::map> shifts; +void output_slr(const generator_slr_t *generator, const char *source, const char *header) { + output_common_t common(generator, "parse_", "TOK_"); - 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; + output_source_slr_t output_source(common, source, header); + output_source.write(); - std::set &symbols = shifts.insert(std::make_pair(it->second, std::set())).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].state = %u;\n", entry.first); - std::fprintf(source_file, "\t\t\t\treturn 1;\n\n"); - } -} - -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())); - - if (rule_id >= 0) { - const std::string &type = generator->get_grammar().get_nonterm_type(item.get_lhs()); - - std::fprintf(source_file, "\t\t\t\t"); - if (!type.empty()) - std::fprintf(source_file, "result.symbol_%s = ", item.get_lhs().c_str()); - std::fprintf(source_file, "%sreduce_%i(", prefix(), rule_id); - - bool empty = true; - const auto &vars = generator->get_grammar().rules[rule_id].variables; - for (unsigned i = 0; i < vars.size(); i++) { - if (vars[i].first.empty()) - continue; - - 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; - } - - for (const auto &arg : generator->get_grammar().extra_args) { - if (!empty) - std::fprintf(source_file, ", "); - - std::fprintf(source_file, "%s", arg.second.c_str()); - - empty = false; - } - - std::fprintf(source_file, ");\n"); - - for (unsigned i = 0; i < vars.size(); i++) { - if (!vars[i].second) - continue; - - auto it = generator->get_grammar().destructors.find(rhs[i]); - if (it == generator->get_grammar().destructors.end()) - continue; - - std::fprintf(source_file, "\t\t\t\t%s(parser->stack[parser->top + %u].value.%s);\n", it->second.c_str(), i, symbol_values[rhs[i]].c_str()); - } - - if (!type.empty()) - std::fprintf(source_file, "\t\t\t\tparser->stack[parser->top].value.symbol_%s = result.symbol_%s;\n", item.get_lhs().c_str(), item.get_lhs().c_str()); - } - - emit_gotos(item.get_lhs()); -} - -bool output_slr_t::emit_state_reduce(unsigned state) { - std::map> 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 &symbols = reductions.insert(std::make_pair(it->second, std::set())).first->second; - symbols.insert(token); - } - - 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) { - std::fprintf(source_file, "\t\tcase %u:\n", state); - std::fprintf(source_file, "\t\t\tswitch (token) {\n"); - - if (generator->get_shifts().find(std::make_pair(state, symbol_t::make_nonterm(""))) != generator->get_shifts().end()) { - std::fprintf(source_file, "\t\t\tcase 0:\n"); - std::fprintf(source_file, "\t\t\t\treturn 0;\n\n"); - } - - emit_state_shift(state); - - bool def = emit_state_reduce(state); - - 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"); + output_header_t output_header(common, header); + output_header.write(); } } diff --git a/src/output_slr.hpp b/src/output_slr.hpp index a64cecf..adc1f87 100644 --- a/src/output_slr.hpp +++ b/src/output_slr.hpp @@ -27,32 +27,10 @@ #pragma once #include "generator_slr.hpp" -#include "output.hpp" namespace solar { -class output_slr_t : public output_t { -private: - const generator_slr_t *generator; - - - 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() { - return generator; - } - - virtual void emit_state(unsigned state); - -public: - output_slr_t(const generator_slr_t *generator0, const char *header, const char *source) : output_t(header, source), generator(generator0) { - initialize(); - } -}; +void output_slr(const generator_slr_t *generator, const char *source, const char *header); } diff --git a/src/output_source.cpp b/src/output_source.cpp new file mode 100644 index 0000000..7000ef9 --- /dev/null +++ b/src/output_source.cpp @@ -0,0 +1,234 @@ +/* + Copyright (c) 2015, Matthias Schiffer + 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.hpp" + +#include + + +namespace solar { + +void output_source_t::emit_header_include() { +#ifdef _WIN32 + const char sep = '\\'; +#else + const char sep = '/'; +#endif + + const char *slash = std::strrchr(header_filename, sep); + const char *basename = slash ? slash+1 : header_filename; + + write_line("#include \"", basename, "\""); +} + +void output_source_t::emit_type_symbol_value() { + block_t symbol_value(this, "typedef union ", prefixed("symbol_value")); + + write_line_(variable_t({prefixed("token_value_t"), "token"})); + + for (const auto &nonterm : get_generator()->get_nonterminals()) { + const std::string &type = get_generator()->get_grammar().get_nonterm_type(nonterm); + + if (!type.empty()) + write_line_(variable_t({type, "symbol_" + nonterm})); + } + + symbol_value.close_(" ", prefixed("symbol_value_t")); +} + +void output_source_t::emit_type_context_state() { + block_t context_state(this, "typedef struct ", prefixed("context_state")); + + write_line_(variable_t({"unsigned", "state"})); + write_line_(variable_t({prefixed("symbol_value_t"), "value"})); + + context_state.close_(" ", prefixed("context_state_t")); +} + +void output_source_t::emit_type_context() { + block_t context(this, "struct ", prefixed("context")); + + write_line_(variable_t({"unsigned", "top"})); + write_line_(variable_t({prefixed("context_state_t"), combine("stack[", stack_size, "]")})); + + context.close_(); +} + +void output_source_t::emit_types() { + emit_type_symbol_value(); + write_line(); + + emit_type_context_state(); + write_line(); + + emit_type_context(); + write_line(); +} + +void output_source_t::emit_alloc() { + block_t alloc(this, sig_alloc()); + write_line_(prefixed("context_t *"), "parser = (", prefixed("context_t *"), ")alloc_func(sizeof(", prefixed("context_t"), "))"); + write_line_("parser->top = 0"); + write_line_("parser->stack[0].state = 0"); + write_line_("return parser"); +} + +void output_source_t::emit_free() { + block_t free_(this, sig_free()); + write_line_("free_func(parser)"); +} + +codegen_t::function_t output_source_t::sig_reduction(unsigned rule_id) { + const rule_t &rule = get_generator()->get_grammar().rules[rule_id]; + const item_t &item = rule.item; + const std::string &type = get_generator()->get_grammar().get_nonterm_type(item.get_lhs()); + + function_t sig("static inline " + (type.empty() ? "void" : type), prefixed(combine("reduce_", rule_id))); + + for (unsigned i = 0; i < rule.variables.size(); i++) { + const auto &var = rule.variables[i]; + + if (var.first.empty()) + continue; + + sig.add_arg(get_generator()->get_grammar().get_type(item.get_rhs()[i]), var.first); + } + + for (const auto &arg : get_generator()->get_grammar().extra_args) + sig.add_arg(arg); + + return sig; +} + +void output_source_t::emit_reduction(unsigned rule_id) { + function_t sig = sig_reduction(rule_id); + write_line(sig, " {", get_generator()->get_grammar().rules[rule_id].action, "}"); + write_line(); +} + +void output_source_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_source_t::emit_gotos(const std::string &lhs) { + std::map> 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 &states = gotos.insert(std::make_pair(it->second, std::set())).first->second; + states.insert(state); + } + + if (gotos.size() == 1) { + write_line_("parser->stack[++parser->top].state = ", gotos.begin()->first); + } + else { + block_t switch_state(this, "switch (parser->stack[parser->top].state)"); + + for (const auto &entry : gotos) { + for (unsigned state : entry.second) + write_case(state); + write_line_("parser->stack[++parser->top].state = ", entry.first); + write_line_("break"); + write_line(); + } + } +} + +void output_source_t::emit_states() { + for (size_t state = 0; state < get_generator()->get_state_count(); state++) { + write_case(state); + emit_state(state); + write_line_("break"); + write_line(); + } +} + +void output_source_t::emit_do_push() { + function_t do_push_sig("static int", prefixed("do_push")); + do_push_sig.add_arg(prefixed("context_t *"), "parser"); + do_push_sig.add_arg("int", "token"); + for (const auto &arg : get_generator()->get_grammar().extra_args) + do_push_sig.add_arg(arg); + + block_t do_push(this, do_push_sig); + + write_line_(prefixed("symbol_value_t"), " result"); + write_line(); + + block_t while_1(this, "while (1)"); + block_t switch_state(this, "switch (parser->stack[parser->top].state)"); + + emit_states(); +} + +void output_source_t::emit_push() { + block_t push(this, sig_push()); + write_line_("int ret = parse_do_push(parser, token, grammar)"); + write_line(); + write_line("if (ret > 0)"); + _write_line_("parser->stack[parser->top-1].value.token = *value"); + write_line(); + write_line_("return ret"); + +} + +void output_source_t::write() { + emit_header_include(); + write_line(); + + if (!get_generator()->get_grammar().source_block.empty()) { + write_line(get_generator()->get_grammar().source_block); + write_line(); + } + + emit_types(); + write_line(); + + emit_alloc(); + write_line(); + emit_free(); + write_line(); + write_line(); + + emit_reductions(); + write_line(); + + emit_do_push(); + write_line(); + + emit_push(); +} + +} diff --git a/src/output_source.hpp b/src/output_source.hpp new file mode 100644 index 0000000..9571295 --- /dev/null +++ b/src/output_source.hpp @@ -0,0 +1,77 @@ +/* + Copyright (c) 2015, Matthias Schiffer + 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. +*/ + + +#pragma once + +#include "codegen.hpp" +#include "output_common.hpp" + + +namespace solar { + +class output_source_t : protected codegen_t, protected output_common_t { +private: + const char *header_filename; + unsigned stack_size; + + std::map tokens; + std::map symbol_values; + + + void emit_header_include(); + + void emit_type_symbol_value(); + void emit_type_context_state(); + void emit_type_context(); + void emit_types(); + + void emit_alloc(); + void emit_free(); + + function_t sig_reduction(unsigned rule_id); + void emit_reduction(unsigned rule_id); + void emit_reductions(); + + void emit_states(); + void emit_do_push(); + void emit_push(); + + virtual void emit_state(unsigned state) = 0; + +protected: + void emit_gotos(const std::string &lhs); + + output_source_t(const output_common_t &common, const char *source, const char *header) : + codegen_t(source), + output_common_t(common), + header_filename(header), + stack_size(1024) {} + +public: + void write(); +}; + +}; 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 + 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> 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 &symbols = shifts.insert(std::make_pair(it->second, std::set())).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> 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 &symbols = reductions.insert(std::make_pair(it->second, std::set())).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"); + } +} + +} diff --git a/src/output_source_slr.hpp b/src/output_source_slr.hpp new file mode 100644 index 0000000..b25f532 --- /dev/null +++ b/src/output_source_slr.hpp @@ -0,0 +1,54 @@ +/* + Copyright (c) 2015, Matthias Schiffer + 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. +*/ + + +#pragma once + +#include "generator_slr.hpp" +#include "output_source.hpp" + + +namespace solar { + +class output_source_slr_t : public output_source_t { +private: + const generator_slr_t * get_generator() { + return dynamic_cast(output_common_t::get_generator()); + } + + void emit_state_shift(unsigned state); + + void emit_state_reduce_code(const item_t &item, unsigned rule_id); + bool emit_state_reduce(unsigned state); + +protected: + virtual void emit_state(unsigned state); + +public: + output_source_slr_t(const output_common_t &common, const char *source, const char *header) : output_source_t(common, source, header) { + } +}; + +} diff --git a/src/parse.cpp b/src/parse.cpp index e30615f..fe3a026 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -24,12 +24,12 @@ static inline void free_rhs(rhs_t *v) { typedef union parse_symbol_value { parse_token_value_t token; - std::string * symbol_action; - rhs_t * symbol_rhs; - solar::rule_t * symbol_rule; - solar::symbol_t * symbol_symbol; - solar::symbol_t * symbol_term; - std::string * symbol_varname; + std::string *symbol_action; + rhs_t *symbol_rhs; + solar::rule_t *symbol_rule; + solar::symbol_t *symbol_symbol; + solar::symbol_t *symbol_term; + std::string *symbol_varname; } parse_symbol_value_t; typedef struct parse_context_state { @@ -39,7 +39,7 @@ typedef struct parse_context_state { struct parse_context { unsigned top; - parse_context_state_t stack[100]; + parse_context_state_t stack[1024]; }; @@ -54,31 +54,32 @@ void parse_free(parse_context_t *parser, void (*free_func)(void *)) { free_func(parser); } -static inline void parse_reduce_3(std::string * nonterm, std::string * type, __attribute__((unused)) solar::grammar_t * grammar) { + +static inline void parse_reduce_3(std::string *nonterm, std::string *type, __attribute__((unused)) solar::grammar_t *grammar) { grammar->nonterm_types.insert(std::make_pair(*nonterm, *type)); } -static inline void parse_reduce_4(solar::symbol_t * term, std::string * type, std::string * name, __attribute__((unused)) solar::grammar_t * grammar) { +static inline void parse_reduce_4(solar::symbol_t *term, std::string *type, std::string *name, __attribute__((unused)) solar::grammar_t *grammar) { grammar->term_types.insert(std::make_pair(*term, std::make_pair(*type, *name))); } -static inline void parse_reduce_5(solar::symbol_t * sym, std::string * name, __attribute__((unused)) solar::grammar_t * grammar) { +static inline void parse_reduce_5(solar::symbol_t *sym, std::string *name, __attribute__((unused)) solar::grammar_t *grammar) { grammar->destructors.insert(std::make_pair(*sym, *name)); } -static inline void parse_reduce_6(std::string * block, __attribute__((unused)) solar::grammar_t * grammar) { +static inline void parse_reduce_6(std::string *block, __attribute__((unused)) solar::grammar_t *grammar) { grammar->source_block = *block; } -static inline void parse_reduce_7(std::string * block, __attribute__((unused)) solar::grammar_t * grammar) { +static inline void parse_reduce_7(std::string *block, __attribute__((unused)) solar::grammar_t *grammar) { grammar->header_block = *block; } -static inline void parse_reduce_8(std::string * type, std::string * name, __attribute__((unused)) solar::grammar_t * grammar) { +static inline void parse_reduce_8(std::string *type, std::string *name, __attribute__((unused)) solar::grammar_t *grammar) { grammar->extra_args.push_back(std::make_pair(*type, *name)); } -static inline void parse_reduce_9(solar::rule_t * rule, __attribute__((unused)) solar::grammar_t * grammar) { +static inline void parse_reduce_9(solar::rule_t *rule, __attribute__((unused)) solar::grammar_t *grammar) { if (grammar->rules.empty()) { solar::item_t init(""); init.get_rhs().push_back(solar::symbol_t::make_nonterm(rule->item.get_lhs().c_str())); @@ -88,32 +89,32 @@ static inline void parse_reduce_9(solar::rule_t * rule, __attribute__((unused)) grammar->rules.push_back(*rule); } -static inline solar::rule_t * parse_reduce_10(std::string * lhs, rhs_t * rhs, std::string * action, __attribute__((unused)) solar::grammar_t * grammar) {return new solar::rule_t {solar::item_t(*lhs, rhs->first), rhs->second, *action};} +static inline solar::rule_t * parse_reduce_10(std::string *lhs, rhs_t *rhs, std::string *action, __attribute__((unused)) solar::grammar_t *grammar) {return new solar::rule_t {solar::item_t(*lhs, rhs->first), rhs->second, *action};} -static inline rhs_t * parse_reduce_11(__attribute__((unused)) solar::grammar_t * grammar) {return new rhs_t();} +static inline rhs_t * parse_reduce_11(__attribute__((unused)) solar::grammar_t *grammar) {return new rhs_t();} -static inline rhs_t * parse_reduce_12(rhs_t * rhs, solar::symbol_t * sym, __attribute__((unused)) solar::grammar_t * grammar) { +static inline rhs_t * parse_reduce_12(rhs_t *rhs, solar::symbol_t *sym, __attribute__((unused)) solar::grammar_t *grammar) { rhs->first.push_back(*sym); rhs->second.emplace_back(); return rhs; } -static inline rhs_t * parse_reduce_13(rhs_t * rhs, solar::symbol_t * sym, std::string * var, __attribute__((unused)) solar::grammar_t * grammar) { +static inline rhs_t * parse_reduce_13(rhs_t *rhs, solar::symbol_t *sym, std::string *var, __attribute__((unused)) solar::grammar_t *grammar) { rhs->first.push_back(*sym); rhs->second.emplace_back(*var, true); return rhs; } -static inline rhs_t * parse_reduce_14(rhs_t * rhs, solar::symbol_t * sym, std::string * var, __attribute__((unused)) solar::grammar_t * grammar) { +static inline rhs_t * parse_reduce_14(rhs_t *rhs, solar::symbol_t *sym, std::string *var, __attribute__((unused)) solar::grammar_t *grammar) { rhs->first.push_back(*sym); rhs->second.emplace_back(*var, false); return rhs; } -static inline rhs_t * parse_reduce_15(rhs_t * rhs, std::string * str, __attribute__((unused)) solar::grammar_t * grammar) { +static inline rhs_t * parse_reduce_15(rhs_t *rhs, std::string *str, __attribute__((unused)) solar::grammar_t *grammar) { for (char c : *str) { rhs->first.push_back(solar::symbol_t::make_char(c)); rhs->second.emplace_back(); @@ -122,27 +123,28 @@ static inline rhs_t * parse_reduce_15(rhs_t * rhs, std::string * str, __attribut return rhs; } -static inline std::string * parse_reduce_16(__attribute__((unused)) solar::grammar_t * grammar) {return new std::string;} +static inline std::string * parse_reduce_16(__attribute__((unused)) solar::grammar_t *grammar) {return new std::string;} + +static inline std::string * parse_reduce_17(std::string *v, __attribute__((unused)) solar::grammar_t *grammar) {return v;} -static inline std::string * parse_reduce_17(std::string * v, __attribute__((unused)) solar::grammar_t * grammar) {return v;} +static inline std::string * parse_reduce_18(std::string *v, __attribute__((unused)) solar::grammar_t *grammar) {return new std::string("return " + *v + ";");} -static inline std::string * parse_reduce_18(std::string * v, __attribute__((unused)) solar::grammar_t * grammar) {return new std::string("return " + *v + ";");} +static inline solar::symbol_t * parse_reduce_19(std::string *v, __attribute__((unused)) solar::grammar_t *grammar) {return new solar::symbol_t(solar::symbol_t::make_nonterm(*v));} -static inline solar::symbol_t * parse_reduce_19(std::string * v, __attribute__((unused)) solar::grammar_t * grammar) {return new solar::symbol_t(solar::symbol_t::make_nonterm(*v));} +static inline solar::symbol_t * parse_reduce_20(solar::symbol_t *v, __attribute__((unused)) solar::grammar_t *grammar) {return v;} -static inline solar::symbol_t * parse_reduce_20(solar::symbol_t * v, __attribute__((unused)) solar::grammar_t * grammar) {return v;} +static inline solar::symbol_t * parse_reduce_21(std::string *v, __attribute__((unused)) solar::grammar_t *grammar) {return new solar::symbol_t(solar::symbol_t::make_term(*v));} -static inline solar::symbol_t * parse_reduce_21(std::string * v, __attribute__((unused)) solar::grammar_t * grammar) {return new solar::symbol_t(solar::symbol_t::make_term(*v));} +static inline solar::symbol_t * parse_reduce_22(char v, __attribute__((unused)) solar::grammar_t *grammar) {return new solar::symbol_t(solar::symbol_t::make_char(v));} -static inline solar::symbol_t * parse_reduce_22(char v, __attribute__((unused)) solar::grammar_t * grammar) {return new solar::symbol_t(solar::symbol_t::make_char(v));} +static inline std::string * parse_reduce_23(std::string *v, __attribute__((unused)) solar::grammar_t *grammar) {return v;} -static inline std::string * parse_reduce_23(std::string * v, __attribute__((unused)) solar::grammar_t * grammar) {return v;} +static inline std::string * parse_reduce_24(std::string *v, __attribute__((unused)) solar::grammar_t *grammar) {return v;} -static inline std::string * parse_reduce_24(std::string * v, __attribute__((unused)) solar::grammar_t * grammar) {return v;} +static inline std::string * parse_reduce_25(std::string *v, __attribute__((unused)) solar::grammar_t *grammar) {return v;} -static inline std::string * parse_reduce_25(std::string * v, __attribute__((unused)) solar::grammar_t * grammar) {return v;} -static int parse_do_push(parse_context_t *parser, int token, __attribute__((unused)) solar::grammar_t * grammar) { +static int parse_do_push(parse_context_t *parser, int token, __attribute__((unused)) solar::grammar_t *grammar) { parse_symbol_value_t result; while (1) { @@ -1163,7 +1165,7 @@ static int parse_do_push(parse_context_t *parser, int token, __attribute__((unus } } -int parse_push(parse_context_t *parser, int token, const parse_token_value_t *value, __attribute__((unused)) solar::grammar_t * grammar) { +int parse_push(parse_context_t *parser, int token, const parse_token_value_t *value, __attribute__((unused)) solar::grammar_t *grammar) { int ret = parse_do_push(parser, token, grammar); if (ret > 0) diff --git a/src/parse.hpp b/src/parse.hpp index a3ced3d..2d73755 100644 --- a/src/parse.hpp +++ b/src/parse.hpp @@ -3,7 +3,8 @@ #include "grammar.hpp" -enum parse_token_t { + +typedef enum parse_token { TOK_BLOCK = 256, TOK_CHAR = 257, TOK_SQBLOCK = 258, @@ -11,11 +12,11 @@ enum parse_token_t { TOK_SYMBOL = 260, TOK_SYMBOL_LC = 261, TOK_SYMBOL_UC = 262, -}; +} parse_token_t; typedef struct parse_token_value { char c; - std::string * str; + std::string *str; } parse_token_value_t; typedef struct parse_context parse_context_t; @@ -23,4 +24,4 @@ typedef struct parse_context parse_context_t; parse_context_t * parse_alloc(void *(*alloc_func)(size_t)); void parse_free(parse_context_t *parser, void (*free_func)(void *)); -int parse_push(parse_context_t *parser, int token, const parse_token_value_t *value, __attribute__((unused)) solar::grammar_t * grammar); +int parse_push(parse_context_t *parser, int token, const parse_token_value_t *value, __attribute__((unused)) solar::grammar_t *grammar); diff --git a/src/solar.cpp b/src/solar.cpp index c0491aa..ffb1871 100644 --- a/src/solar.cpp +++ b/src/solar.cpp @@ -89,9 +89,7 @@ int main(int argc, char *argv[]) { return 1; generator_slr_t generator(grammar); - - output_slr_t output(&generator, argv[3], argv[2]); - output.write(); + output_slr(&generator, argv[2], argv[3]); return 0; } -- cgit v1.2.3