summaryrefslogtreecommitdiffstats
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
parentbb018683c93673679bb54b63c8aff43f507948de (diff)
downloadsolar-6c8cd11dad10587e5dde9ab7706384927b961bb6.tar
solar-6c8cd11dad10587e5dde9ab7706384927b961bb6.zip
Completely refactor code generation
-rw-r--r--src/CMakeLists.txt7
-rw-r--r--src/codegen.cpp46
-rw-r--r--src/codegen.hpp219
-rw-r--r--src/output.cpp344
-rw-r--r--src/output_common.cpp88
-rw-r--r--src/output_common.hpp95
-rw-r--r--src/output_header.cpp85
-rw-r--r--src/output_header.hpp48
-rw-r--r--src/output_lr0.cpp126
-rw-r--r--src/output_slr.cpp134
-rw-r--r--src/output_slr.hpp24
-rw-r--r--src/output_source.cpp234
-rw-r--r--src/output_source.hpp (renamed from src/output.hpp)59
-rw-r--r--src/output_source_slr.cpp151
-rw-r--r--src/output_source_slr.hpp (renamed from src/output_lr0.hpp)21
-rw-r--r--src/parse.cpp66
-rw-r--r--src/parse.hpp9
-rw-r--r--src/solar.cpp4
18 files changed, 1055 insertions, 705 deletions
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 <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 "codegen.hpp"
+
+#include <cerrno>
+#include <system_error>
+
+
+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 <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.
+*/
+
+
+#pragma once
+
+#include <cstdio>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <vector>
+
+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<std::string, std::string> &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<variable_t> args;
+
+ void add_arg(const std::pair<std::string, std::string> &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<typename... Args> void open_block(Args ...args) {
+ write_line(args..., " {");
+ level++;
+ }
+
+ template<typename... Args> 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<variable_t> &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<typename T> 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<typename T, typename... Args> 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<typename... Args> 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<typename... Args> 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<typename... Args> block_t(codegen_t *codegen0, Args ...args) : codegen(codegen0) {
+ codegen->open_block(args...);
+ }
+
+ template<typename... Args> void close(Args ...args) {
+ close_string = combine(args...);
+ }
+
+ template<typename... Args> void close_(Args ...args) {
+ close(args..., ";");
+ }
+
+ ~block_t() {
+ codegen->close_block(close_string);
+ }
+ };
+
+ codegen_t(const char *filename);
+ ~codegen_t();
+
+ template<typename... Args> static std::string combine(Args ...args) {
+ std::ostringstream s;
+ handle_args(&s, false, args...);
+ return s.str();
+ }
+
+ template<typename... Args> static std::string call(Args ...args) {
+ std::ostringstream s;
+ handle_args(&s, true, args...);
+ return s.str();
+ }
+
+ template<typename... Args> void write_line(Args ...args) {
+ write_line_offset(0, args...);
+ }
+
+ template<typename... Args> void write_line_(Args ...args) {
+ write_line(args..., ";");
+ }
+
+ template<typename... Args> void _write_line(Args ...args) {
+ write_line_offset(1, args...);
+ }
+
+ template<typename... Args> void _write_line_(Args ...args) {
+ write_line_offset(1, args..., ";");
+ }
+
+ template<typename... Args> void write_case(Args ...args) {
+ write_line_offset(-1, "case ", args..., ":");
+ }
+
+ template<typename... Args> 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 <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();
-}
-
-}
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 <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_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 <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.
+*/
+
+
+#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<std::string, unsigned> tokens;
+ std::map<symbol_t, std::string> 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<std::string, unsigned> & 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 <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_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<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)
+ 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 <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.
+*/
+
+
+#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 <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_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_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<unsigned, std::set<symbol_t>> 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<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)
- 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<unsigned, std::set<symbol_t>> 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<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) {
- 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 <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.hpp"
+
+#include <cstring>
+
+
+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<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) {
+ 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.hpp b/src/output_source.hpp
index a685ec1..9571295 100644
--- a/src/output.hpp
+++ b/src/output_source.hpp
@@ -26,61 +26,52 @@
#pragma once
-#include "generator.hpp"
-
-#include <cstdio>
+#include "codegen.hpp"
+#include "output_common.hpp"
namespace solar {
-class output_t {
-protected:
- std::string prefix_str;
- std::string token_prefix_str;
+class output_source_t : protected codegen_t, protected output_common_t {
+private:
+ const char *header_filename;
unsigned stack_size;
- std::string header_filename;
-
- std::FILE *header_file;
- std::FILE *source_file;
-
std::map<std::string, unsigned> tokens;
- std::map<std::string, unsigned> nonterms;
-
std::map<symbol_t, std::string> symbol_values;
- const char * prefix() const {
- return prefix_str.c_str();
- }
- const char * token_prefix() const {
- return token_prefix_str.c_str();
- }
+ void emit_header_include();
- std::string symbol_case(const symbol_t &sym);
+ void emit_type_symbol_value();
+ void emit_type_context_state();
+ void emit_type_context();
+ void emit_types();
- void emit_tokens();
- void emit_token_value();
- void emit_header();
+ void emit_alloc();
+ void emit_free();
+ function_t sig_reduction(unsigned rule_id);
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();
+ void emit_states();
+ void emit_do_push();
+ void emit_push();
- virtual const generator_t * get_generator() = 0;
virtual void emit_state(unsigned state) = 0;
- output_t(const char *header, const char *source);
+protected:
+ void emit_gotos(const std::string &lhs);
-public:
- virtual ~output_t();
+ 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 <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");
+ }
+}
+
+}
diff --git a/src/output_lr0.hpp b/src/output_source_slr.hpp
index dd95318..b25f532 100644
--- a/src/output_lr0.hpp
+++ b/src/output_source_slr.hpp
@@ -26,29 +26,28 @@
#pragma once
-#include "generator_lr0.hpp"
-#include "output.hpp"
+#include "generator_slr.hpp"
+#include "output_source.hpp"
namespace solar {
-class output_lr0_t : public output_t {
+class output_source_slr_t : public output_source_t {
private:
- const generator_lr0_t *generator;
+ const generator_slr_t * get_generator() {
+ return dynamic_cast<const generator_slr_t *>(output_common_t::get_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;
- }
+ 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_lr0_t(const generator_lr0_t *generator0, const char *header, const char *source) : output_t(header, source), generator(generator0) {
- initialize();
+ 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;
}