Completely refactor code generation
This commit is contained in:
parent
bb018683c9
commit
6c8cd11dad
18 changed files with 1057 additions and 707 deletions
|
@ -1,11 +1,14 @@
|
||||||
add_executable(solar
|
add_executable(solar
|
||||||
|
codegen.cpp
|
||||||
generator.cpp
|
generator.cpp
|
||||||
generator_lr0.cpp
|
generator_lr0.cpp
|
||||||
generator_slr.cpp
|
generator_slr.cpp
|
||||||
lex.cpp
|
lex.cpp
|
||||||
output.cpp
|
output_common.cpp
|
||||||
output_lr0.cpp
|
output_header.cpp
|
||||||
output_slr.cpp
|
output_slr.cpp
|
||||||
|
output_source.cpp
|
||||||
|
output_source_slr.cpp
|
||||||
parse.cpp
|
parse.cpp
|
||||||
solar.cpp
|
solar.cpp
|
||||||
)
|
)
|
||||||
|
|
46
src/codegen.cpp
Normal file
46
src/codegen.cpp
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
219
src/codegen.hpp
Normal file
219
src/codegen.hpp
Normal file
|
@ -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:");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
344
src/output.cpp
344
src/output.cpp
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
88
src/output_common.cpp
Normal file
88
src/output_common.cpp
Normal file
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
95
src/output_common.hpp
Normal file
95
src/output_common.hpp
Normal file
|
@ -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);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
85
src/output_header.cpp
Normal file
85
src/output_header.cpp
Normal file
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
48
src/output_header.hpp
Normal file
48
src/output_header.hpp
Normal file
|
@ -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();
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
|
@ -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");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -24,139 +24,21 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "output_header.hpp"
|
||||||
#include "output_slr.hpp"
|
#include "output_slr.hpp"
|
||||||
|
#include "output_source_slr.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace solar {
|
namespace solar {
|
||||||
|
|
||||||
void output_slr_t::emit_state_shift(unsigned state) {
|
void output_slr(const generator_slr_t *generator, const char *source, const char *header) {
|
||||||
std::map<unsigned, std::set<symbol_t>> shifts;
|
output_common_t common(generator, "parse_", "TOK_");
|
||||||
|
|
||||||
for (const symbol_t &token : generator->get_terminals()) {
|
output_source_slr_t output_source(common, source, header);
|
||||||
auto it = generator->get_shifts().find(std::make_pair(state, token));
|
output_source.write();
|
||||||
if (it == generator->get_shifts().end())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
std::set<symbol_t> &symbols = shifts.insert(std::make_pair(it->second, std::set<symbol_t>())).first->second;
|
output_header_t output_header(common, header);
|
||||||
symbols.insert(token);
|
output_header.write();
|
||||||
}
|
|
||||||
|
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,32 +27,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "generator_slr.hpp"
|
#include "generator_slr.hpp"
|
||||||
#include "output.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace solar {
|
namespace solar {
|
||||||
|
|
||||||
class output_slr_t : public output_t {
|
void output_slr(const generator_slr_t *generator, const char *source, const char *header);
|
||||||
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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
234
src/output_source.cpp
Normal file
234
src/output_source.cpp
Normal file
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -26,61 +26,52 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "generator.hpp"
|
#include "codegen.hpp"
|
||||||
|
#include "output_common.hpp"
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
|
|
||||||
namespace solar {
|
namespace solar {
|
||||||
|
|
||||||
class output_t {
|
class output_source_t : protected codegen_t, protected output_common_t {
|
||||||
protected:
|
private:
|
||||||
std::string prefix_str;
|
const char *header_filename;
|
||||||
std::string token_prefix_str;
|
|
||||||
unsigned stack_size;
|
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> tokens;
|
||||||
std::map<std::string, unsigned> nonterms;
|
|
||||||
|
|
||||||
std::map<symbol_t, std::string> symbol_values;
|
std::map<symbol_t, std::string> symbol_values;
|
||||||
|
|
||||||
const char * prefix() const {
|
|
||||||
return prefix_str.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char * token_prefix() const {
|
void emit_header_include();
|
||||||
return token_prefix_str.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
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_alloc();
|
||||||
void emit_token_value();
|
void emit_free();
|
||||||
void emit_header();
|
|
||||||
|
|
||||||
|
function_t sig_reduction(unsigned rule_id);
|
||||||
void emit_reduction(unsigned rule_id);
|
void emit_reduction(unsigned rule_id);
|
||||||
void emit_reductions();
|
void emit_reductions();
|
||||||
void emit_gotos(const std::string &lhs);
|
|
||||||
void emit_states();
|
void emit_states();
|
||||||
void emit_header_include();
|
void emit_do_push();
|
||||||
void emit_source();
|
void emit_push();
|
||||||
|
|
||||||
void initialize();
|
|
||||||
|
|
||||||
virtual const generator_t * get_generator() = 0;
|
|
||||||
virtual void emit_state(unsigned state) = 0;
|
virtual void emit_state(unsigned state) = 0;
|
||||||
|
|
||||||
output_t(const char *header, const char *source);
|
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:
|
public:
|
||||||
virtual ~output_t();
|
|
||||||
|
|
||||||
void write();
|
void write();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
};
|
151
src/output_source_slr.cpp
Normal file
151
src/output_source_slr.cpp
Normal file
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -26,29 +26,28 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "generator_lr0.hpp"
|
#include "generator_slr.hpp"
|
||||||
#include "output.hpp"
|
#include "output_source.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace solar {
|
namespace solar {
|
||||||
|
|
||||||
class output_lr0_t : public output_t {
|
class output_source_slr_t : public output_source_t {
|
||||||
private:
|
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_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);
|
virtual void emit_state(unsigned state);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
output_lr0_t(const generator_lr0_t *generator0, const char *header, const char *source) : output_t(header, source), generator(generator0) {
|
output_source_slr_t(const output_common_t &common, const char *source, const char *header) : output_source_t(common, source, header) {
|
||||||
initialize();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,12 +24,12 @@ static inline void free_rhs(rhs_t *v) {
|
||||||
|
|
||||||
typedef union parse_symbol_value {
|
typedef union parse_symbol_value {
|
||||||
parse_token_value_t token;
|
parse_token_value_t token;
|
||||||
std::string * symbol_action;
|
std::string *symbol_action;
|
||||||
rhs_t * symbol_rhs;
|
rhs_t *symbol_rhs;
|
||||||
solar::rule_t * symbol_rule;
|
solar::rule_t *symbol_rule;
|
||||||
solar::symbol_t * symbol_symbol;
|
solar::symbol_t *symbol_symbol;
|
||||||
solar::symbol_t * symbol_term;
|
solar::symbol_t *symbol_term;
|
||||||
std::string * symbol_varname;
|
std::string *symbol_varname;
|
||||||
} parse_symbol_value_t;
|
} parse_symbol_value_t;
|
||||||
|
|
||||||
typedef struct parse_context_state {
|
typedef struct parse_context_state {
|
||||||
|
@ -39,7 +39,7 @@ typedef struct parse_context_state {
|
||||||
|
|
||||||
struct parse_context {
|
struct parse_context {
|
||||||
unsigned top;
|
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);
|
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));
|
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)));
|
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));
|
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;
|
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;
|
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));
|
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()) {
|
if (grammar->rules.empty()) {
|
||||||
solar::item_t init("");
|
solar::item_t init("");
|
||||||
init.get_rhs().push_back(solar::symbol_t::make_nonterm(rule->item.get_lhs().c_str()));
|
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);
|
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->first.push_back(*sym);
|
||||||
rhs->second.emplace_back();
|
rhs->second.emplace_back();
|
||||||
|
|
||||||
return rhs;
|
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->first.push_back(*sym);
|
||||||
rhs->second.emplace_back(*var, true);
|
rhs->second.emplace_back(*var, true);
|
||||||
|
|
||||||
return rhs;
|
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->first.push_back(*sym);
|
||||||
rhs->second.emplace_back(*var, false);
|
rhs->second.emplace_back(*var, false);
|
||||||
|
|
||||||
return rhs;
|
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) {
|
for (char c : *str) {
|
||||||
rhs->first.push_back(solar::symbol_t::make_char(c));
|
rhs->first.push_back(solar::symbol_t::make_char(c));
|
||||||
rhs->second.emplace_back();
|
rhs->second.emplace_back();
|
||||||
|
@ -122,27 +123,28 @@ static inline rhs_t * parse_reduce_15(rhs_t * rhs, std::string * str, __attribut
|
||||||
return rhs;
|
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;
|
parse_symbol_value_t result;
|
||||||
|
|
||||||
while (1) {
|
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);
|
int ret = parse_do_push(parser, token, grammar);
|
||||||
|
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
|
|
||||||
#include "grammar.hpp"
|
#include "grammar.hpp"
|
||||||
|
|
||||||
enum parse_token_t {
|
|
||||||
|
typedef enum parse_token {
|
||||||
TOK_BLOCK = 256,
|
TOK_BLOCK = 256,
|
||||||
TOK_CHAR = 257,
|
TOK_CHAR = 257,
|
||||||
TOK_SQBLOCK = 258,
|
TOK_SQBLOCK = 258,
|
||||||
|
@ -11,11 +12,11 @@ enum parse_token_t {
|
||||||
TOK_SYMBOL = 260,
|
TOK_SYMBOL = 260,
|
||||||
TOK_SYMBOL_LC = 261,
|
TOK_SYMBOL_LC = 261,
|
||||||
TOK_SYMBOL_UC = 262,
|
TOK_SYMBOL_UC = 262,
|
||||||
};
|
} parse_token_t;
|
||||||
|
|
||||||
typedef struct parse_token_value {
|
typedef struct parse_token_value {
|
||||||
char c;
|
char c;
|
||||||
std::string * str;
|
std::string *str;
|
||||||
} parse_token_value_t;
|
} parse_token_value_t;
|
||||||
|
|
||||||
typedef struct parse_context parse_context_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));
|
parse_context_t * parse_alloc(void *(*alloc_func)(size_t));
|
||||||
void parse_free(parse_context_t *parser, void (*free_func)(void *));
|
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);
|
||||||
|
|
|
@ -89,9 +89,7 @@ int main(int argc, char *argv[]) {
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
generator_slr_t generator(grammar);
|
generator_slr_t generator(grammar);
|
||||||
|
output_slr(&generator, argv[2], argv[3]);
|
||||||
output_slr_t output(&generator, argv[3], argv[2]);
|
|
||||||
output.write();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue