diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 7 | ||||
-rw-r--r-- | src/item.hpp | 80 | ||||
-rw-r--r-- | src/lex.cpp | 369 | ||||
-rw-r--r-- | src/lex.hpp | 102 | ||||
-rw-r--r-- | src/parser.cpp | 125 | ||||
-rw-r--r-- | src/parser.hpp | 58 | ||||
-rw-r--r-- | src/solar.cpp | 83 | ||||
-rw-r--r-- | src/state.cpp | 67 | ||||
-rw-r--r-- | src/state.hpp | 58 | ||||
-rw-r--r-- | src/symbol.hpp | 71 |
10 files changed, 1020 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..bb5e874 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,7 @@ +add_executable(solar + lex.cpp + parser.cpp + solar.cpp + state.cpp +) +set_target_properties(solar PROPERTIES COMPILE_FLAGS "-std=c++11 -Wall") diff --git a/src/item.hpp b/src/item.hpp new file mode 100644 index 0000000..58987b8 --- /dev/null +++ b/src/item.hpp @@ -0,0 +1,80 @@ +/* + 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 "symbol.hpp" + +#include <vector> + + +namespace solar { + +struct item_t : public std::tuple<std::string, std::vector<symbol_t>, unsigned> { + item_t(const std::string &lhs) + : std::tuple<std::string, std::vector<symbol_t>, unsigned>(lhs, std::vector<symbol_t>(), 0) {} + + const std::string & get_lhs() const { + return std::get<0>(*this); + } + + std::string & get_lhs() { + return std::get<0>(*this); + } + + const std::vector<symbol_t> & get_rhs() const { + return std::get<1>(*this); + } + + std::vector<symbol_t> & get_rhs() { + return std::get<1>(*this); + } + + unsigned get_point() const { + return std::get<2>(*this); + } + + unsigned & get_point() { + return std::get<2>(*this); + } + + bool can_shift() const { + return get_point() < get_rhs().size(); + } + + void shift() { + get_point()++; + } + + symbol_t get_next_symbol() const { + if (can_shift()) + return get_rhs()[get_point()]; + else + return symbol_t::make_end(); + } +}; + +} diff --git a/src/lex.cpp b/src/lex.cpp new file mode 100644 index 0000000..0587689 --- /dev/null +++ b/src/lex.cpp @@ -0,0 +1,369 @@ +/* + Copyright (c) 2013-2014, 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 "lex.hpp" + +#include <cstdlib> + + +#define array_size(array) (sizeof(array)/sizeof((array)[0])) + + +namespace solar { + + +struct keyword_t { + const char *keyword; + int token; +}; + +/* the keyword list must be sorted */ +static const keyword_t keywords[] = { +}; + +static int compare_keywords(const void *v1, const void *v2) { + const keyword_t *k1 = static_cast<const keyword_t*>(v1), *k2 = static_cast<const keyword_t*>(v2); + return std::strcmp(k1->keyword, k2->keyword); +} + + +bool lex_t::advance() { + if (start > 0) { + std::memmove(buffer, buffer+start, end - start); + end -= start; + start = 0; + } + + if (end == sizeof(buffer)) + return false; + + size_t l = std::fread(buffer+end, 1, sizeof(buffer) - end, file); + + end += l; + return l; +} + +bool lex_t::next(bool move) { + if (start + tok_len >= end) + return false; + + if (current() == '\n') { + loc.last_column = 0; + loc.last_line++; + } + else { + loc.last_column++; + } + + if (move) + start++; + else + tok_len++; + + + if (start + tok_len >= end) + return advance(); + + return true; +} + +void lex_t::consume(bool consume_needspace) { + start += tok_len; + tok_len = 0; + + needspace = consume_needspace; +} + +int lex_t::io_error(value_t *value) { + value->error = "I/O error"; + return -1; +} + +int lex_t::syntax_error(value_t *value) { + if (std::ferror(file)) + return io_error(value); + + value->error = "syntax error"; + return -1; +} + +int lex_t::consume_comment(value_t *value) { + char prev = 0; + + while (next(true)) { + if (prev == '*' && current() == '/') { + next(true); + consume(false); + return 0; + } + + prev = current(); + } + + if (std::ferror(file)) + return io_error(value); + + value->error = "unterminated block comment"; + return -1; +} + +/* +int lex_t::unterminated_string(value_t *value) { + if (ferror(file)) + return io_error(value); + + value->error = "unterminated string"; + return -1; +} + +int lex_t::lex_string(value_t *value) { + char *buf = NULL; + size_t len = 1024; + size_t pos = 0; + + if (needspace) + return syntax_error(value); + + buf = static_cast<char*>(std::malloc(len)); + + while (true) { + if (!next(true)) { + std::free(buf); + return unterminated_string(value); + } + + char cur = current(); + + if (cur == '"') + break; + + if (cur == '\\') { + if (!next(true)) { + free(buf); + return unterminated_string(value); + } + + cur = current(); + + if (cur == '\n') + continue; + } + + if (pos >= len) { + len *= 2; + buf = static_cast<char*>(std::realloc(buf, len)); + } + + buf[pos++] = cur; + } + + value->str = strndup(buf, pos); + std::free(buf); + + next(true); + consume(true); + + return TOK_STRING; + }*/ + +int lex_t::lex_number(value_t *value) { + if (needspace) + return syntax_error(value); + + while (next(false)) { + char cur = current(); + + if (cur >= '0' && cur <= '9') + continue; + + if (cur == 'x' || (cur >= 'a' && cur <= 'f') || (cur >= 'A' && cur <= 'F')) + continue; + + break; + } + + char *endptr, *token = get_token(); + value->number = std::strtoull(token, &endptr, 0); + + bool ok = !*endptr; + free(token); + + if (!ok) + return syntax_error(value); + + consume(true); + + return TOK_UINT; +} + +int lex_t::lex_keyword(value_t *value) { + if (needspace) + return syntax_error(value); + + while (next(false)) { + char cur = current(); + + if (!((cur >= 'a' && cur <= 'z') || (cur >= '0' && cur <= '9') || cur == '-')) + break; + } + + char *token = get_token(); + const keyword_t key = { .keyword = token, .token = 0 }; + const keyword_t *ret = static_cast<const keyword_t*>(bsearch(&key, keywords, array_size(keywords), sizeof(keyword_t), compare_keywords)); + free(token); + + if (!ret) + return syntax_error(value); + + consume(true); + + return ret->token; +} + +int lex_t::lex_symbol(value_t *value, bool terminal) { + if (needspace) + return syntax_error(value); + + while (next(false)) { + char cur = current(); + + switch (cur) { + case 'A' ... 'Z': + if (!terminal) + break; + + continue; + + case 'a' ... 'z': + if (terminal) + break; + + continue; + + case '0' ... '9': + case '_': + continue; + } + + break; + } + + value->str = get_token(); + return terminal ? TOK_TERM : TOK_NONTERM; +} + +int lex_t::lex(value_t *value) { + int token; + + while (end > start) { + loc.first_line = loc.last_line; + loc.first_column = loc.last_column+1; + + switch (current()) { + case ' ': + case '\n': + case '\t': + case '\r': + next(true); + consume(false); + continue; + + case ';': + case ':': + case '{': + case '}': + case '|': + case '=': + token = current(); + next(true); + consume(false); + return token; + + case '/': + if (!next(true)) + return syntax_error(value); + + if (current() == '*') { + token = consume_comment(value); + if (token) + return token; + + continue; + } + + if (current() != '/') + return syntax_error(value); + + ///* fall-through */ + //case '#': + while (next(true)) { + if (current() == '\n') + break; + } + + next(true); + consume(false); + continue; + + case '\'': + if (!next(true)) + return syntax_error(value); + + value->number = current(); + + if (!next(true) || current() != '\'') + return syntax_error(value); + + next(true); + + consume(false); + + return TOK_CHAR; + + //case '"': + //return lex_string(value); + + case '0' ... '9': + return lex_number(value); + + case 'a' ... 'z': + return lex_symbol(value, false); + + case 'A' ... 'Z': + return lex_symbol(value, true); + + default: + return syntax_error(value); + } + } + + if (ferror(file)) + return io_error(value); + + return 0; +} + +} diff --git a/src/lex.hpp b/src/lex.hpp new file mode 100644 index 0000000..8898d0b --- /dev/null +++ b/src/lex.hpp @@ -0,0 +1,102 @@ +/* + Copyright (c) 2013-2014, 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 "parser.hpp" + +#include <cstdio> +#include <cstring> + + +namespace solar { + +struct location_t { +public: + int first_line; + int first_column; + int last_line; + int last_column; + + location_t() : first_line(1), first_column(0), last_line(1), last_column(0) {} +}; + +class lex_t { +private: + location_t loc; + + std::FILE *file; + + bool needspace; + + size_t start; + size_t end; + size_t tok_len; + char buffer[65556]; + + + bool advance(); + bool next(bool move); + void consume(bool needspace); + + int io_error(value_t *value); + int syntax_error(value_t *value); + int consume_comment(value_t *value); + //int unterminated_string(value_t *value); + + int lex_string(value_t *value); + int lex_address(value_t *value); + int lex_float(value_t *value); + int lex_number(value_t *value); + int lex_keyword(value_t *value); + int lex_symbol(value_t *value, bool terminal); + + char current() { + return buffer[start + tok_len]; + } + + char * get_token() { + return strndup(buffer+start, tok_len); + } + + +public: + lex_t(FILE *file0) : file(file0), needspace(false), start(0), end(0), tok_len(0) { + advance(); + } + + ~lex_t() { + fclose(file); + } + + int lex(value_t *value); + + const location_t & get_location() const { + return loc; + } +}; + +} diff --git a/src/parser.cpp b/src/parser.cpp new file mode 100644 index 0000000..bd4dfbf --- /dev/null +++ b/src/parser.cpp @@ -0,0 +1,125 @@ +/* + 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 "parser.hpp" + +#include <cstdlib> + + +namespace solar { + +enum parser_state { + STATE_INIT, + STATE_RULE_BAR, + STATE_RULE_EQUAL, + STATE_RULE, +}; + +struct parser { + parser_state state; +}; + +parser_t * parser_alloc(void) { + parser_t *parser = (parser_t *)std::malloc(sizeof(parser_t)); + parser->state = STATE_INIT; + + return parser; +} + +int parser_push(parser_t *parser, int token, const value_t *value, state_t *state) { + switch (parser->state) { + case STATE_INIT: + switch (token) { + case TOK_NONTERM: + parser->state = STATE_RULE_BAR; + state->new_rule(value->str); + free(value->str); + return 1; + + case 0: + return 0; + } + + break; + + case STATE_RULE_BAR: + if (token == '|') { + parser->state = STATE_RULE_EQUAL; + return 1; + } + + break; + + case STATE_RULE_EQUAL: + if (token == '=') { + parser->state = STATE_RULE; + return 1; + } + + break; + + case STATE_RULE: + switch (token) { + case TOK_NONTERM: + state->add_rule_nonterminal(value->str); + free(value->str); + return 1; + + case TOK_TERM: + state->add_rule_terminal(value->str); + free(value->str); + return 1; + + case TOK_CHAR: + state->add_rule_terminal(value->number); + return 1; + + case TOK_BLOCK: + case ';': + state->add_rule(); + parser->state = STATE_INIT; + return 1; + } + + break; + } + + switch (token) { + case TOK_NONTERM: + case TOK_TERM: + case TOK_CHAR: + case TOK_BLOCK: + free(value->str);; + } + + return -1; +} + +void parser_free(parser_t *parser) { + std::free(parser); +} + +} diff --git a/src/parser.hpp b/src/parser.hpp new file mode 100644 index 0000000..c5a1e48 --- /dev/null +++ b/src/parser.hpp @@ -0,0 +1,58 @@ +/* + 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 "state.hpp" + +#include <cstdint> + + +namespace solar { + +enum token_t { + TOK_TERM = 1, + TOK_NONTERM, + TOK_BLOCK, + TOK_CHAR, + TOK_UINT, +}; + +typedef struct value { + char *str; + uint64_t number; + const char *error; +} value_t; + + +typedef struct parser parser_t; + + +parser_t * parser_alloc(void); +int parser_push(parser_t *parser, int token, const value_t *value, state_t *state); +void parser_free(parser_t *parser); + +} diff --git a/src/solar.cpp b/src/solar.cpp new file mode 100644 index 0000000..a5085a1 --- /dev/null +++ b/src/solar.cpp @@ -0,0 +1,83 @@ +/* + 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 "lex.hpp" +#include "parser.hpp" + +#include <cstdio> +#include <memory> + + +namespace solar { + +bool read_grammar(const char *filename, state_t *state) { + FILE *file = fopen(filename, "r"); + if (!file) { + std::fprintf(stderr, "unable to open file %s\n", filename); + return false; + } + + std::unique_ptr<lex_t> lexer(new lex_t(file)); + parser_t *parser = parser_alloc(); + int ret; + + do { + int token; + value_t value; + + token = lexer->lex(&value); + if (token < 0) { + std::fprintf(stderr, "error: %s at %s:%i:%i\n", value.error, filename, + lexer->get_location().first_line, lexer->get_location().first_column); + return false; + } + + ret = parser_push(parser, token, &value, state); + } while (ret > 0); + + if (ret < 0) { + std::fprintf(stderr, "error: parse error at %s:%i:%i\n", filename, + lexer->get_location().first_line, lexer->get_location().first_column); + return false; + } + + parser_free(parser); + + return true; +} + +} + + +int main() { + using namespace solar; + + state_t state; + if (!read_grammar("grammar.y", &state)) + return 1; + + return 0; +} diff --git a/src/state.cpp b/src/state.cpp new file mode 100644 index 0000000..e798dce --- /dev/null +++ b/src/state.cpp @@ -0,0 +1,67 @@ +/* + 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 "state.hpp" + + +namespace solar { + +void state_t::new_rule(const char *nonterm) { + if (rules.empty()) { + // start rule + current.get_rhs().emplace_back(symbol_t::make_nonterm(nonterm)); + add_rule(); + } + + current = item_t(nonterm); + +} + +void state_t::add_rule_nonterminal(const char *nonterm) { + current.get_rhs().emplace_back(symbol_t::make_nonterm(nonterm)); +} + +void state_t::add_rule_terminal(const char *term) { + current.get_rhs().emplace_back(symbol_t::make_term(term)); +} + +void state_t::add_rule_terminal(unsigned char term) { + current.get_rhs().emplace_back(symbol_t::make_char(term)); +} + +void state_t::add_rule() { + rules.emplace(current.get_lhs(), current); + + while (true) { + items.emplace(current.get_next_symbol(), current); + if (!current.can_shift()) + break; + + current.shift(); + } +} + +} diff --git a/src/state.hpp b/src/state.hpp new file mode 100644 index 0000000..8069ef0 --- /dev/null +++ b/src/state.hpp @@ -0,0 +1,58 @@ +/* + 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 "item.hpp" + +#include <map> +#include <utility> + + +namespace solar { + +class state_t { +private: + std::multimap<std::string, item_t> rules; + std::multimap<symbol_t, item_t> items; + + item_t current; + +public: + state_t() : current("") {} + + const std::multimap<std::string, item_t> & get_rules() const { + return rules; + } + + void new_rule(const char *nonterm); + void add_rule_nonterminal(const char *nonterm); + void add_rule_terminal(const char *term); + void add_rule_terminal(unsigned char term); + void add_rule(); +}; + +} diff --git a/src/symbol.hpp b/src/symbol.hpp new file mode 100644 index 0000000..31b006d --- /dev/null +++ b/src/symbol.hpp @@ -0,0 +1,71 @@ +/* + 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 <string> +#include <tuple> + + +namespace solar { + +enum symbol_type_t { + SYMBOL_TYPE_END, + SYMBOL_TYPE_NONTERM, + SYMBOL_TYPE_TERM, + SYMBOL_TYPE_CHAR, +}; + +struct symbol_t : public std::tuple<symbol_type_t, std::string> { + symbol_t(symbol_type_t type, const char *value) : std::tuple<symbol_type_t, std::string>(type, value) {} + + symbol_type_t get_type() const { + return std::get<0>(*this); + } + + const std::string & get_value() const { + return std::get<1>(*this); + } + + static symbol_t make_end() { + return symbol_t(SYMBOL_TYPE_END, ""); + } + + static symbol_t make_nonterm(const char *value) { + return symbol_t(SYMBOL_TYPE_NONTERM, value); + } + + static symbol_t make_term(const char *value) { + return symbol_t(SYMBOL_TYPE_TERM, value); + } + + static symbol_t make_char(unsigned char value) { + char v[2] = {char(value), 0}; + return symbol_t(SYMBOL_TYPE_CHAR, v); + } +}; + +} |